コード例 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TApi"></typeparam>
        /// <param name="config"></param>
        /// <param name="routeName"></param>
        /// <param name="routePrefix"></param>
        /// <param name="allowBatching"></param>
        /// <param name="httpServer"></param>
        /// <returns></returns>
        public static HttpConfiguration MapRestier <TApi>(this HttpConfiguration config, string routeName, string routePrefix, bool allowBatching, HttpServer httpServer)
        {
            ODataBatchHandler batchHandler = null;
            var conventions = CreateRestierRoutingConventions(config, routeName);

            if (allowBatching)
            {
                if (httpServer == null)
                {
                    throw new ArgumentNullException(nameof(httpServer), owinException);
                }

#pragma warning disable IDE0067 // Dispose objects before losing scope
                batchHandler = new RestierBatchHandler(httpServer)
                {
                    ODataRouteName = routeName
                };
#pragma warning restore IDE0067 // Dispose objects before losing scope
            }

            config.MapODataServiceRoute(routeName, routePrefix, (builder) =>
            {
                builder.AddService <IEnumerable <IODataRoutingConvention> >(ServiceLifetime.Singleton, sp => conventions);
                if (batchHandler != null)
                {
                    //RWM: DO NOT simplify this generic signature. It HAS to stay this way, otherwise the code breaks.
                    builder.AddService <ODataBatchHandler>(ServiceLifetime.Singleton, sp => batchHandler);
                }
            });

            return(config);
        }
コード例 #2
0
        /// TODO GitHubIssue#51 : Support model lazy loading
        /// <summary>
        /// Maps the API routes to the RestierController.
        /// </summary>
        /// <typeparam name="TApi">The user API.</typeparam>
        /// <param name="config">The <see cref="HttpConfiguration"/> instance.</param>
        /// <param name="routeName">The name of the route.</param>
        /// <param name="routePrefix">The prefix of the route.</param>
        /// <param name="apiFactory">The callback to create API instances.</param>
        /// <param name="batchHandler">The handler for batch requests.</param>
        /// <returns>The task object containing the resulted <see cref="ODataRoute"/> instance.</returns>
        public static async Task <ODataRoute> MapRestierRoute <TApi>(
            this HttpConfiguration config,
            string routeName,
            string routePrefix,
            Func <IApi> apiFactory,
            RestierBatchHandler batchHandler = null)
            where TApi : ApiBase
        {
            Ensure.NotNull(apiFactory, "apiFactory");

            using (var api = apiFactory())
            {
                var model = await api.GetModelAsync();

                model.EnsurePayloadValueConverter();
                var conventions = CreateRestierRoutingConventions(config, model, apiFactory);

                if (batchHandler != null && batchHandler.ApiFactory == null)
                {
                    batchHandler.ApiFactory = apiFactory;
                }

                return(config.MapODataServiceRoute(
                           routeName, routePrefix, model, new DefaultODataPathHandler(), conventions, batchHandler));
            }
        }
コード例 #3
0
#pragma warning restore CA1823 // Do not declare static members on generic types

        /// TODO GitHubIssue#51 : Support model lazy loading
        /// <summary>
        /// Maps the API routes to the RestierController.
        /// </summary>
        /// <typeparam name="TApi">The user API.</typeparam>
        /// <param name="config">The <see cref="HttpConfiguration"/> instance.</param>
        /// <param name="routeName">The name of the route.</param>
        /// <param name="routePrefix">The prefix of the route.</param>
        /// <param name="batchHandler">The handler for batch requests.</param>
        /// <returns>The task object containing the resulted <see cref="ODataRoute"/> instance.</returns>
        public static Task <ODataRoute> MapRestierRoute <TApi>(
            this HttpConfiguration config,
            string routeName,
            string routePrefix,
            RestierBatchHandler batchHandler = null)
            where TApi : ApiBase
        {
            // This will be added a service to callback stored in ApiConfiguration
            // Callback is called by ApiBase.AddApiServices method to add real services.
            ApiBase.AddPublisherServices(typeof(TApi), services =>
            {
                services.AddODataServices <TApi>();
            });

            IContainerBuilder func() => new RestierContainerBuilder(typeof(TApi));

            config.UseCustomContainerBuilder(func);

            var conventions = CreateRestierRoutingConventions(config, routeName);

            if (batchHandler != null)
            {
                batchHandler.ODataRouteName = routeName;
            }

            void configureAction(IContainerBuilder builder) => builder
            .AddService <IEnumerable <IODataRoutingConvention> >(ServiceLifetime.Singleton, sp => conventions)
            .AddService <ODataBatchHandler>(ServiceLifetime.Singleton, sp => batchHandler);

            var route = config.MapODataServiceRoute(routeName, routePrefix, configureAction);

            return(Task.FromResult(route));
        }
