/// <summary> /// Maps the specified OData route and the OData route attributes. /// </summary> /// <param name="builder">The <see cref="IEndpointRouteBuilder"/> to add the route to.</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 input <see cref="IEndpointRouteBuilder"/>.</returns> public static IEndpointRouteBuilder MapODataRoute(this IEndpointRouteBuilder builder, string routeName, string routePrefix, Action <IContainerBuilder> configureAction) { if (builder == null) { throw Error.ArgumentNull("builder"); } if (routeName == null) { throw Error.ArgumentNull("routeName"); } // Build and configure the root container. IServiceProvider serviceProvider = builder.ServiceProvider; IPerRouteContainer perRouteContainer = serviceProvider.GetRequiredService <IPerRouteContainer>(); if (perRouteContainer == null) { throw Error.InvalidOperation(SRResources.MissingODataServices, nameof(IPerRouteContainer)); } // Make sure the MetadataController is registered with the ApplicationPartManager. ApplicationPartManager applicationPartManager = serviceProvider.GetRequiredService <ApplicationPartManager>(); applicationPartManager.ApplicationParts.Add(new AssemblyPart(typeof(MetadataController).Assembly)); // Create an service provider for this route. Add the default services to the custom configuration actions. Action <IContainerBuilder> builderAction = ConfigureDefaultServices(builder, configureAction); IServiceProvider subServiceProvider = perRouteContainer.CreateODataRootContainer(routeName, builderAction); // Resolve the path handler and set URI resolver to it. IODataPathHandler pathHandler = subServiceProvider.GetRequiredService <IODataPathHandler>(); // If settings is not on local, use the global configuration settings. ODataOptions options = serviceProvider.GetRequiredService <ODataOptions>(); if (pathHandler != null && pathHandler.UrlKeyDelimiter == null) { pathHandler.UrlKeyDelimiter = options.UrlKeyDelimiter; } // Resolve HTTP handler, create the OData route and register it. routePrefix = RemoveTrailingSlash(routePrefix); // If a batch handler is present, register the route with the batch path mapper. This will be used // by the batching middleware to handle the batch request. Batching still requires the injection // of the batching middleware via UseODataBatching(). ODataBatchHandler batchHandler = subServiceProvider.GetService <ODataBatchHandler>(); if (batchHandler != null) { // TODO: for the $batch, i need more time to refactor/test it. // batchHandler.ODataRoute = route; batchHandler.ODataRouteName = routeName; string batchPath = String.IsNullOrEmpty(routePrefix) ? '/' + ODataRouteConstants.Batch : '/' + routePrefix + '/' + ODataRouteConstants.Batch; ODataBatchPathMapping batchMapping = builder.ServiceProvider.GetRequiredService <ODataBatchPathMapping>(); batchMapping.AddRoute(routeName, batchPath); } builder.MapDynamicControllerRoute <ODataEndpointRouteValueTransformer>( ODataEndpointPattern.CreateODataEndpointPattern(routeName, routePrefix)); perRouteContainer.AddRoute(routeName, routePrefix); return(builder); }