예제 #1
0
        private PomonaResponse ExecuteQueryable(PomonaContext context, IQueryable resultAsQueryable)
        {
            var queryableActionResult = resultAsQueryable as IQueryableActionResult;
            int?defaultPageSize       = null;

            if (queryableActionResult != null && queryableActionResult.Projection != null)
            {
                defaultPageSize = queryableActionResult.DefaultPageSize;
                if (queryableActionResult.Projection != QueryProjection.AsEnumerable)
                {
                    var entity = queryableActionResult.Execute(queryableActionResult.Projection);
                    if (entity == null)
                    {
                        throw new ResourceNotFoundException("Resource not found.");
                    }
                    return(new PomonaResponse(entity, expandedPaths: context.ExpandedPaths));
                }
                resultAsQueryable = queryableActionResult.WrappedQueryable;
            }

            var queryExecutor = GetInstance <IQueryExecutor>();
            var pomonaQuery   = ParseQuery(context, resultAsQueryable.ElementType, defaultPageSize);

            return(queryExecutor.ApplyAndExecute(resultAsQueryable, pomonaQuery));
        }
예제 #2
0
        private PomonaQuery ParseQuery(PomonaContext context, Type rootType, int?defaultPageSize = null)
        {
            var queryPropertyResolver = new QueryTypeResolver(TypeMapper);
            var queryExpressionParser = new QueryExpressionParser(queryPropertyResolver);
            var queryTransformer      = new PomonaHttpQueryTransformer(TypeMapper, queryExpressionParser);
            var structuredType        = (ResourceType)TypeMapper.FromType(rootType);

            return(queryTransformer.TransformRequest(context, structuredType, defaultPageSize));
        }
예제 #3
0
        internal static IQueryable Query(this IPomonaSession session,
                                         UrlSegment urlSegment)
        {
            if (session == null)
                throw new ArgumentNullException(nameof(session));
            if (urlSegment == null)
                throw new ArgumentNullException(nameof(urlSegment));

            var request = new PomonaContext(urlSegment, acceptType : typeof(IQueryable), handleException : false);
            return (IQueryable)session.Dispatch(request).Entity;
        }
예제 #4
0
        internal static object Get(this IPomonaSession session,
                                   UrlSegment urlSegment)
        {
            if (session == null)
                throw new ArgumentNullException(nameof(session));
            if (urlSegment == null)
                throw new ArgumentNullException(nameof(urlSegment));

            var request = new PomonaContext(urlSegment, executeQueryable : true, handleException : false);
            return session.Dispatch(request).Entity;
        }
예제 #5
0
        private PomonaResponse DispatchInternal(PomonaContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.Session != this)
            {
                throw new ArgumentException("Request session is not same as this.");
            }

            var savedOuterContext = CurrentContext;

            try
            {
                CurrentContext = context;
                var result = Factory.Pipeline.Process(context);

                var resultEntity      = result.Entity;
                var resultAsQueryable = resultEntity as IQueryable;
                if (resultAsQueryable != null && context.ExecuteQueryable)
                {
                    result = ExecuteQueryable(context, resultAsQueryable);
                }

                if (context.AcceptType != null && !context.AcceptType.IsInstanceOfType(resultEntity))
                {
                    var route      = context.Route;
                    var resultType = route.ResultType;
                    if (typeof(IQueryable).IsAssignableFrom(context.AcceptType) &&
                        route.IsSingle &&
                        resultType.Type.IsInstanceOfType(resultEntity))
                    {
                        var array = Array.CreateInstance(resultType, 1);
                        array.SetValue(resultEntity, 0);
                        return(new PomonaResponse(array.AsQueryable()));
                    }

                    throw new InvalidOperationException("Result is not of accepted type.");
                }
                return(result);
            }
            finally
            {
                CurrentContext = savedOuterContext;
            }
        }
예제 #6
0
        internal static IQueryable Query(this IPomonaSession session,
                                         UrlSegment urlSegment)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (urlSegment == null)
            {
                throw new ArgumentNullException(nameof(urlSegment));
            }

            var request = new PomonaContext(urlSegment, acceptType: typeof(IQueryable), handleException: false);

            return((IQueryable)session.Dispatch(request).Entity);
        }
예제 #7
0
        internal static object Get(this IPomonaSession session,
                                   UrlSegment urlSegment)
        {
            if (session == null)
            {
                throw new ArgumentNullException(nameof(session));
            }
            if (urlSegment == null)
            {
                throw new ArgumentNullException(nameof(urlSegment));
            }

            var request = new PomonaContext(urlSegment, executeQueryable: true, handleException: false);

            return(session.Dispatch(request).Entity);
        }
예제 #8
0
        public virtual PomonaResponse Dispatch(PomonaContext context)
        {
            try
            {
                return(DispatchInternal(context));
            }
            catch (Exception ex)
            {
                if (!context.HandleException)
                {
                    throw;
                }

                var error = this.container.GetInstance <IPomonaErrorHandler>().HandleException(ex);
                if (error == null)
                {
                    throw;
                }

                return(new PomonaResponse(error.Entity ?? PomonaResponse.NoBodyEntity,
                                          error.StatusCode,
                                          responseHeaders: error.ResponseHeaders));
            }
        }
예제 #9
0
        public IEnumerable <RouteAction> GetRouteActions(PomonaContext context)
        {
            var route = context.Node.Route;

            return(Factory.ActionResolver.Resolve(route, context.Method));
        }
