コード例 #1
0
        /// <summary>
        /// Maps a versioned OData route. When the <paramref name="batchHandler"/> is provided, it will create a '$batch' endpoint to handle the batch requests.
        /// </summary>
        /// <param name="builder">The extended <see cref="IRouteBuilder">route builder</see>.</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="model">The <see cref="IEdmModel">EDM model</see> to use for parsing OData paths.</param>
        /// <param name="apiVersion">The <see cref="ApiVersion">API version</see> associated with the model.</param>
        /// <param name="pathHandler">The <see cref="IODataPathHandler">OData path handler</see> to use for parsing the OData path.</param>
        /// <param name="routingConventions">The <see cref="IEnumerable{T}">sequence</see> of <see cref="IODataRoutingConvention">OData routing conventions</see>
        /// to use for controller and action selection.</param>
        /// <param name="batchHandler">The <see cref="ODataBatchHandler">OData batch handler</see>.</param>
        /// <returns>The mapped <see cref="ODataRoute">OData route</see>.</returns>
        /// <remarks>The <see cref="ApiVersionAnnotation">API version annotation</see> will be added or updated on the specified <paramref name="model"/> using
        /// the provided <paramref name="apiVersion">API version</paramref>.</remarks>
        public static ODataRoute MapVersionedODataRoute(
            this IRouteBuilder builder,
            string routeName,
            string routePrefix,
            IEdmModel model,
            ApiVersion apiVersion,
            IODataPathHandler pathHandler,
            IEnumerable <IODataRoutingConvention> routingConventions,
            ODataBatchHandler batchHandler)
        {
            Arg.NotNull(builder, nameof(builder));
            Arg.NotNullOrEmpty(routeName, nameof(routeName));
            Arg.NotNull(model, nameof(model));
            Arg.NotNull(apiVersion, nameof(apiVersion));
            Contract.Ensures(Contract.Result <ODataRoute>() != null);

            IEnumerable <IODataRoutingConvention> NewRoutingConventions(IServiceProvider serviceProvider)
            {
                var conventions = VersionedODataRoutingConventions.AddOrUpdate(routingConventions.ToList());

                conventions.Insert(0, new VersionedAttributeRoutingConvention(routeName, builder.ServiceProvider, apiVersion));
                return(conventions.ToArray());
            }

            var routeCollection          = builder.ServiceProvider.GetRequiredService <IODataRouteCollectionProvider>();
            var perRouteContainer        = builder.ServiceProvider.GetRequiredService <IPerRouteContainer>();
            var options                  = builder.ServiceProvider.GetRequiredService <ODataOptions>();
            var inlineConstraintResolver = builder.ServiceProvider.GetRequiredService <IInlineConstraintResolver>();

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

            model.SetAnnotationValue(model, new ApiVersionAnnotation(apiVersion));

            var configureAction = builder.ConfigureDefaultServices(container =>
                                                                   container.AddService(Singleton, typeof(IEdmModel), sp => model)
                                                                   .AddService(Singleton, typeof(IODataPathHandler), sp => pathHandler)
                                                                   .AddService(Singleton, typeof(IEnumerable <IODataRoutingConvention>), NewRoutingConventions)
                                                                   .AddService(Singleton, typeof(ODataBatchHandler), sp => batchHandler));
            var rootContainer   = perRouteContainer.CreateODataRootContainer(routeName, configureAction);
            var router          = rootContainer.GetService <IRouter>() ?? builder.DefaultHandler;
            var routeConstraint = new VersionedODataPathRouteConstraint(routeName, apiVersion);
            var route           = new ODataRoute(router, routeName, routePrefix.RemoveTrailingSlash(), routeConstraint, inlineConstraintResolver);

            builder.ConfigureBatchHandler(rootContainer, route);
            builder.Routes.Add(route);
            routeCollection.Add(new ODataRouteMapping(route, apiVersion, rootContainer));
            builder.AddRouteToRespondWithBadRequestWhenAtLeastOneRouteCouldMatch(routeName, routePrefix, apiVersion, inlineConstraintResolver);
            NotifyRoutesMapped();

            return(route);
        }
