Beispiel #1
0
        public HttpResponseMessage <JsonQueryResult> Query([FromBody] JsonQueryBatchRequest batch)
        {
            string hintText = Request.RequestUri.Query;

            // Validate arguments
            if (batch == null || batch.Queries == null || batch.Requests == null || batch.Queries.Length == 0 || batch.Requests.Length == 0)
            {
                string error = "Cannot parse post data.";
                if (batch == null)
                {
                    error += "batch was null.";
                }
                else if (batch.Queries == null)
                {
                    error += "batch.Queries was null.";
                }
                else if (batch.Requests == null)
                {
                    error += "batch.Requests was null.";
                }
                else if (batch.Queries.Length == 0)
                {
                    error += "batch.Queries.Length was 0.";
                }
                else if (batch.Requests.Length == 0)
                {
                    error += "batch.Requests.Length was 0.";
                }

                EventLog.Application.WriteError(error);
                return(new HttpResponseMessage <JsonQueryResult>(HttpStatusCode.BadRequest));
            }


            // Prep working objects
            var context = new EntityPackage( );

            context.AddEntityRequestBatch(batch, hintText);

            return(new HttpResponseMessage <JsonQueryResult>(context.GetQueryResult( )));
        }
Beispiel #2
0
        /// <summary>
        ///     Add a request for a set of entities and queries.
        /// </summary>
        /// <param name="batch">The batch.</param>
        /// <param name="hintText">A hint about what this query is doing. Use for logging/diagnostics only.</param>
        /// <exception cref="System.ArgumentException">
        /// </exception>
        /// <exception cref="System.Exception">Internal error: batch query mismatch.</exception>
        public void AddEntityRequestBatch(JsonQueryBatchRequest batch, string hintText = null)
        {
            JsonQueryResult result = _result;


#pragma warning disable 618
            EntityInfoService svc = _svc;
#pragma warning restore 618

            var memberRequests = new EntityMemberRequest[batch.Queries.Length];

            foreach (JsonQuerySingleRequest request in batch.Requests)
            {
                string requestHintText = request.Hint ?? hintText;

                _entitiesVisited.Clear( );

                var singleResult = new JsonSingleQueryResult
                {
                    Hint = request.Hint, Ids = new List <long>( )
                };

                try
                {
                    EntityMemberRequest memberRequest;

                    // Do not require access to the individual query components
                    using (PerformanceCounters.Measure(EntityInfoServicePerformanceCounters.CategoryName, EntityInfoServicePerformanceCounters.RequestCountersPrefix))
                        using (new SecurityBypassContext( ))
                        {
                            // Get/parse the request query. (Either parse, or load from previous cache as part of this request).
                            if (request.QueryIndex < 0 || request.QueryIndex >= batch.Queries.Length)
                            {
                                EventLog.Application.WriteError("Cannot locate query string.");
                                singleResult.Code = HttpStatusCode.BadRequest;
                                continue;
                            }
                            memberRequest = memberRequests[request.QueryIndex];
                            if (memberRequest == null)
                            {
                                string queryString = batch.Queries[request.QueryIndex];

                                //// Parse the request
                                try
                                {
                                    memberRequest = Factory.RequestParser.ParseRequestQuery(queryString);
                                }
                                catch (Exception ex)
                                {
                                    EventLog.Application.WriteError(ex.ToString( ));
                                    singleResult.Code = HttpStatusCode.BadRequest;
                                    continue;
                                }
                                memberRequests[request.QueryIndex] = memberRequest;
                            }
                        }

                    // Get the entityRefs
                    IEnumerable <EntityRef> ids = Enumerable.Empty <EntityRef>( );

                    if (request.Aliases != null && request.Aliases.Length > 0)
                    {
                        ids = ids.Union(request.Aliases.Select(ConvertId));
                    }

                    if (request.Ids != null && request.Ids.Length > 0)
                    {
                        ids = ids.Union(request.Ids.Select(ConvertId));
                    }

                    IList <EntityRef> entityRefs = ids.ToList( );

                    if (entityRefs.All(er => er == null))
                    {
                        singleResult.Code = HttpStatusCode.NotFound;
                        continue;
                    }

                    // Run the request
                    IEnumerable <EntityData> entitiesData;
                    try
                    {
                        if (BulkRequestHelper.IsValidForBulkRequest(memberRequest))
                        {
                            var entityRequest = new EntityRequest
                            {
                                QueryType     = request.QueryType,
                                RequestString = memberRequest.RequestString,
                                Hint          = requestHintText,
                                Entities      = entityRefs,
                                Filter        = request.Filter,
                                Isolated      = request.Isolated
                            };

                            // Run the request
                            entitiesData = BulkRequestRunner.GetEntities(entityRequest);

                            singleResult.Cached = entityRequest.ResultFromCache;
                        }
                        else
                        {
                            EventLog.Application.WriteWarning(
                                "Request cannot be handled by BulkRequest. Hint: {0}\n{1}",
                                requestHintText, memberRequest.RequestString);

                            switch (request.QueryType)
                            {
                            case QueryType.Instances:
                                entitiesData = svc.GetEntitiesByType(entityRefs.Single( ), true, memberRequest);
                                break;

                            case QueryType.ExactInstances:
                                entitiesData = svc.GetEntitiesByType(entityRefs.Single( ), false, memberRequest);
                                break;

                            case QueryType.Basic:
                            case QueryType.BasicWithDemand:
                                entitiesData = svc.GetEntitiesData(entityRefs, memberRequest);
                                break;

                            default:
                                throw new ArgumentException(string.Format("Unknown query type {0}", request.QueryType));
                            }
                        }
                    }
                    catch (ArgumentException ex)
                    {
                        // sorry world!
                        if (ex.Message.Contains("does not represent a known entity"))
                        {
                            singleResult.Code = HttpStatusCode.BadRequest;
                            continue;
                        }
                        throw;
                    }

                    // Skip results where access is denied
                    foreach (EntityData entityData in entitiesData.Where(ed => ed != null))
                    {
                        AppendEntityToResult(result, entityData);
                        singleResult.Ids.Add(entityData.Id.Id);
                    }

                    // Set the result to NotFound for Basic and BasicWithDemand only
                    if (request.QueryType == QueryType.Basic || request.QueryType == QueryType.BasicWithDemand)
                    {
                        singleResult.Code = singleResult.Ids.Count > 0
                                                        ? HttpStatusCode.OK
                                                        : HttpStatusCode.NotFound;
                    }
                    else
                    {
                        singleResult.Code = HttpStatusCode.OK;
                    }
                }
                catch (PlatformSecurityException ex)
                {
                    EventLog.Application.WriteWarning(ex.ToString( ));
                    singleResult.Ids.Clear( );
                    singleResult.Code = HttpStatusCode.Forbidden;
                }
                catch (Exception ex)
                {
                    EventLog.Application.WriteError(ex.ToString( ));
                    singleResult.Code = HttpStatusCode.InternalServerError;
                }
                finally
                {
                    // Place in the finally block so we are certain that it gets run exactly once per iteration
                    result.Results.Add(singleResult);
                }
            }

            if (result.Results.Count != batch.Requests.Length)
            {
                // We are indexing by ID, so we must always ensure that request position matches result position.
                throw new Exception("Internal error: batch query mismatch.");
            }
        }