コード例 #4
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="TApi"></typeparam>
        /// <param name="config"></param>
        /// <param name="routeName"></param>
        /// <param name="routePrefix"></param>
        /// <param name="allowBatching"></param>
        /// <returns></returns>
        public static HttpConfiguration MapRestier <TApi>(this HttpConfiguration config, string routeName, string routePrefix, bool allowBatching = true)
        {
            ODataBatchHandler batchHandler = null;
            var conventions = CreateRestierRoutingConventions(config, routeName);

            if (allowBatching)
            {
#pragma warning disable IDE0067 // Dispose objects before losing scope
                batchHandler = new RestierBatchHandler(GlobalConfiguration.DefaultServer)
                {
                    ODataRouteName = routeName
                };
#pragma warning restore IDE0067 // Dispose objects before losing scope
            }

            config.MapODataServiceRoute(routeName, routePrefix, (builder) =>
            {
                builder.AddService <IEnumerable <IODataRoutingConvention> >(ServiceLifetime.Singleton, sp => conventions);
                if (batchHandler != null)
                {
                    builder.AddService(ServiceLifetime.Singleton, sp => batchHandler);
                }
            });

            return(config);
        }
コード例 #5
0
 /// <summary>
 /// Maps the API routes to the RestierController.
 /// </summary>
 /// <typeparam name="TApi">The user API.</typeparam>
 /// <param name="config">The <see cref="HttpConfiguration"/> instance.</param>
 /// <param name="routeName">The name of the route.</param>
 /// <param name="routePrefix">The prefix of the route.</param>
 /// <param name="batchHandler">The handler for batch requests.</param>
 /// <returns>The task object containing the resulted <see cref="ODataRoute"/> instance.</returns>
 public static async Task <ODataRoute> MapRestierRoute <TApi>(
     this HttpConfiguration config,
     string routeName,
     string routePrefix,
     RestierBatchHandler batchHandler = null)
     where TApi : ApiBase, new()
 {
     return(await MapRestierRoute <TApi>(
                config, routeName, routePrefix, () => new TApi(), batchHandler));
 }
コード例 #6
0
        /// TODO GitHubIssue#51 : Support model lazy loading
        /// <summary>
        /// Maps the API routes to the RestierController.
        /// </summary>
        /// <typeparam name="TApi">The user API.</typeparam>
        /// <param name="config">The <see cref="HttpConfiguration"/> instance.</param>
        /// <param name="routeName">The name of the route.</param>
        /// <param name="routePrefix">The prefix of the route.</param>
        /// <param name="apiFactory">The callback to create API instances.</param>
        /// <param name="batchHandler">The handler for batch requests.</param>
        /// <returns>The task object containing the resulted <see cref="ODataRoute"/> instance.</returns>
        public static Task <ODataRoute> MapRestierRoute <TApi>(
            this HttpConfiguration config,
            string routeName,
            string routePrefix,
            Func <ApiBase> apiFactory,
            RestierBatchHandler batchHandler = null)
            where TApi : ApiBase
        {
            Ensure.NotNull(apiFactory, "apiFactory");

            // This will be added a service to callback stored in ApiConfiguration
            // Callback is called by ApiBase.AddApiServices method to add real services.
            ApiConfiguration.AddPublisherServices <TApi>(services =>
            {
                services.AddODataServices <TApi>();
            });
            using (var api = apiFactory())
            {
                var model = GetModel(api);

                var conventions = CreateRestierRoutingConventions(config, model, apiFactory);

                if (batchHandler != null && batchHandler.ApiFactory == null)
                {
                    batchHandler.ApiFactory = apiFactory;
                }

                // Customized path handler should be added in ConfigureApi as service
                // Allow to handle URL encoded slash (%2F), and backslash(%5C) with customized handler
                var handler = api.Context.GetApiService <IODataPathHandler>();
                if (handler == null)
                {
                    handler = new DefaultODataPathHandler();
                }

                var route = config.MapODataServiceRoute(
                    routeName, routePrefix, model, handler, conventions, batchHandler);

                // Customized converter should be added in ConfigureApi as service
                var converter = api.Context.GetApiService <ODataPayloadValueConverter>();
                if (converter == null)
                {
                    converter = new RestierPayloadValueConverter();
                }

                model.SetPayloadValueConverter(converter);

                return(Task.FromResult(route));
            }
        }