コード例 #2
0
        /// <summary>
        /// Maps the specified OData route and the OData route attributes.
        /// </summary>
        /// <param name="builder">The extended <see cref="IRouteBuilder">route builder</see>.</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="apiVersion">The <see cref="ApiVersion">API version</see> associated with the model.</param>
        /// <param name="configureAction">The configuring action to add the services to the root container.</param>
        /// <param name="configureRoutingConventions">The configuring action to add or update routing conventions.</param>
        /// <returns>The added <see cref="ODataRoute"/>.</returns>
        public static ODataRoute MapVersionedODataRoute(
            this IRouteBuilder builder,
            string routeName,
            string routePrefix,
            ApiVersion apiVersion,
            Action <IContainerBuilder> configureAction,
            Action <ODataConventionConfigurationContext> configureRoutingConventions)
        {
            Arg.NotNull(builder, nameof(builder));
            Arg.NotNullOrEmpty(routeName, nameof(routeName));
            Arg.NotNull(apiVersion, nameof(apiVersion));
            Contract.Ensures(Contract.Result <ODataRoute>() != null);

            IEnumerable <IODataRoutingConvention> NewRoutingConventions(IServiceProvider serviceProvider)
            {
                var model = serviceProvider.GetRequiredService <IEdmModel>();
                var routingConventions = VersionedODataRoutingConventions.CreateDefault();
                var context            = new ODataConventionConfigurationContext(routeName, model, apiVersion, routingConventions);

                model.SetAnnotationValue(model, new ApiVersionAnnotation(apiVersion));
                routingConventions.Insert(0, new VersionedAttributeRoutingConvention(routeName, builder.ServiceProvider, apiVersion));
                configureRoutingConventions?.Invoke(context);

                return(context.RoutingConventions.ToArray());
            }

            var routeCollection          = builder.ServiceProvider.GetRequiredService <IODataRouteCollectionProvider>();
            var perRouteContainer        = builder.ServiceProvider.GetRequiredService <IPerRouteContainer>();
            var inlineConstraintResolver = builder.ServiceProvider.GetRequiredService <IInlineConstraintResolver>();
            var preConfigureAction       = builder.ConfigureDefaultServices(
                container =>
            {
                container.AddService(Singleton, typeof(IEnumerable <IODataRoutingConvention>), NewRoutingConventions);
                configureAction?.Invoke(container);
            });
            var rootContainer = perRouteContainer.CreateODataRootContainer(routeName, preConfigureAction);
            var router        = rootContainer.GetService <IRouter>() ?? builder.DefaultHandler;

            builder.ConfigurePathHandler(rootContainer);

            var routeConstraint = new VersionedODataPathRouteConstraint(routeName, apiVersion);
            var route           = new ODataRoute(router, routeName, routePrefix.RemoveTrailingSlash(), routeConstraint, inlineConstraintResolver);

            builder.ConfigureBatchHandler(rootContainer, route);
            builder.Routes.Add(route);
            routeCollection.Add(new ODataRouteMapping(route, apiVersion, rootContainer));
            builder.AddRouteToRespondWithBadRequestWhenAtLeastOneRouteCouldMatch(routeName, routePrefix, apiVersion, inlineConstraintResolver);
            NotifyRoutesMapped();

            return(route);
        }