Beispiel #3
0
        /// <summary>
        /// Add a request for a set of entities and queries.
        /// </summary>
        /// <param name="batch"></param>
        public void AddEntityRequestBatch(JsonQueryBatchRequest batch)
        {
            var result = this.Result;


            var svc = Svc;

            var memberRequests = new EntityMemberRequest[batch.Queries.Length];

            foreach (var request in batch.Requests)
            {
                EntitiesVisited.Clear();

                var singleResult = new JsonSingleQueryResult();

                try
                {
                    // Get/parse the request query. (Either parse, or load from previous cache as part of this request).
                    if (request.QueryIndex < 0 || request.QueryIndex >= batch.Queries.Length)
                    {
                        throw new Exception("Cannot locate query string.");
                    }
                    var memberRequest = memberRequests[request.QueryIndex];
                    if (memberRequest == null)
                    {
                        string queryString = batch.Queries[request.QueryIndex];

                        //// Parse the request
                        try
                        {
                            memberRequest = EntityRequestHelper.BuildRequest(queryString);
                        }
                        catch (Exception ex)
                        {
                            EventLog.Application.WriteError(ex.ToString());
                            singleResult.Code = HttpStatusCode.BadRequest;
                            continue;
                        }
                        memberRequests[request.QueryIndex] = memberRequest;
                    }

                    // Get the entityRefs
                    IEnumerable <EntityRef> entityRefs = request.Ids.Select(objId =>
                    {
                        if (objId is string)
                        {
                            var entityRef = new EntityRef((string)objId);
                            try
                            {
                                long id = entityRef.Id;
                            }
                            catch (ArgumentException ex)
                            {
                                singleResult.Code = HttpStatusCode.NotFound;
                                return(new EntityRef(0));    // or whatever
                            }
                            return(entityRef);
                        }
                        if (objId is long)
                        {
                            return(new EntityRef((long)objId));
                        }
                        if (objId is int)
                        {
                            return(new EntityRef((long)(int)objId));
                        }
                        throw new InvalidOperationException();
                    });


                    // Run the request
                    IEnumerable <EntityData> entitiesData;
                    try
                    {
                        switch (request.QueryType)
                        {
                        case QueryType.Instances:
                            entitiesData = svc.GetEntitiesByType(entityRefs.Single(), true, memberRequest);
                            break;

                        case QueryType.ExactInstances:
                            entitiesData = svc.GetEntitiesByType(entityRefs.Single(), false, memberRequest);
                            break;

                        case QueryType.Basic:
                        default:
                            entitiesData = svc.GetEntitiesData(entityRefs, memberRequest);
                            break;
                        }
                    }
                    catch (ArgumentException ex)
                    {
                        // sorry world!
                        if (ex.Message.Contains("does not represent a known entity"))
                        {
                            singleResult.Code = HttpStatusCode.BadRequest;
                            continue;
                        }
                        throw;
                    }


                    // Package results
                    singleResult.IDs = new List <long>();

                    foreach (var entityData in entitiesData)
                    {
                        AppendEntityToResult(result, entityData, this);
                        singleResult.IDs.Add(entityData.Id.Id);
                    }

                    // Capture result code
                    singleResult.Code = singleResult.IDs.Count > 0
                                            ? HttpStatusCode.OK
                                            : HttpStatusCode.NotFound;
                }
                catch (Exception ex)
                {
                    EventLog.Application.WriteError(ex.ToString());
                    singleResult.Code = HttpStatusCode.InternalServerError;
                }
                finally
                {
                    // Place in the finally block so we are certain that it gets run exactly once per iteration
                    result.Results.Add(singleResult);
                }
            }

            if (result.Results.Count != batch.Requests.Length)
            {
                // We are indexing by ID, so we must always ensure that request position matches result position.
                throw new Exception("Internal error: batch query mismatch.");
            }
        }