예제 #10
0
        public PomonaQuery TransformRequest(PomonaContext context, StructuredType rootType, int? defaultTop = null)
        {
            if (context == null)
                throw new ArgumentNullException(nameof(context));
            if (rootType == null)
                throw new ArgumentNullException(nameof(rootType));

            StructuredType ofType = null;
            if (context.Query["$oftype"].HasValue)
                ofType = (StructuredType)this.typeMapper.FromType((string)context.Query["$oftype"]);

            var query = new PomonaQuery(rootType, ofType);

            if (context.Query["$debug"].HasValue)
            {
                query.DebugInfoKeys =
                    new HashSet<string>(((string)context.Query["$debug"]).ToLower().Split(',').Select(x => x.Trim()));
            }

            string filter = null;
            var top = defaultTop ?? 100;
            var skip = 0;

            if (context.Query["$totalcount"].HasValue && ((string)context.Query["$totalcount"]).ToLower() == "true")
                query.IncludeTotalCount = true;

            if (context.Query["$top"].HasValue)
                top = int.Parse(context.Query["$top"]);

            if (context.Query["$skip"].HasValue)
                skip = int.Parse(context.Query["$skip"]);

            if (context.Query["$filter"].HasValue)
                filter = (string)context.Query["$filter"];

            ParseFilterExpression(query, filter);
            var selectSourceType = query.OfType.Type;

            if (context.Query["$groupby"].HasValue)
            {
                var groupby = (string)context.Query["$groupby"];
                ParseGroupByExpression(query, groupby);
                selectSourceType =
                    typeof(IGrouping<,>).MakeGenericType(
                        query.GroupByExpression.ReturnType, selectSourceType);
            }

            if (context.Query["$projection"].HasValue)
            {
                var projectionString = (string)context.Query["$projection"];
                query.Projection = projectionMap[projectionString];

                QueryProjection projection;
                if (!projectionMap.TryGetValue(projectionString, out projection))
                {
                    throw new QueryParseException("\"" + projectionString +
                                                  "\" is not a valid value for query parameter $projection",
                                                  null,
                                                  QueryParseErrorReason.UnrecognizedProjection,
                                                  null);
                }
                query.Projection = projection;
            }
            else
            {
                query.Projection = QueryProjection.AsEnumerable;
            }

            if (context.Query["$select"].HasValue)
            {
                var select = (string)context.Query["$select"];
                ParseSelect(query, select, selectSourceType);
            }

            if (context.Query["$orderby"].HasValue)
                ParseOrderBy(query, (string)context.Query["$orderby"]);

            query.Top = top;
            query.Skip = skip;

            if (context.Query["$expand"].HasValue)
            {
                // TODO: Translate expanded paths using TypeMapper
                query.ExpandedPaths = ((string)context.Query["$expand"]);
            }
            else
                query.ExpandedPaths = string.Empty;

            query.Url = context.Url;

            UpdateResultType(query);

            return query;
        }
예제 #11
0
        public PomonaQuery TransformRequest(PomonaContext context, StructuredType rootType, int?defaultTop = null)
        {
            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            if (rootType == null)
            {
                throw new ArgumentNullException(nameof(rootType));
            }

            StructuredType ofType = null;

            if (context.Query["$oftype"].HasValue)
            {
                ofType = (StructuredType)this.typeMapper.FromType((string)context.Query["$oftype"]);
            }

            var query = new PomonaQuery(rootType, ofType);

            if (context.Query["$debug"].HasValue)
            {
                query.DebugInfoKeys =
                    new HashSet <string>(((string)context.Query["$debug"]).ToLower().Split(',').Select(x => x.Trim()));
            }

            string filter = null;
            var    top    = defaultTop ?? 100;
            var    skip   = 0;

            if (context.Query["$totalcount"].HasValue && ((string)context.Query["$totalcount"]).ToLower() == "true")
            {
                query.IncludeTotalCount = true;
            }

            if (context.Query["$top"].HasValue)
            {
                top = int.Parse(context.Query["$top"]);
            }

            if (context.Query["$skip"].HasValue)
            {
                skip = int.Parse(context.Query["$skip"]);
            }

            if (context.Query["$filter"].HasValue)
            {
                filter = (string)context.Query["$filter"];
            }

            ParseFilterExpression(query, filter);
            var selectSourceType = query.OfType.Type;

            if (context.Query["$groupby"].HasValue)
            {
                var groupby = (string)context.Query["$groupby"];
                ParseGroupByExpression(query, groupby);
                selectSourceType =
                    typeof(IGrouping <,>).MakeGenericType(
                        query.GroupByExpression.ReturnType, selectSourceType);
            }

            if (context.Query["$projection"].HasValue)
            {
                var projectionString = (string)context.Query["$projection"];
                query.Projection = projectionMap[projectionString];

                QueryProjection projection;
                if (!projectionMap.TryGetValue(projectionString, out projection))
                {
                    throw new QueryParseException("\"" + projectionString +
                                                  "\" is not a valid value for query parameter $projection",
                                                  null,
                                                  QueryParseErrorReason.UnrecognizedProjection,
                                                  null);
                }
                query.Projection = projection;
            }
            else
            {
                query.Projection = QueryProjection.AsEnumerable;
            }

            if (context.Query["$select"].HasValue)
            {
                var select = (string)context.Query["$select"];
                ParseSelect(query, select, selectSourceType);
            }

            if (context.Query["$orderby"].HasValue)
            {
                ParseOrderBy(query, (string)context.Query["$orderby"]);
            }

            query.Top  = top;
            query.Skip = skip;

            if (context.Query["$expand"].HasValue)
            {
                // TODO: Translate expanded paths using TypeMapper
                query.ExpandedPaths = ((string)context.Query["$expand"]);
            }
            else
            {
                query.ExpandedPaths = string.Empty;
            }

            query.Url = context.Url;

            UpdateResultType(query);

            return(query);
        }