コード例 #3
0
        public static ODataRoute MapVersionedODataRoute(
            this HttpConfiguration configuration,
            string routeName,
            string routePrefix,
            IEdmModel model,
            ApiVersion apiVersion,
            IODataPathHandler pathHandler,
            IEnumerable<IODataRoutingConvention> routingConventions,
            ODataBatchHandler batchHandler )
        {
            Arg.NotNull( configuration, nameof( configuration ) );
            Arg.NotNull( model, nameof( model ) );
            Arg.NotNull( apiVersion, nameof( apiVersion ) );
            Contract.Ensures( Contract.Result<ODataRoute>() != null );

            var routeConventions = EnsureConventions( routingConventions.ToList() );
            var routes = configuration.Routes;

            if ( !IsNullOrEmpty( routePrefix ) )
            {
                routePrefix = routePrefix.TrimEnd( '/' );
            }

            if ( batchHandler != null )
            {
                var batchTemplate = IsNullOrEmpty( routePrefix ) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch;
                routes.MapHttpBatchRoute( routeName + "Batch", batchTemplate, batchHandler );
            }

            configuration.SetResolverSettings( pathHandler );
            model.SetAnnotationValue( model, new ApiVersionAnnotation( apiVersion ) );
            routeConventions.Insert( 0, new VersionedAttributeRoutingConvention( model, configuration ) );

            var routeConstraint = new VersionedODataPathRouteConstraint( pathHandler, model, routeName, routeConventions.ToArray(), apiVersion );
            var route = new ODataRoute( routePrefix, routeConstraint );

            AddApiVersionConstraintIfNecessary( route );
            routes.Add( routeName, route );

            var unversionedRouteConstraint = new ODataPathRouteConstraint( pathHandler, model, routeName, routeConventions.ToArray() );
            var unversionedRoute = new ODataRoute( routePrefix, new UnversionedODataPathRouteConstraint( unversionedRouteConstraint, apiVersion ) );

            AddApiVersionConstraintIfNecessary( unversionedRoute );
            routes.Add( routeName + UnversionedRouteSuffix, unversionedRoute );

            return route;
        }
コード例 #4
0
        static ODataRoute MapVersionedODataRoute(
            HttpConfiguration configuration,
            string routeName,
            string routePrefix,
            IEdmModel model,
            ApiVersion apiVersion,
            IODataPathHandler pathHandler,
            IEnumerable <IODataRoutingConvention> routingConventions,
            ODataBatchHandler batchHandler,
            HttpMessageHandler defaultHandler)
        {
            Arg.NotNull(configuration, nameof(configuration));
            Arg.NotNull(model, nameof(model));
            Arg.NotNull(apiVersion, nameof(apiVersion));
            Contract.Ensures(Contract.Result <ODataRoute>() != null);

            var routeConventions = EnsureConventions(routingConventions.ToList());
            var routes           = configuration.Routes;

            if (!IsNullOrEmpty(routePrefix))
            {
                routePrefix = routePrefix.TrimEnd('/');
            }

            if (pathHandler != null && pathHandler.UrlKeyDelimiter == null)
            {
                pathHandler.UrlKeyDelimiter = configuration.GetUrlKeyDelimiter();
            }

            model.SetAnnotationValue(model, new ApiVersionAnnotation(apiVersion));
            routeConventions.Insert(0, new VersionedAttributeRoutingConvention(routeName, configuration, apiVersion));

            var rootContainer = configuration.CreateODataRootContainer(
                routeName,
                builder => builder.AddService(Singleton, typeof(IEdmModel), sp => model)
                .AddService(Singleton, typeof(IODataPathHandler), sp => pathHandler)
                .AddService(Singleton, typeof(IEnumerable <IODataRoutingConvention>), sp => routeConventions.ToArray())
                .AddService(Singleton, typeof(ODataBatchHandler), sp => batchHandler)
                .AddService(Singleton, typeof(HttpMessageHandler), sp => defaultHandler));

            rootContainer.InitializeAttributeRouting();

            var routeConstraint = new VersionedODataPathRouteConstraint(routeName, apiVersion);
            var route           = default(ODataRoute);

            if (defaultHandler != null)
            {
                route = new ODataRoute(routePrefix, routeConstraint, defaults: null, constraints: null, dataTokens: null, handler: defaultHandler);
            }
            else
            {
                if (batchHandler != null)
                {
                    batchHandler.ODataRouteName = routeName;
                    var batchTemplate = IsNullOrEmpty(routePrefix) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch;
                    routes.MapHttpBatchRoute(routeName + nameof(ODataRouteConstants.Batch), batchTemplate, batchHandler);
                }

                route = new ODataRoute(routePrefix, routeConstraint);
            }

            routes.Add(routeName, route);
            AddApiVersionConstraintIfNecessary(route);

            var unversionedRouteConstraint = new ODataPathRouteConstraint(routeName);
            var unversionedRoute           = new ODataRoute(routePrefix, new UnversionedODataPathRouteConstraint(unversionedRouteConstraint, apiVersion));

            AddApiVersionConstraintIfNecessary(unversionedRoute);
            routes.Add(routeName + UnversionedRouteSuffix, unversionedRoute);

            return(route);
        }
