Exemple #1
0
 /// <summary>
 /// Gets the set of property values to be serialized for the current instance
 /// </summary>
 /// <returns></returns>
 IEnumerator <object> IEnumerable <object> .GetEnumerator()
 {
     return(Instance.Type.Properties
            .Where(property => ExoWeb.IncludeInClientModel(property) && !property.IsStatic)
            .Select(property => property.IsList && !HasList(property) ? "?" : JsonConverter.GetPropertyValue(property, Instance))
            .GetEnumerator());
 }
Exemple #2
0
        /// <summary>
        /// Raises domain events.
        /// </summary>
        void RaiseEvents(ServiceResponse response, ModelTransaction transaction)
        {
            // Process each event in the request
            if (Events != null)
            {
                response.Events = Events
                                  .Select((domainEvent) =>
                {
                    // Restore the instance to be a valid model instance
                    if (domainEvent.Instance != null)
                    {
                        if (transaction != null)
                        {
                            domainEvent.Instance = transaction.GetInstance(domainEvent.Instance.Type, domainEvent.Instance.Id);
                        }
                        else
                        {
                            domainEvent.Instance = domainEvent.Instance.Type.Create(domainEvent.Instance.Id);
                        }
                    }

                    var result = domainEvent.Raise(transaction);

                    if (result == null)
                    {
                        return(null);
                    }

                    ModelType type;
                    ModelInstance[] roots;
                    bool isList;

                    if (ExoWeb.TryConvertQueryInstance(result, out type, out roots, out isList))
                    {
                        Query newQuery = new Query(type, roots, true, isList, domainEvent.Include);
                        newQuery.Prepare(response);

                        Query[] newQueries = new Query[] { newQuery };
                        Queries            = Queries == null ? newQueries : Queries.Union(newQueries).ToArray();

                        return(isList ? (object)roots : (object)roots[0]);
                    }
                    else if (domainEvent.Include != null && domainEvent.Include.Length > 0)
                    {
                        Query newQuery = new Query(domainEvent.Instance.Type, new[] { domainEvent.Instance }, true, false, domainEvent.Include);
                        newQuery.Prepare(response);

                        Query[] newQueries = new Query[] { newQuery };
                        Queries            = Queries == null ? newQueries : Queries.Union(newQueries).ToArray();

                        return(result);
                    }
                    else
                    {
                        return(result);
                    }
                })
                                  .ToArray();
            }
        }
Exemple #3
0
        /// <summary>
        /// Creates a query to load an instance and a set of options paths.
        /// </summary>
        /// <param name="instance"></param>
        /// <param name="scope"></param>
        /// <param name="paths"></param>
        /// <returns></returns>
        public static ServiceRequest.Query Query(object instance, ViewScope scope, params string[] paths)
        {
            ModelType type;

            ModelInstance[] roots;
            bool            isList;

            if (ExoWeb.TryConvertQueryInstance(instance, out type, out roots, out isList))
            {
                return(new ServiceRequest.Query(type, roots, scope == ViewScope.InScope, isList, paths));
            }
            else
            {
                return(null);
            }
        }
Exemple #4
0
 public static string ProcessRequest(string json)
 {
     return(JsonUtility.Serialize(ExoWeb.FromJson <ServiceRequest>(json).Invoke(null)));
 }
