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”开头的用户。
第二个不行。我叫
http://localhost:5000/v1/ApplicationUser/1
http://localhost:5000/v1/ApplicationUser(1)
和 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 重现:
https://localhost:5001/api/testentity
:有效
https://localhost:5001/api/testentity?$filter=id%20eq%201
:有效
https://localhost:5001/api/testentity/1
:不起作用
https://localhost:5001/api/testentity(1)
:不起作用
这很奇怪,但是如果您将方法名称“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
让我分享更多细节,希望对您有所帮助。
--> 现在常规路由:
您注册了名为“ApplicationUser”的实体集,因此任何名为“ApplicationUserController”的控制器都被视为 OData 控制器。
“ApplicationUserController”中的任何操作都是潜在的 OData 方法。
“Get()”方法符合实体集常规路由规则,因此,本次“Get()”动作将构建两条OData路由。
- ~/v{版本}/ApplicationUser
- ~/v{version}/ApplicationUser/$count
- “GetById(long id)”不满足任何内置的常规路由规则,因此,此方法没有 OData 路由构建。
--> 现在对于属性路由:
由于您在控制器上装饰了“[ODataRouting]”,因此任何属性路由,例如 [HttpGet("ApplicationUser")] 都是潜在的 OData 属性路由。
OData 属性路由基于模型寄存器。您应该创建以路由前缀“v{version}”
开头的路由模板
因此,如果您将“[HttpGet("ApplicationUser/{id}")]”更改为 [HttpGet("v{version}/ApplicationUser/{id}")]
路由应该有效。
注意,如果你在"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/
这是我的 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”开头的用户。
第二个不行。我叫
http://localhost:5000/v1/ApplicationUser/1
http://localhost:5000/v1/ApplicationUser(1)
和 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 重现:
https://localhost:5001/api/testentity
:有效https://localhost:5001/api/testentity?$filter=id%20eq%201
:有效https://localhost:5001/api/testentity/1
:不起作用https://localhost:5001/api/testentity(1)
:不起作用
这很奇怪,但是如果您将方法名称“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
让我分享更多细节,希望对您有所帮助。
--> 现在常规路由:
您注册了名为“ApplicationUser”的实体集,因此任何名为“ApplicationUserController”的控制器都被视为 OData 控制器。
“ApplicationUserController”中的任何操作都是潜在的 OData 方法。
“Get()”方法符合实体集常规路由规则,因此,本次“Get()”动作将构建两条OData路由。
- ~/v{版本}/ApplicationUser
- ~/v{version}/ApplicationUser/$count
- “GetById(long id)”不满足任何内置的常规路由规则,因此,此方法没有 OData 路由构建。
--> 现在对于属性路由:
由于您在控制器上装饰了“[ODataRouting]”,因此任何属性路由,例如 [HttpGet("ApplicationUser")] 都是潜在的 OData 属性路由。
OData 属性路由基于模型寄存器。您应该创建以路由前缀“v{version}”
开头的路由模板因此,如果您将“[HttpGet("ApplicationUser/{id}")]”更改为 [HttpGet("v{version}/ApplicationUser/{id}")] 路由应该有效。
注意,如果你在"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/