コード例 #7
0
        public static async void Register(HttpConfiguration config)
        {
#if !PROD
            config.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
#endif

            config.Filter().Expand().Select().OrderBy().MaxTop(100).Count();
            config.SetTimeZoneInfo(TimeZoneInfo.Utc);

            config.MapHttpAttributeRoutes();

            var batchHandler = new RestierBatchHandler(GlobalConfiguration.DefaultServer);
#pragma warning disable CA2007 // Do not directly await a Task
            await config.MapRestierRoute <NorthwindApi>("ApiV1", "", batchHandler);

#pragma warning restore CA2007 // Do not directly await a Task
        }
コード例 #8
0
        /// <summary>
        /// Instructs WebApi to map one or more of the registered Restier APIs to the specified Routes, each with it's own isolated Dependency Injection container.
        /// </summary>
        /// <param name="config">The <see cref="HttpConfiguration"/> instance to enhance.</param>
        /// <param name="configureRoutesAction">The action for configuring a set of routes.</param>
        /// <param name="httpServer">The HttpServer instance to create the routes on.</param>
        /// <returns>The <see cref="HttpConfiguration"/> instance to allow for fluent method chaining.</returns>
        /// <example>
        /// <code>
        /// config.MapRestier(builder =>
        ///     builder
        ///         .MapApiRoute<SomeApi>("SomeApiV1", "someapi/")
        ///         .MapApiRoute<AnotherApi>("AnotherApiV1", "anotherapi/")
        /// );
        /// </code>
        /// </example>
        public static HttpConfiguration MapRestier(this HttpConfiguration config, Action <RestierRouteBuilder> configureRoutesAction, HttpServer httpServer)
        {
            Ensure.NotNull(configureRoutesAction, nameof(configureRoutesAction));

            var rrb = new RestierRouteBuilder();

            configureRoutesAction.Invoke(rrb);

            foreach (var route in rrb.Routes)
            {
                ODataBatchHandler batchHandler = null;
                var conventions = CreateRestierRoutingConventions(config, route.Key);

                if (route.Value.AllowBatching)
                {
                    if (httpServer == null)
                    {
                        throw new ArgumentNullException(nameof(httpServer), OwinException);
                    }

#pragma warning disable IDE0067 // Dispose objects before losing scope
                    batchHandler = new RestierBatchHandler(httpServer)
                    {
                        ODataRouteName = route.Key
                    };
#pragma warning restore IDE0067 // Dispose objects before losing scope
                }

                var odataRoute = config.MapODataServiceRoute(route.Key, route.Value.RoutePrefix, (containerBuilder, routeName) =>
                {
                    var rcb          = containerBuilder as RestierContainerBuilder;
                    rcb.routeBuilder = rrb;
                    rcb.RouteName    = routeName;

                    containerBuilder.AddService <IEnumerable <IODataRoutingConvention> >(ServiceLifetime.Singleton, sp => conventions);
                    if (batchHandler != null)
                    {
                        //RWM: DO NOT simplify this generic signature. It HAS to stay this way, otherwise the code breaks.
                        containerBuilder.AddService <ODataBatchHandler>(ServiceLifetime.Singleton, sp => batchHandler);
                    }
                });
            }

            return(config);
        }
