示例#1
0
        /// <summary>
        ///  Mirrors the MVC PersistentControllerActivator for the WebSharper
        ///  context.
        /// </summary>
        /// <typeparam name="M"></typeparam>
        /// <param name="viewModelAccessor">non-thread safe static reference to the ViewModel</param>
        /// <returns></returns>
        // [Remote] -> Yields "Remote methods must not be generic" from WebSharper:
        // https://github.com/dotnet-websharper/core/issues/1048
        public static M Load <M, V>(string viewState, out V viewModelAccessor, Storage?sessionStorage = null)
            where M : class, IStored <M>, new()
            where V : ViewModel <M>, new()
        {
            var storage   = sessionStorage ?? StorageImplementation.GetStorage(Configuration, HttpContext);
            var storageID = StorageImplementation.GetStorageID(typeof(M).Name);
            var getQuery  = RequestQuerySessionMiddleware.Query(HttpContext);

            // Implements StorageImplementation.ClearIfRequested(HttpContext, storage, storageID)
            // for WebSharper Ajax POST requests
            if (getQuery != null &&
                getQuery.TryGetValue("clear", out string getClear) &&
                bool.TryParse(getClear, out bool _) &&
                Once(OnceAction.Clear, storageID))
            {
                getQuery.TryGetValue("storage", out string getStorage);
                Enum.TryParse <Storage>(getStorage, true, out Storage clearStorage);
                StorageImplementation.Clear(HttpContext, clearStorage, storage, storageID);
            }

            V    viewModel;
            Guid sessionOverride;
            Guid session;

            byte[] bytes;
            Func <byte[], byte[]> filter;

            if (getQuery != null &&
                getQuery.TryGetValue("session", out string getSession) &&
                Guid.TryParse(getSession, out sessionOverride) &&
                Once(OnceAction.Load, storageID))
            {
                // ---------- Direct Load Database ----------
                viewModel       = new V();
                (bytes, filter) = StorageImplementation.DatabaseBytes(Configuration, HttpContext, storageID, sessionOverride);
                viewModel.Main  = (M)StorageImplementation.LoadFromBytes(() => new M(), bytes, filter);
            }
            else
            {
                // ---------- Load ViewState ----------
                if (storage == Storage.ViewState)
                {
                    viewModel           = new V();
                    filter              = StorageImplementation.DecryptViewState(Configuration);
                    viewModel.ViewState = viewState;
                    viewModel.DeserializeMain(filter);
                }

                // ---------- Load Session ----------
                else if (storage == Storage.Session)
                {
                    HttpContext.Session.TryGetValue(storageID, out bytes);
                    viewModel = new V();
                    viewModel.SetMain(StorageImplementation.LoadFromBytes(() => new M(), bytes));
                }

                // ---------- Load Database ----------
                else if (storage == Storage.Database)
                {
                    Guid.TryParse(HttpContext.Request.Cookies[storageID].FromCookieString()["session"], out session);
                    (bytes, filter) = StorageImplementation.DatabaseBytes(Configuration, HttpContext, storageID, session);
                    viewModel       = new V();
                    viewModel.SetMain(StorageImplementation.LoadFromBytes(() => new M(), bytes, filter));
                }
                else
                {
                    throw new NotImplementedException("Storage {0} not implemented");
                }
            }

            // Now that an instance is guaranteed remember the storage type for Save() and the client.
            viewModel.SessionStorage  = storage;
            viewModel.VSessionStorage = storage.ToString();

            // An instantiated Main is now guaranteed -> make its members
            // visible to WebSharper:
            viewModel.LoadMembers();

            // Include the ViewModel instance as member of the returned Main
            viewModel.Main.ViewModel = viewModel;

            // Set a reference to the ViewModel
            viewModelAccessor = viewModel;

            return(viewModel.Main);
        }
        /// <summary>
        /// Custom Controller factory method returning a serialized object if available.
        /// </summary>
        /// <param name="actionContext"></param>
        /// <returns></returns>
        public object Create(ControllerContext actionContext)
        {
            object controller         = null;
            var    controllerTypeInfo = actionContext.ActionDescriptor.ControllerTypeInfo;
            var    controllerType     = controllerTypeInfo.AsType();
            var    storageID          = StorageImplementation.GetStorageID(controllerTypeInfo.Name);
            var    sessionStorageID   = StorageImplementation.GetSessionStorageID(controllerTypeInfo.Name);

            var storage = StorageImplementation.GetStorage(this.Configuration, this.HttpContext, sessionStorageID);

            StorageImplementation.ClearIfRequested(this.HttpContext, storage, storageID);

            Guid sessionOverride;
            Guid session;

            byte[] bytes;
            Func <byte[], byte[]> filter = null;

            // ---------- Direct GET request ?session= from the Database ----------
            if (this.HttpContext.Request.Method == WebRequestMethods.Http.Get &&
                Guid.TryParse(this.HttpContext.Request.Query["session"], out sessionOverride))
            {
                using (var db = new ASP_DBEntities())
                {
                    (bytes, filter) = StorageImplementation.DatabaseBytes(Configuration, HttpContext, storageID, sessionOverride);
                    controller      = DeserializeController(actionContext, controllerTypeInfo, controllerType, bytes, filter);
                }
            }
            else
            {
                // ---------- Load from ViewState ----------
                if (storage == Storage.ViewState &&
                    this.HttpContext.Request.Method == WebRequestMethods.Http.Post &&
                    this.HttpContext.Request.Form.ContainsKey(storageID))
                {
                    // input type=hidden from <input viewstate="@ViewBag.ViewState" />
                    var controllerString = this.HttpContext.Request.Form[storageID];
                    if (!String.IsNullOrEmpty(controllerString))
                    {
                        (bytes, filter) = StorageImplementation.ViewStateBytes(this.Configuration, controllerString);
                        controller      = DeserializeController(actionContext, controllerTypeInfo, controllerType, bytes, filter);
                    }
                }

                // ---------- Load from Session ----------
                else if (storage == Storage.Session &&
                         this.HttpContext.Session.TryGetValue(storageID, out bytes))
                {
                    controller = DeserializeController(actionContext, controllerTypeInfo, controllerType, bytes);
                }

                // ---------- Load from Database ----------
                else if (storage == Storage.Database &&
                         Guid.TryParse(this.HttpContext.Request.Cookies[storageID].FromCookieString()["session"], out session))
                {
                    (bytes, filter) = StorageImplementation.DatabaseBytes(Configuration, HttpContext, storageID, session);
                    controller      = DeserializeController(actionContext, controllerTypeInfo, controllerType, bytes, filter);
                    ((IPersistentController)controller).Session = session;
                }

                // ---------- Load from X-ViewState Header ----------
                else if (storage == Storage.Header &&
                         this.HttpContext.Request.Headers.ContainsKey(StorageImplementation.HeaderName))
                {
                    // input type=hidden from <input viewstate="@ViewBag.ViewState" />
                    var controllerString = this.HttpContext.Request.Headers[StorageImplementation.HeaderName];
                    if (!String.IsNullOrEmpty(controllerString))
                    {
                        (bytes, filter) = StorageImplementation.ViewStateBytes(this.Configuration, controllerString);
                        controller      = DeserializeController(actionContext, controllerTypeInfo, controllerType, bytes, filter);
                    }
                }

                if (controller == null)
                {
                    // ASP.NET Core implementation, no persistence, just return the new controller
                    controller = actionContext.HttpContext.RequestServices.GetService(controllerType);
                }
            }

            return(controller);
        }