Reputation: 1263
I am trying to setup a new .NET Core 3.1 API with OData.
I have a working .NET Core API in 2.2 with OData, so I am going off of that one.
I am using three OData specific nuget packages: Microsoft.AspNetCore.OData v7.3.0, Microsoft.AspNetCore.OData.Versioning v4.1.1 and Microsoft.AspNetCore.OData.Versioning.ApiExplorer v4.1.1.
I keep getting the folloing response when I send a GET request to my controller:
System.InvalidOperationException: Cannot find the services container for route 'odata-Unversioned'. This should not happen and represents a bug.
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.<>c__DisplayClass0_0.<Match>b__0()
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)
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.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
Note I have the requirement that the API needs to be versioned. I am not sure if versioning has something to do with this error, but the old .NET Core 2.2 API that I have uses OData versioning as well. Does anyone know what the services container is for a route?
I setup my project similar to https://devblogs.microsoft.com/odata/experimenting-with-odata-in-asp-net-core-3-1/. I also even tried setting it up exactly as is done in the blog post, however I could not even get OData to work without versioning. When I tried removing versioning, I kept getting a 404 and it couldn't hit the route. Is my routing setup correctly?
Here is the ConfigureServices
public void ConfigureServices(IServiceCollection services)
{
// Add API versioning
services.AddApiVersioning(options => options.ReportApiVersions = true);
// Add OData
services.AddOData().EnableApiVersioning();
services.AddODataApiExplorer(options =>
{
options.GroupNameFormat = "'v'VVV";
options.SubstituteApiVersionInUrl = true;
});
// Add support for controllers and API-related features
services.AddControllers(mvcOptions => mvcOptions.EnableEndpointRouting = false);
}
Here is the Configure
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
var apiVersion = new ApiVersion(1, 0);
app.UseMvc(routeBuilder =>
{
routeBuilder.Count().Filter().OrderBy().Expand().Select().MaxTop(null);
app.UseMvc(routes =>
routes.MapVersionedODataRoute("odata", "api/v{version:apiVersion}", app.GetEdmModel(), apiVersion));
});
}
Here is the extension method GetEdmModel()
I am using above
public static class ODataExtensions
{
public static IEdmModel GetEdmModel(this IApplicationBuilder app)
{
var model = GetEdmModel(app.ApplicationServices);
return model;
}
private static IEdmModel GetEdmModel(IServiceProvider serviceProvider)
{
var builder = new ODataConventionModelBuilder(serviceProvider);
// Entities
builder.EntityType<Object>().HasKey(x => x.Id);
// Controllers
builder.EntitySet<Object>("Object");
return builder.GetEdmModel();
}
}
Here is the controller
[Route("odata")]
[ApiVersion("1")]
public class ObjectsController : ODataController
{
private readonly ILogicService _logicService;
public AlternateIdsController(ILogicService logicService)
{
_logicService = logicService;
}
[HttpGet]
[EnableQuery]
public IActionResult Get()
{
return Ok(_logicService.Browse());
}
}
Upvotes: 3
Views: 1590
Reputation: 4368
I can confirm that this is actually a bug, but it only seems to manifest when a URL is requested for an entity that doesn't exist. This is being tracked as Issue 553 with a fix forthcoming.
Upvotes: 0
Reputation: 1263
The controller name in the GetEdmModel() method and the actual name of the Controller class differed by one 's'.
Upvotes: 3