/// <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);
        }