コード例 #5
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="apiVersion">The <see cref="ApiVersion">API version</see> associated with the model.</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 MapVersionedODataRoute(this HttpConfiguration configuration, string routeName, string routePrefix, ApiVersion apiVersion, Action <IContainerBuilder> configureAction)
        {
            Arg.NotNull(configuration, nameof(configuration));
            Arg.NotNull(apiVersion, nameof(apiVersion));
            Contract.Ensures(Contract.Result <ODataRoute>() != null);

            object ConfigureRoutingConventions(IServiceProvider serviceProvider)
            {
                var model = serviceProvider.GetRequiredService <IEdmModel>();
                var routingConventions = EnsureConventions(ODataRoutingConventions.CreateDefault());

                model.SetAnnotationValue(model, new ApiVersionAnnotation(apiVersion));
                routingConventions.Insert(0, new VersionedAttributeRoutingConvention(routeName, configuration, apiVersion));

                return(routingConventions.ToArray());
            }

            if (!IsNullOrEmpty(routePrefix))
            {
                routePrefix = routePrefix.TrimEnd('/');
            }

            var rootContainer = configuration.CreateODataRootContainer(
                routeName,
                builder =>
            {
                builder.AddService(Singleton, typeof(IEnumerable <IODataRoutingConvention>), ConfigureRoutingConventions);
                configureAction?.Invoke(builder);
            });
            var pathHandler = rootContainer.GetRequiredService <IODataPathHandler>();

            if (pathHandler != null && pathHandler.UrlKeyDelimiter == null)
            {
                pathHandler.UrlKeyDelimiter = configuration.GetUrlKeyDelimiter();
            }

            rootContainer.InitializeAttributeRouting();

            var routeConstraint = new VersionedODataPathRouteConstraint(routeName, apiVersion);
            var route           = default(ODataRoute);
            var routes          = configuration.Routes;
            var messageHandler  = rootContainer.GetService <HttpMessageHandler>();

            if (messageHandler != null)
            {
                route = new ODataRoute(
                    routePrefix,
                    routeConstraint,
                    defaults: null,
                    constraints: null,
                    dataTokens: null,
                    handler: messageHandler);
            }
            else
            {
                var batchHandler = rootContainer.GetService <ODataBatchHandler>();

                if (batchHandler != null)
                {
                    batchHandler.ODataRouteName = routeName;
                    var batchTemplate = IsNullOrEmpty(routePrefix) ? ODataRouteConstants.Batch : routePrefix + '/' + ODataRouteConstants.Batch;
                    routes.MapHttpBatchRoute(routeName + nameof(ODataRouteConstants.Batch), batchTemplate, batchHandler);
                }

                route = new ODataRoute(routePrefix, routeConstraint);
            }

            routes.Add(routeName, route);
            AddApiVersionConstraintIfNecessary(route);

            var unversionedRouteConstraint = new ODataPathRouteConstraint(routeName);
            var unversionedRoute           = new ODataRoute(routePrefix, new UnversionedODataPathRouteConstraint(unversionedRouteConstraint, apiVersion));

            AddApiVersionConstraintIfNecessary(unversionedRoute);
            configuration.Routes.Add(routeName + UnversionedRouteSuffix, unversionedRoute);

            return(route);
        }