Closed
Description
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" />