コード例 #1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="AttributeRoutingConvention"/> class.
        /// </summary>
        /// <param name="routeName">The name of the route.</param>
        /// <param name="configuration">The <see cref="HttpConfiguration"/> to use for figuring out all the controllers to
        /// look for a match.</param>
        /// <param name="pathTemplateHandler">The path template handler to be used for parsing the path templates.</param>
        public AttributeRoutingConvention(string routeName, HttpConfiguration configuration,
                                          IODataPathTemplateHandler pathTemplateHandler)
            : this(routeName, pathTemplateHandler)
        {
            if (configuration == null)
            {
                throw Error.ArgumentNull("configuration");
            }

            IODataPathHandler pathHandler = pathTemplateHandler as IODataPathHandler;

            // if settings is not on local, use the global configuration settings.
            if (pathHandler != null && pathHandler.UrlKeyDelimiter == null)
            {
                ODataUrlKeyDelimiter urlKeyDelimiter = configuration.GetUrlKeyDelimiter();
                pathHandler.UrlKeyDelimiter = urlKeyDelimiter;
            }

            Action <HttpConfiguration> oldInitializer = configuration.Initializer;
            bool initialized = false;

            configuration.Initializer = (config) =>
            {
                if (!initialized)
                {
                    initialized = true;
                    oldInitializer(config);
                    IHttpControllerSelector controllerSelector = config.Services.GetHttpControllerSelector();
                    _attributeMappings = BuildAttributeMappings(controllerSelector.GetControllerMapping().Values);
                }
            };
        }
コード例 #2
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="serviceBaseUri">The base URI of the service. This will be used as the base URI for all entity containers.</param>
        /// <param name="urlKeyDelimiter">Key delimiter used in url.</param>
        internal ODataConventionalUriBuilder(Uri serviceBaseUri, ODataUrlKeyDelimiter urlKeyDelimiter)
        {
            Debug.Assert(serviceBaseUri != null && serviceBaseUri.IsAbsoluteUri, "serviceBaseUri != null && serviceBaseUri.IsAbsoluteUri");
            Debug.Assert(urlKeyDelimiter != null, "urlKeyDelimiter != null");

            this.serviceBaseUri = serviceBaseUri;
            this.keySerializer  = KeySerializer.Create(urlKeyDelimiter.EnableKeyAsSegment);
        }
コード例 #3
0
        public static Uri UriBuilder(Uri queryUri, ODataUrlKeyDelimiter urlKeyDelimiter, ODataUriParserSettings settings)
        {
            ODataUriParser odataUriParser = new ODataUriParser(HardCodedTestModel.TestModel, ServiceRoot, queryUri);

            odataUriParser.UrlKeyDelimiter = urlKeyDelimiter;
            ODataUri odataUri = odataUriParser.ParseUri();

            return(odataUri.BuildUri(urlKeyDelimiter));
        }
コード例 #4
0
        /// <summary>
        /// Set the UrlKeyDelimiter in DefaultODataPathHandler.
        /// </summary>
        /// <param name="configuration">The server configuration.</param>
        /// <param name="urlKeyDelimiter">The <see cref="ODataUrlKeyDelimiter"/></param>
        public static void SetUrlKeyDelimiter(this HttpConfiguration configuration, ODataUrlKeyDelimiter urlKeyDelimiter)
        {
            if (configuration == null)
            {
                throw Error.ArgumentNull("configuration");
            }

            configuration.Properties[UrlKeyDelimiterKey] = urlKeyDelimiter;
        }
コード例 #5
0
        /// <summary>
        /// Set the UrlKeyDelimiter in DefaultODataPathHandler.
        /// </summary>
        /// <param name="builder">The <see cref="IRouteBuilder"/>.</param>
        /// <param name="urlKeyDelimiter">The <see cref="ODataUrlKeyDelimiter"/></param>
        public static IRouteBuilder SetUrlKeyDelimiter(this IRouteBuilder builder, ODataUrlKeyDelimiter urlKeyDelimiter)
        {
            if (builder == null)
            {
                throw Error.ArgumentNull("builder");
            }

            if (urlKeyDelimiter == null)
            {
                throw Error.ArgumentNull("urlKeyDelimiter");
            }

            ODataOptions defaultOptions = builder.GetDefaultODataOptions();

            defaultOptions.UrlKeyDelimiter = urlKeyDelimiter;
            return(builder);
        }
コード例 #6
0
        private static Uri GenerateQueryFromExpandedItem(ODataSerializerContext writeContext, Uri navigationLink)
        {
            IWebApiUrlHelper urlHelper = writeContext.InternalUrlHelper;

            if (urlHelper == null)
            {
                return(navigationLink);
            }
            string serviceRoot = urlHelper.CreateODataLink(
                writeContext.InternalRequest.Context.RouteName,
                writeContext.InternalRequest.PathHandler,
                new List <ODataPathSegment>());
            Uri            serviceRootUri = new Uri(serviceRoot);
            ODataUriParser parser         = new ODataUriParser(writeContext.Model, serviceRootUri, navigationLink);
            ODataUri       newUri         = parser.ParseUri();

            newUri.SelectAndExpand = writeContext.SelectExpandClause;
            if (writeContext.CurrentExpandedSelectItem != null)
            {
                newUri.OrderBy = writeContext.CurrentExpandedSelectItem.OrderByOption;
                newUri.Filter  = writeContext.CurrentExpandedSelectItem.FilterOption;
                newUri.Skip    = writeContext.CurrentExpandedSelectItem.SkipOption;
                newUri.Top     = writeContext.CurrentExpandedSelectItem.TopOption;

                if (writeContext.CurrentExpandedSelectItem.CountOption != null)
                {
                    if (writeContext.CurrentExpandedSelectItem.CountOption.HasValue)
                    {
                        newUri.QueryCount = writeContext.CurrentExpandedSelectItem.CountOption.Value;
                    }
                }

                ExpandedNavigationSelectItem expandedNavigationItem = writeContext.CurrentExpandedSelectItem as ExpandedNavigationSelectItem;
                if (expandedNavigationItem != null)
                {
                    newUri.SelectAndExpand = expandedNavigationItem.SelectAndExpand;
                }
            }

            ODataUrlKeyDelimiter keyDelimiter = writeContext.InternalRequest.Options.UrlKeyDelimiter == ODataUrlKeyDelimiter.Slash ? ODataUrlKeyDelimiter.Slash : ODataUrlKeyDelimiter.Parentheses;

            return(newUri.BuildUri(keyDelimiter));
        }
コード例 #7
0
        /// <summary>
        /// Initializes a new instance of <see cref="ODataUriParserConfiguration"/>.
        /// </summary>
        /// <param name="model">Model to use for metadata binding.</param>
        /// <param name="container">The optional dependency injection container to get related services for URI parsing.</param>
        /// <exception cref="System.ArgumentNullException">Throws if input model is null.</exception>
        /// <exception cref="ArgumentException">Throws if the input serviceRoot is not an AbsoluteUri</exception>
        public ODataUriParserConfiguration(IEdmModel model, IServiceProvider container)
        {
            ExceptionUtils.CheckArgumentNotNull(model, "model");

            this.Model           = model;
            this.Container       = container;
            this.Resolver        = ODataUriResolver.GetUriResolver(container);
            this.urlKeyDelimiter = ODataUrlKeyDelimiter.GetODataUrlKeyDelimiter(container);

            if (this.Container == null)
            {
                this.Settings = new ODataUriParserSettings();
            }
            else
            {
                this.Settings = this.Container.GetRequiredService <ODataUriParserSettings>();
            }

            this.EnableUriTemplateParsing = false;
        }
コード例 #8
0
        private static Uri GenerateQueryFromExpandedItem(ODataSerializerContext writeContext, Uri navigationLink)
        {
            string         serviceRoot    = writeContext.Request.CreateODataLink(new List <ODataPathSegment>());
            Uri            serviceRootUri = new Uri(serviceRoot);
            ODataUriParser parser         = new ODataUriParser(writeContext.Model, serviceRootUri, navigationLink);
            ODataUri       newUri         = parser.ParseUri();

            newUri.SelectAndExpand = writeContext.SelectExpandClause;
            if (writeContext.CurrentExpandedSelectItem != null)
            {
                newUri.OrderBy = writeContext.CurrentExpandedSelectItem.OrderByOption;
                newUri.Filter  = writeContext.CurrentExpandedSelectItem.FilterOption;
                newUri.Skip    = writeContext.CurrentExpandedSelectItem.SkipOption;
                newUri.Top     = writeContext.CurrentExpandedSelectItem.TopOption;

                if (writeContext.CurrentExpandedSelectItem.CountOption != null)
                {
                    if (writeContext.CurrentExpandedSelectItem.CountOption.HasValue)
                    {
                        newUri.QueryCount = writeContext.CurrentExpandedSelectItem.CountOption.Value;
                    }
                }

                ExpandedNavigationSelectItem expandedNavigationItem = writeContext.CurrentExpandedSelectItem as ExpandedNavigationSelectItem;
                if (expandedNavigationItem != null)
                {
                    newUri.SelectAndExpand = expandedNavigationItem.SelectAndExpand;
                }
            }

            ODataUrlKeyDelimiter keyDelimiter = ODataUrlKeyDelimiter.Parentheses;
            ODataOptions         options      = writeContext.Request.HttpContext.RequestServices.GetRequiredService <IOptions <ODataOptions> >().Value;

            if (options != null)
            {
                keyDelimiter = options.UrlKeyDelimiter;
            }

            return(newUri.BuildUri(keyDelimiter));
        }