Exemple #5
0
        /// <summary>
        /// Outputs the JSON for the specified instance to the response stream.
        /// </summary>
        /// <param name="response"></param>
        internal ServiceResponse Invoke(ModelTransaction initChanges)
        {
            // Raise the begin request event
            ExoWeb.OnBeginRequest(this);

            // Create a response for the request
            ServiceResponse response = new ServiceResponse();

            response.ServerInfo = new ServerInformation();
            response.Changes    = initChanges;

            try
            {
                // Set the types to return from the request
                response.Types = Types;

                // Apply view initialization changes
                if (Changes != null && Changes.Length > 0 && Changes[0].Source == ChangeSource.Init)
                {
                    response.Changes = Changes[0].Changes;
                    response.Changes.Perform();
                }

                // Load root instances
                if (Queries != null)
                {
                    foreach (var query in Queries)
                    {
                        query.Prepare(response);
                        query.LoadRoots(response.Changes);
                    }
                }

                // Preload the scope of work before applying changes
                PerformQueries(response, false, initChanges != null);

                // Apply additional changes and raise domain events
                ApplyChanges(response);

                // Load instances specified by load queries
                PerformQueries(response, true, initChanges != null);

                // Condense the transaction log
                if (response.Changes != null)
                {
                    response.Changes.Condense();
                }

                // Send conditions for instances loaded in the request
                if (response.Instances != null || response.Changes != null)
                {
                    // Add instances created during the request
                    if (response.Changes != null)
                    {
                        foreach (var instance in response.Changes.OfType <ModelInitEvent.InitNew>().Select(modelEvent => modelEvent.Instance))
                        {
                            response.inScopeInstances.Add(instance);
                        }
                    }

                    // Ensure conditions are evaluated before extracting them
                    ExoWeb.OnEnsureConditions(response, response.inScopeInstances);

                    // Extract conditions for all instances involved in the request
                    Dictionary <string, List <Condition> > conditionsByType = new Dictionary <string, List <Condition> >();
                    foreach (var condition in response.inScopeInstances.SelectMany(instance => Condition.GetConditions(instance)))
                    {
                        List <Condition> conditions;
                        if (!conditionsByType.TryGetValue(condition.Type.Code, out conditions))
                        {
                            conditionsByType[condition.Type.Code] = conditions = new List <Condition>();
                        }

                        if (!conditions.Contains(condition))
                        {
                            conditions.Add(condition);
                        }
                    }
                    response.Conditions = conditionsByType;
                }
            }
            finally
            {
                // Raise the end request event
                ExoWeb.OnEndRequest(this, response);
            }

            // Return the response
            return(response);
        }
        void IJsonSerializable.Serialize(JsonWriter writer)
        {
            // Types
            if (Types != null && Types.Any())
            {
                writer.WritePropertyName("types");
                writer.WriteStartObject();
                foreach (var type in Types)
                {
                    writer.WritePropertyName(type);
                    writer.WriteRawValue(GetTypeJson(type));
                }
                writer.WriteEndObject();
            }

            if (Instances != null && Instances.Any())
            {
                writer.WritePropertyName("instances");
                writer.WriteStartObject();

                foreach (var typeItem in Instances)
                {
                    writer.WritePropertyName(typeItem.Key);
                    writer.WriteStartObject();

                    // Serialize static property values
                    if (typeItem.Value.StaticProperties.Count > 0)
                    {
                        writer.WritePropertyName("static");
                        writer.Serialize(
                            typeItem.Value.StaticProperties.ToDictionary(
                                property => property.Name,
                                property => JsonConverter.GetPropertyValue(property, property.DeclaringType)));
                    }

                    // Serialize instances
                    foreach (var instanceItem in typeItem.Value.Instances)
                    {
                        writer.WritePropertyName(instanceItem.Key);
                        writer.Serialize(instanceItem.Value);
                    }

                    writer.WriteEndObject();
                }

                writer.WriteEndObject();
            }

            if (Conditions != null && Conditions.Any())
            {
                writer.WritePropertyName("conditions");
                writer.Serialize(Conditions);
            }

            if (Events != null && Events.Any())
            {
                writer.WritePropertyName("events");
                writer.Serialize(Events);
            }

            if (Model != null && Model.Any())
            {
                writer.WritePropertyName("model");
                writer.Serialize(Model);
            }

            if (ServerInfo != null)
            {
                writer.WritePropertyName("serverInfo");
                writer.Serialize(ServerInfo);
            }

            if (Changes != null && Changes.Any())
            {
                writer.WritePropertyName("changes");
                writer.Serialize(Changes.Where(modelEvent => !(modelEvent is ModelValueChangeEvent) || ExoWeb.IncludeInClientModel(((ModelValueChangeEvent)modelEvent).Property)));
            }
        }
Exemple #7
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));
            }
        }