OData возвращает 'Не удается найти контейнер служб для маршрута' odata-Unversioned '

Я пытаюсь настроить новый API .NET Core 3.1 с OData.

У меня есть работающий API .NET Core в версии 2.2 с OData, поэтому я откажусь от него.

Я использую три пакета Nuget для OData: Microsoft.AspNetCore.OData v7.3.0, Microsoft.AspNetCore.OData.Versioning v4.1.1 и Microsoft.AspNetCore. OData.Versioning.ApiExplorer v4.1.1.

Когда я отправляю запрос GET на свой контроллер, я получаю следующий ответ:

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)

Примечание. У меня есть требование, чтобы у API была версия. Я не уверен, связано ли управление версиями с этой ошибкой, но старый API .NET Core 2.2, который у меня есть, также использует управление версиями OData. Кто-нибудь знает, что такое контейнер услуг для маршрута?

Я настраиваю свой проект аналогично https://devblogs.microsoft.com/odata/experimenting-with-odata-in-asp-net-core-3-1/. Я даже попытался настроить его точно так, как это сделано в сообщении в блоге, однако мне не удалось даже заставить OData работать без управления версиями. Когда я пытался удалить управление версиями, я продолжал получать 404, и он не мог попасть в маршрут. Правильно ли настроена моя маршрутизация?

Вот 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);
}

Вот конфигурация

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

Вот метод расширения GetEdmModel(), который я использую выше

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

Вот контроллер

[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());
    }
}

person Nick Gallimore    schedule 23.01.2020    source источник


Ответы (2)


Имя контроллера в методе GetEdmModel () и фактическое имя класса контроллера различались на единицу.

person Nick Gallimore    schedule 23.01.2020
comment
К сожалению, несовпадение имен приведет к проявлению этой ошибки. Рад, что ты нашел виновника. Мы надеемся, что исправление улучшит восприятие, когда кто-то сделает эту ошибку в будущем. - person Chris Martinez; 18.09.2020

Я могу подтвердить, что это действительно ошибка, но она кажется проявляется только тогда, когда URL-адрес запрашивается для несуществующей сущности. Это отслеживается как ошибка 553 с исправлением в ближайшее время.

person Chris Martinez    schedule 18.09.2020