Inheritance: IJsonSerializable
Beispiel #1
0
 internal ServiceRequestEventArgs(ServiceRequest request, ServiceResponse response)
 {
     this.Request  = request;
     this.Response = response;
 }
Beispiel #2
0
        /// <summary>
        /// Generates a script tag to embed a model including instance data into a server-rendered view.
        /// Supports initial customization of the model via an initialization delegate.
        /// </summary>
        /// <param name="query"></param>
        /// <param name="init"></param>
        /// <returns></returns>
        static void Model(TextWriter writer, object query, Delegate init)
        {
            // Raise the begin model event
            if (BeginModel != null)
            {
                BeginModel(query, EventArgs.Empty);
            }

            // Get the roots for each query
            var roots = new List <KeyValuePair <string, ServiceRequest.Query> >();

            foreach (var prop in query.GetType().GetProperties())
            {
                // Get the value of the model property
                var m = prop.GetValue(query, null);
                if (m == null)
                {
                    continue;
                }

                // Convert the value into a query, if necessary
                var q = m as ServiceRequest.Query ?? Query(m);
                if (q != null)
                {
                    q.LoadRoots(null);
                    roots.Add(new KeyValuePair <string, ServiceRequest.Query>(prop.Name, q));
                }
            }

            // Create the request object
            ServiceRequest request = new ServiceRequest(roots.Select(r => r.Value).ToArray());

            // Synthesize init new changes for new query roots
            ModelTransaction initChanges = (ModelTransaction)request.Queries
                                           .SelectMany(q => q.Roots)
                                           .Where(i => i.IsNew)
                                           .Select(i => new ModelInitEvent.InitNew(i))
                                           .Cast <ModelEvent>()
                                           .ToList();

            // Perform the initialization action, if specified
            if (init != null)
            {
                // Determine matching parameters
                var parameters = new object[init.Method.GetParameters().Length];
                foreach (var p in init.Method.GetParameters())
                {
                    foreach (var root in roots)
                    {
                        if (p.Name.Equals(root.Key, StringComparison.InvariantCultureIgnoreCase))
                        {
                            // List parameter
                            if (p.ParameterType.IsArray)
                            {
                                parameters[p.Position] = root.Value.Roots.Select(r => r.Instance).ToArray();
                            }

                            // Instance parameter
                            else
                            {
                                parameters[p.Position] = root.Value.Roots.Select(r => r.Instance).FirstOrDefault();
                            }

                            break;
                        }
                    }

                    // Throw an exception if the model property value cannot be cast to the corresponding initialization parameter
                    if (parameters[p.Position] != null && !p.ParameterType.IsAssignableFrom(parameters[p.Position].GetType()))
                    {
                        throw new ArgumentException(String.Format("The model property '{0}' cannot be converted into the initialization parameter type of '{1}'.", p.Name, p.ParameterType.FullName));
                    }

                    // Throw an exception if a valid model parameter could not be found to pass to the initialization delegate
                    if (parameters[p.Position] == null && query.GetType().GetProperty(p.Name, BindingFlags.Public | BindingFlags.IgnoreCase | BindingFlags.Instance) == null)
                    {
                        throw new ArgumentException(String.Format("A model property could not be found to pass to the initialization parameter '{0}'.", p.Name));
                    }
                }

                // Perform initialization while capturing changes
                initChanges.Record(() =>
                {
                    // Prevent property change rules from running until after initialization
                    ModelEventScope.Perform(() => init.DynamicInvoke(parameters));
                });
            }

            // Invoke the request queries
            ServiceResponse response = request.Invoke(initChanges);

            response.Model = roots.ToDictionary(r => r.Key, r => r.Value);
            foreach (var q in response.Model.Values)
            {
                q.ReducePaths();
            }

            // Track the current model roots to support server template rendering
            foreach (var root in response.Model)
            {
                Templates.Page.Current.Model[root.Key] = root.Value.IsList ? (object)root.Value.Roots : (root.Value.Roots.Length == 1 ?root.Value.Roots[0] : null);
            }

            // Write the model embed script to the writer
            writer.Write("<script type=\"text/javascript\">$exoweb(");
            JsonUtility.Serialize(writer, response);
            writer.Write(");</script>");

            // Raise the end model event
            if (EndModel != null)
            {
                EndModel(query, EventArgs.Empty);
            }
        }
Beispiel #3
0
 internal ServiceRequestEventArgs(ServiceRequest request, ServiceResponse response)
 {
     this.Request = request;
     this.Response = response;
 }
Beispiel #4
0
        /// <summary>
        /// Processes incoming requests and routes them to the appropriate JSON handler method.
        /// </summary>
        /// <param name="context"></param>
        void IHttpHandler.ProcessRequest(HttpContext context)
        {
            IsExecuting = true;

            try
            {
                // Perform the requested operation
                switch (context.Request.PathInfo)
                {
                case "/GetType":

                    // Enable response caching
                    context.Response.Cache.SetCacheability(HttpCacheability.Public);
                    context.Response.Cache.SetExpires(DateTime.Now.AddDays(7));
                    context.Response.Cache.SetMaxAge(TimeSpan.FromDays(7));

                    // Output the type metadata
                    context.Response.ContentType = "application/json";
                    JsonUtility.Serialize(context.Response.OutputStream, new ServiceRequest(context.Request.QueryString["type"].Replace("\"", "")).Invoke(null));

                    break;

                case "/LogError":

                    // Raise the error event
                    context.Response.ContentType = "application/json";
                    ExoWeb.OnError(JsonUtility.Deserialize <ServiceError>(context.Request.InputStream));

                    break;

                default:

                    // Deserialize the request
                    context.Response.Cache.SetCacheability(HttpCacheability.NoCache);
                    context.Response.Cache.SetNoStore();
                    ServiceRequest request = JsonUtility.Deserialize <ServiceRequest>(context.Request.InputStream);

                    // Invoke the request and output the response
                    context.Response.ContentType = "application/json";
                    using (var test = new StringWriter())
                    {
                        JsonUtility.Serialize(test, request.Invoke(null));
                        context.Response.Write(test.ToString());
                    }

                    break;
                }
            }
            catch (Exception e)
            {
                // look for an ExoModel.ModelException that may display a more
                // abstracted or informative message in the UI.  Otherwise, use
                // the inner most exception
                Exception reported = e;
                for (Exception x = e; x != null; x = x.InnerException)
                {
                    reported = x;
                    if (x is ModelException)
                    {
                        break;
                    }
                }

                // Create an error to log
                var error = new ServiceError();

                error.Type       = reported.GetType().FullName;
                error.StackTrace = GetFullStackTrace(e);
                error.Message    = reported.Message;
                error.Url        = context.Request.RawUrl;

                if (error.AdditionalInfo == null)
                {
                    error.AdditionalInfo = new Dictionary <string, object>();
                }
                //error.AdditionalInfo.Add("Client.RequestJson", json);

                // Raise the error event
                ExoWeb.OnError(error);

                // Also send the error information to the client
                context.Response.Clear();
                context.Response.ContentType = "application/json";
                context.Response.StatusCode  = 500;                // internal server error

                // Enable error information on client
                if (ExoWeb.EnableExceptionInformation)
                {
                    context.Response.AddHeader("jsonerror", "true");

                    // Ensure IIS 7 doesn't intercept the error
                    context.Response.TrySkipIisCustomErrors = true;
                }

                context.Response.Write(ExoWeb.ToJson(error));
            }
        }