コード例 #9
0
 /// <summary>
 /// Sets the <see cref="ODataUrlKeyDelimiter"/> to use while parsing, specifically whether to recognize keys as segments or not.
 /// </summary>
 /// <param name="keyDelimiter">The key demimiter.</param>
 /// <returns>The calling itself.</returns>
 public ODataOptions SetUrlKeyDelimiter(ODataUrlKeyDelimiter keyDelimiter)
 {
     UrlKeyDelimiter = keyDelimiter;
     return(this);
 }
コード例 #10
0
 // Slash became the default 4/18/2018
 // REF: https://github.com/OData/WebApi/pull/1393
 static ODataUrlKeyDelimiter UrlKeyDelimiterOrDefault(ODataUrlKeyDelimiter urlKeyDelimiter) => urlKeyDelimiter ?? Slash;
コード例 #11
0
        private ODataUriParser ParseDynamicPathSegmentFunc_ReturnDynamicPathSegment_WithCollectionReturnType(Uri fullUri, out ODataPath odataPath, ODataUrlKeyDelimiter uriConventions = null)
        {
            var container = ContainerBuilderHelper.BuildContainer(builder => builder.AddService <UriPathParser, SingleSegmentUriPathParser>(ServiceLifetime.Scoped));
            var uriParser = new ODataUriParser(oneDriveModel, ServiceRoot, fullUri, container);

            if (uriConventions != null)
            {
                uriParser.UrlKeyDelimiter = uriConventions;
            }

            var operation = oneDriveModel.SchemaElements.OfType <IEdmOperation>().FirstOrDefault(o => o.Name == "recent");

            uriParser.ParseDynamicPathSegmentFunc = (previous, identifier, parenthesisExpression) =>
            {
                var dynamicPathSeg = new DynamicPathSegment(identifier, operation.ReturnType.Definition, containedItemsNav, false);

                var segments = new List <ODataPathSegment>
                {
                    dynamicPathSeg
                };

                if (parenthesisExpression != null)
                {
                    segments.Add(new KeySegment(dynamicPathSeg, new Dictionary <string, object>()
                    {
                        { "id", parenthesisExpression.Trim('\'') }
                    }, itemType, null));
                }

                return(segments);
            };

            odataPath = uriParser.ParsePath();
            return(uriParser);
        }
コード例 #12
0
        private ODataPath ParseDynamicPathSegmentFunc_ReturnDynamicPathSegment_WithCollectionReturnType(Uri fullUri, ODataUrlKeyDelimiter uriConventions = null)
        {
            ODataPath odataPath;

            ParseDynamicPathSegmentFunc_ReturnDynamicPathSegment_WithCollectionReturnType(fullUri, out odataPath, uriConventions);
            return(odataPath);
        }
コード例 #13
0
        /// <summary>
        /// Maps the specified OData route and the OData route attributes.
        /// </summary>
        /// <param name="configuration">The server configuration.</param>
        /// <param name="routeName">The name of the route to map.</param>
        /// <param name="routePrefix">The prefix to add to the OData route's path template.</param>
        /// <param name="configureAction">The configuring action to add the services to the root container.</param>
        /// <returns>The added <see cref="ODataRoute"/>.</returns>
        public static ODataRoute MapODataServiceRoute(this HttpConfiguration configuration, string routeName,
                                                      string routePrefix, Action <IContainerBuilder> configureAction)
        {
            if (configuration == null)
            {
                throw Error.ArgumentNull("configuration");
            }

            if (routeName == null)
            {
                throw Error.ArgumentNull("routeName");
            }

            // 1) Build and configure the root container.
            IServiceProvider rootContainer = configuration.CreateODataRootContainer(routeName, configureAction);

            // 2) Resolve the path handler and set URI resolver to it.
            IODataPathHandler pathHandler = rootContainer.GetRequiredService <IODataPathHandler>();

            // if settings is not on local, use the global configuration settings.
            if (pathHandler != null && pathHandler.UrlKeyDelimiter == null)
            {
                ODataUrlKeyDelimiter urlKeyDelimiter = configuration.GetUrlKeyDelimiter();
                pathHandler.UrlKeyDelimiter = urlKeyDelimiter;
            }

            // 3) Resolve some required services and create the route constraint.
            ODataPathRouteConstraint routeConstraint = new ODataPathRouteConstraint(routeName);

            // Attribute routing must initialized before configuration.EnsureInitialized is called.
            rootContainer.GetServices <IODataRoutingConvention>();

            // 4) Resolve HTTP handler, create the OData route and register it.
            ODataRoute          route;
            HttpRouteCollection routes = configuration.Routes;

            routePrefix = RemoveTrailingSlash(routePrefix);
            HttpMessageHandler messageHandler = rootContainer.GetService <HttpMessageHandler>();

            if (messageHandler != null)
            {
                route = new ODataRoute(
                    routePrefix,
                    routeConstraint,
                    defaults: null,
                    constraints: null,
                    dataTokens: null,
                    handler: messageHandler);
            }
            else
            {
                ODataBatchHandler batchHandler = rootContainer.GetService <ODataBatchHandler>();
                if (batchHandler != null)
                {
                    batchHandler.ODataRouteName = routeName;
                    string batchTemplate = String.IsNullOrEmpty(routePrefix) ? ODataRouteConstants.Batch
                        : routePrefix + '/' + ODataRouteConstants.Batch;
                    routes.MapHttpBatchRoute(routeName + "Batch", batchTemplate, batchHandler);
                }

                route = new ODataRoute(routePrefix, routeConstraint);
            }

            routes.Add(routeName, route);
            return(route);
        }
コード例 #14
0
 /// <summary>
 /// Get the string representation of <see cref="ODataPath"/>.
 /// mainly translate Query Url path.
 /// </summary>
 /// <param name="path">Path to perform the computation on.</param>
 /// <param name="urlKeyDelimiter">Mark whether key is segment</param>
 /// <returns>The string representation of the Query Url path.</returns>
 public static string ToResourcePathString(this ODataPath path, ODataUrlKeyDelimiter urlKeyDelimiter)
 {
     return(string.Concat(path.WalkWith(new PathSegmentToResourcePathTranslator(urlKeyDelimiter)).ToArray()).TrimStart('/'));
 }
コード例 #15
0
        /// <summary>
        /// Tries to handle the current segment as a key property value.
        /// </summary>
        /// <param name="segmentText">The segment text.</param>
        /// <param name="previous">The previous segment.</param>
        /// <param name="previousKeySegment">The parent node's key segment.</param>
        /// <param name="odataUrlKeyDelimiter">Key delimiter used in url.</param>
        /// <param name="resolver">The resolver to use.</param>
        /// <param name="keySegment">The key segment that was created if the segment could be interpreted as a key.</param>
        /// <param name="enableUriTemplateParsing">Whether Uri template parsing is enabled.</param>
        /// <returns>Whether or not the segment was interpreted as a key.</returns>
        internal static bool TryHandleSegmentAsKey(string segmentText, ODataPathSegment previous, KeySegment previousKeySegment, ODataUrlKeyDelimiter odataUrlKeyDelimiter, ODataUriResolver resolver, out KeySegment keySegment, bool enableUriTemplateParsing = false)
        {
            Debug.Assert(previous != null, "previous != null");
            Debug.Assert(odataUrlKeyDelimiter != null, "odataUrlKeyDelimiter != null");
            Debug.Assert(resolver != null, "resolver != null");

            keySegment = null;

            // If the current convention does not support keys-as-segments, then this does not apply.
            if (!odataUrlKeyDelimiter.EnableKeyAsSegment)
            {
                return(false);
            }

            // Keys only apply to collections, so if the prior segment is already a singleton, do not treat this segment as a key.
            if (previous.SingleResult)
            {
                return(false);
            }

            // System segments (ie '$count') are never keys.
            if (IsSystemSegment(segmentText))
            {
                return(false);
            }

            // If the previous type is not an entity collection type
            // TODO: collapse this and SingleResult.
            IEdmEntityType targetEntityType;

            if (previous.TargetEdmType == null || !previous.TargetEdmType.IsEntityOrEntityCollectionType(out targetEntityType))
            {
                return(false);
            }

            // Previously KeyAsSegment only allows single key, but we can also leverage related key finder to auto fill
            // missed key value from referential constraint information, which would be done in CreateKeySegment.
            // CreateKeySegment method will check whether key properties are missing after taking in related key values.
            keySegment = CreateKeySegment(previous, previousKeySegment, SegmentArgumentParser.FromSegment(segmentText, enableUriTemplateParsing), resolver);

            return(true);
        }
コード例 #16
0
 /// <summary>
 /// Private constructor since the singleton instance is sufficient.
 /// </summary>
 /// <param name="odataUrlKeyDelimiter">Key delimiter used in url.</param>
 public PathSegmentToResourcePathTranslator(ODataUrlKeyDelimiter odataUrlKeyDelimiter)
 {
     Debug.Assert(odataUrlKeyDelimiter != null, "odataUrlKeyDelimiter != null");
     this.KeySerializer = KeySerializer.Create(odataUrlKeyDelimiter.EnableKeyAsSegment);
 }