OData路由找不到路由

OData routing cannot find the route

这是我的 ApplicationUserController(我删除了 ctor 等不必要的部分):

[ODataRouting]
public class ApplicationUserController : ApiController
{
    [EnableQuery]
    [HttpGet("ApplicationUser")]
    [HttpGet("ApplicationUser/$count")]
    public IQueryable<ApplicationUser> Get()
    {
        return _applicationUserRepository.GetQueryable();
    }

    [HttpGet("ApplicationUser/{id}")]
    [HttpGet("ApplicationUser({id})")]
    public async Task<ApplicationUser> GetById([FromODataUri] long id)
    {
        return await _applicationUserRepository.SingleOrDefault(x => x.Id == id);
    }
}

第一个功能完美运行。我调用 http://localhost:5000/v1/ApplicationUser?$filter=startsWith(LastName, 'Test') 并得到所有姓氏以“Test”开头的用户。

第二个不行。我叫

和 none 确实有效。对于两者,我都收到 404:未找到。

我做错了什么吗? 我也尝试添加 EnableQuery-Attribute,但没有任何区别。

这是我来自 ConfigureServices 的代码:

public void ConfigureServices(IServiceCollection services)
{
    IEdmModel v1 = _getEdmModel();
    
    services.AddOData(opt => opt
        .AddModel("v{version}", v1)
        .Select()
        .Expand()
        .OrderBy()
        .Filter()
        .Count()
    );
}

和我的 _getEdmModel():

private static IEdmModel _getEdmModel()
{
    ODataConventionModelBuilder builder = new (new DefaultAssemblyResolver());
    builder.EntitySet<ApplicationUser>("ApplicationUser");            
    builder.EntityType<ApplicationUser>().HasKey(x => x.Id); // edit: added this line
    return builder.GetEdmModel();
}

更新:

我创建了一个新的存储库,基本代码在这里:https://github.com/matthiasburger/ApplePie

相同的行为,可通过以下 URL 重现:

这很奇怪,但是如果您将方法名称“GetById”更改为“GetTestEntity”,它会起作用...


题外话

您可以通过

简化您的 Serilog 实例(删除主机构建器中已有的大量代码)
public static void Main(string[] args)
{
    CreateHostBuilder(args).Build().Run();
}

public static IHostBuilder CreateHostBuilder(string[] args) => Host
    .CreateDefaultBuilder(args) // sets all the configuration options right!
    .ConfigureAppConfiguration((hostingContext, config) =>
        config.AddJsonFile("secrets.json", optional: true, reloadOnChange: true))
    .UseSerilogLogger((hostBuilderContext, loggerConfiguration) => loggerConfiguration
        .ReadFrom.Configuration(hostBuilderContext.Configuration)
        .Enrich.FromLogContext()) // no output?
    .ConfigureWebHostDefaults(webHostBuilder => webHostBuilder
        .UseStartup<Startup>()
    );

您唯一会错过的是虚拟主机的起始和最终异常。但如果那里有问题,无论如何你都会注意到。

@Matthias Burger

让我分享更多细节,希望对您有所帮助。

--> 现在常规路由:

  1. 您注册了名为“ApplicationUser”的实体集,因此任何名为“ApplicationUserController”的控制器都被视为 OData 控制器。

  2. “ApplicationUserController”中的任何操作都是潜在的 OData 方法。

  3. “Get()”方法符合实体集常规路由规则,因此,本次“Get()”动作将构建两条OData路由。

  • ~/v{版本}/ApplicationUser
  • ~/v{version}/ApplicationUser/$count
  1. “GetById(long id)”不满足任何内置的常规路由规则,因此,此方法没有 OData 路由构建。

--> 现在对于属性路由:

  1. 由于您在控制器上装饰了“[ODataRouting]”,因此任何属性路由,例如 [HttpGet("ApplicationUser")] 都是潜在的 OData 属性路由。

  2. OData 属性路由基于模型寄存器。您应该创建以路由前缀“v{version}”

    开头的路由模板
  3. 因此,如果您将“[HttpGet("ApplicationUser/{id}")]”更改为 [HttpGet("v{version}/ApplicationUser/{id}")] 路由应该有效。

  4. 注意,如果你在"Get()"方法的属性中添加前缀,你会得到Ambiguous routes异常,因为"Get()"将有OData常规路由和属性路由.因此,请避免将它们混合在一起。

顺便给你404https://github.com/matthiasburger/ApplePie

关于属性路由,可以参考:

https://devblogs.microsoft.com/odata/attribute-routing-in-asp-net-core-odata-8-0-rc/