コード例 #9
0
        /// <summary>
        /// Instructs WebApi to map one or more of the registered Restier APIs to the specified Routes, each with it's own isolated Dependency Injection container.
        /// </summary>
        /// <param name="routeBuilder">The <see cref="HttpConfiguration"/> instance to enhance.</param>
        /// <param name="configureRoutesAction">The action for configuring a set of routes.</param>
        /// <returns>The <see cref="HttpConfiguration"/> instance to allow for fluent method chaining.</returns>
        /// <example>
        /// <code>
        /// config.MapRestier(builder =>
        ///     builder
        ///         .MapApiRoute<SomeApi>("SomeApiV1", "someapi/")
        ///         .MapApiRoute<AnotherApi>("AnotherApiV1", "anotherapi/")
        /// );
        /// </code>
        /// </example>
        public static IRouteBuilder MapRestier(this IRouteBuilder routeBuilder, Action <RestierRouteBuilder> configureRoutesAction)
        {
            Ensure.NotNull(routeBuilder, nameof(routeBuilder));
            Ensure.NotNull(configureRoutesAction, nameof(configureRoutesAction));

            var perRouteContainer = routeBuilder.ServiceProvider.GetRequiredService <IPerRouteContainer>();

            perRouteContainer.BuilderFactory = () => routeBuilder.ServiceProvider.GetRequiredService <IContainerBuilder>();

            var rrb = new RestierRouteBuilder();

            configureRoutesAction.Invoke(rrb);

            foreach (var route in rrb.Routes)
            {
                ODataBatchHandler batchHandler = null;

                if (route.Value.AllowBatching)
                {
#pragma warning disable IDE0067 // Dispose objects before losing scope
                    batchHandler = new RestierBatchHandler()
                    {
                        ODataRouteName = route.Key
                    };
#pragma warning restore IDE0067 // Dispose objects before losing scope
                }

                var odataRoute = routeBuilder.MapODataServiceRoute(route.Key, route.Value.RoutePrefix, (containerBuilder) =>
                {
                    var rcb          = containerBuilder as RestierContainerBuilder;
                    rcb.routeBuilder = rrb;
                    rcb.RouteName    = route.Key;

                    containerBuilder.AddService <IEnumerable <IODataRoutingConvention> >(OData.ServiceLifetime.Singleton, sp => routeBuilder.CreateRestierRoutingConventions(route.Key));
                    if (batchHandler != null)
                    {
                        //RWM: DO NOT simplify this generic signature. It HAS to stay this way, otherwise the code breaks.
                        containerBuilder.AddService <ODataBatchHandler>(OData.ServiceLifetime.Singleton, sp => batchHandler);
                    }
                });
            }

            return(routeBuilder);
        }
コード例 #10
0
        /// TODO GitHubIssue#51 : Support model lazy loading
        /// <summary>
        /// Maps the API routes to the RestierController.
        /// </summary>
        /// <typeparam name="TApi">The user API.</typeparam>
        /// <param name="config">The <see cref="HttpConfiguration"/> instance.</param>
        /// <param name="routeName">The name of the route.</param>
        /// <param name="routePrefix">The prefix of the route.</param>
        /// <param name="apiFactory">The callback to create API instances.</param>
        /// <param name="batchHandler">The handler for batch requests.</param>
        /// <returns>The task object containing the resulted <see cref="ODataRoute"/> instance.</returns>
        public static Task <ODataRoute> MapRestierRoute <TApi>(
            this HttpConfiguration config,
            string routeName,
            string routePrefix,
            Func <ApiBase> apiFactory,
            RestierBatchHandler batchHandler = null)
            where TApi : ApiBase
        {
            Ensure.NotNull(apiFactory, "apiFactory");

            // ApiBase.ConfigureApi is called before this method is called.
            ApiConfiguration.Configure <TApi>(services =>
            {
                services.AddScoped <RestierQueryExecutorOptions>()
                .ChainPrevious <IQueryExecutor, RestierQueryExecutor>();
            });
            using (var api = apiFactory())
            {
                var model = api.GetModelAsync().Result;

                var conventions = CreateRestierRoutingConventions(config, model, apiFactory);

                if (batchHandler != null && batchHandler.ApiFactory == null)
                {
                    batchHandler.ApiFactory = apiFactory;
                }

                var route = config.MapODataServiceRoute(
                    routeName, routePrefix, model, new DefaultODataPathHandler(), conventions, batchHandler);

                // Customized converter should be added in ConfigureApi as service
                var converter = api.Context.GetApiService <ODataPayloadValueConverter>();
                if (converter == null)
                {
                    converter = new RestierPayloadValueConverter();
                }

                model.SetPayloadValueConverter(converter);

                return(Task.FromResult(route));
            }
        }