Skip to content

Error: "Cannot find the services container for route" when using MapVersionedODataRoute #553

Closed
@aniliht

Description

@aniliht

Hello, I'm using the ASP.NET Core 2.2 and OData. I'm using the following setup in which I create the EdmModel dynamically by looking at the user's claims. Based on the claims, I add a EntitySet A or EntitySet B for example.

When I browse to the controller for EntitySet A and the user doesn't have the claim for it,
I get the following exception when I use the MapVersionedODataRoute. I don't get the exception if I use the OData routebuilder method MapODataServiceRoute(...); which returns 404 as expected instead.

Perhaps my setup is not supported or I misconfigured something? Thanks for your time.

Exception Message:

System.InvalidOperationException: 'Cannot find the services container for route 'odataV1-Unversioned'. This should not happen and represents a bug.'

StackTrace

at Microsoft.AspNet.OData.PerRouteContainerBase.GetODataRootContainer(String routeName)
at Microsoft.AspNet.OData.Extensions.HttpRequestExtensions.CreateRequestScope(HttpRequest request, String routeName)
at Microsoft.AspNet.OData.Extensions.HttpRequestExtensions.CreateRequestContainer(HttpRequest request, String routeName)
at Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint.GetODataPath(String oDataPathString, String uriPathString, String queryString, Func`1 requestContainerFactory)
at Microsoft.AspNet.OData.Routing.ODataPathRouteConstraint.Match(HttpContext httpContext, IRouter route, String routeKey, RouteValueDictionary values, RouteDirection routeDirection)
at Microsoft.AspNet.OData.Routing.UnversionedODataPathRouteConstraint.Match(HttpContext httpContext, IRouter route, String routeKey, RouteValueDictionary values, RouteDirection routeDirection) in E:\BA\56\s\src\Microsoft.AspNetCore.OData.Versioning\AspNet.OData\Routing\UnversionedODataPathRouteConstraint.cs:line 79
at Microsoft.AspNetCore.Routing.RouteConstraintMatcher.Match(IDictionary`2 constraints, RouteValueDictionary routeValues, HttpContext httpContext, IRouter route, RouteDirection routeDirection, ILogger logger)
at Microsoft.AspNetCore.Routing.RouteBase.RouteAsync(RouteContext context)
at Microsoft.AspNetCore.Routing.RouteCollection.RouteAsync(RouteContext context)
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)

Startup.cs

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddApplicationInsightsTelemetry();
            services.Configure<AuthSettings>(Configuration.GetSection(nameof(AuthSettings)));
            var provider = services.BuildServiceProvider();
            var authSettings = provider.GetRequiredService<IOptions<AuthSettings>>();

            services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
                .AddJwtBearer(options =>
                {
                    options.SaveToken = true;
                    options.Audience = authSettings.Value.Audience;
                    options.Authority = authSettings.Value.Authority;
                    options.TokenValidationParameters = new TokenValidationParameters
                    {
                        ValidateAudience = true,
                        ValidateIssuer = true,
                        ValidateLifetime = true,
                        ValidateIssuerSigningKey = true
                    };
                });

            services.AddHttpContextAccessor();
            services.AddApiVersioning();
            services.AddOData().EnableApiVersioning();

            services.AddMvc(options =>
            {
                options.EnableEndpointRouting = false;

                var policy = new AuthorizationPolicyBuilder()
                    .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                    .RequireAuthenticatedUser()                    
                    .Build();

                options.Filters.Add(new AuthorizeFilter(policy));

            }).SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

            ConfigureApplicationServices(services);
        }        

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
#if DEBUG
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
#endif
            app.UseUnhandledExceptionMiddleware();
            app.UseAuthentication();
            app.UseHttpsRedirection();

            var routeNameV1 = "odataV1";
            app.UseMvc(routeBuilder =>
            {
                routeBuilder.MapVersionedODataRoute(routeNameV1, string.Empty, new ApiVersion(1, 0), GetODataContainerBuilder(routeNameV1, routeBuilder));
            });
        }

        private Action<IContainerBuilder> GetODataContainerBuilder(string routeName, IRouteBuilder routeBuilder)
        {
            return new Action<IContainerBuilder>(containerBuilder =>
            {
                containerBuilder.AddService<IEdmModel>(Microsoft.OData.ServiceLifetime.Scoped, sp =>
                {
                    var httpRequestScope = sp.GetRequiredService<HttpRequestScope>();
                    var claims = httpRequestScope?.HttpRequest?.HttpContext?.User?.Claims;
                    
                    return EdmModelFactory.GetEdmModel(claims);  // based on the claims, will select EntitySet to add to the model.

                });

                containerBuilder.AddService<IEnumerable<IODataRoutingConvention>>(Microsoft.OData.ServiceLifetime.Singleton, sp =>
                               ODataRoutingConventions.CreateDefaultWithAttributeRouting(routeName, routeBuilder));
            });

        }

Nuget package versions:

    <PackageReference Include="Microsoft.ApplicationInsights.AspNetCore" Version="2.8.0" />
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Http.Extensions" Version="2.2.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.Versioning" Version="3.1.6" />
    <PackageReference Include="Microsoft.AspNetCore.OData" Version="7.2.1" />
    <PackageReference Include="Microsoft.AspNetCore.OData.Versioning" Version="3.2.4" />
    <PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.2.0" PrivateAssets="All" />
    <PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="2.2.0" />

Metadata

Metadata

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions