使用 OData 8 设置自定义路由

Set custom route using OData 8

最近我更新到 OData 8.0.10。我在我的 Startup.cs 文件中添加了这个:

services.AddRouting();
services.AddControllers().AddOData(opt => 
opt.AddRouteComponents("odata", GetEdmModel()).Filter().Select().OrderBy().Count());

哪里

private static IEdmModel GetEdmModel()
{
    ODataConventionModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<Project>("Project");
    return builder.GetEdmModel();
}

我有这个小控制器

[Route("api/[controller]")]
[ApiController]
public class ProjectController : ControllerBase
{
    [HttpGet]
    [EnableQuery(PageSize = 20)]
    public IQueryable<Project> GetAsync()
    {
        var projects = _projectRepository.GetAll();
        return projects;
    }

    [HttpGet("{id}", Name = "GetProjectById")]
    public async Task<ActionResult> GetAsyncById(long id)
    {
        var project = await _projectService.GetProjectByIDAsync(id);
        return Ok(project);
    }

    [HttpPatch("{id}", Name = "PatchProjectById")]
    public async Task<ActionResult> PatchProject(long id, [FromBody] ProjectPatchDetails projectPatch)
    {
        var project = await _projectRepository.GetAsync(id);
        var updated = await _projectService.UpdateProjectAsync(id, project, projectPatch);
        return Ok(updated);
    }
}

具有三个端点,其中一个由 [EnableQuery] 注释,其余则没有。当我访问 api/project?$count=true&$skip=0&$orderby=CreateDate%20desc 时,我得到一个分页信息(20 条记录),但我没有得到 @odata.context 和 @odata.count。如果我使用 odata/ 前缀访问 /odata/project?$count=true&$skip=0&$orderby=CreateDate%20desc,它会给我 @odata.context 和 @odata.count。我尝试将 AddRouteComponents 更改为 AddRouteComponents("api", GetEdmModel()) 但在这种情况下我收到以下错误:

"The request matched multiple endpoints. Matches: MyApp.Api.Controllers.ProjectController.GetAsync (MyApp.Api) MyApp.Api.Controllers.ProjectController.GetAsync (MyApp.Api)"

在这种情况下我有多个问题:

  1. 有没有办法将 odata 重新路由到 api,将 /odata 前缀设为 /api 并使其工作?
  2. 我是否应该制作另一个控制器来存储所有 OData 标记的操作,如果可能的话,这样可能会解决这个问题?

我认为您的 ProjectController 应该继承自 ODataController 而不是 ControllerBase。使用 ODataController,您应该获得 context url@odata.count

@anthino

  1. 有没有办法将 odata 重新路由到 api,将 /odata 前缀设为 /api 并使其工作?

如果加了'opt.AddRouteComponents("api", GetEdmModel())',记得去掉 [Route("api/[controller]")]等属性路由

  1. 我是否应该创建另一个控制器来存储所有 OData 标记的操作,如果可能的话,这样可能会解决这个问题?

基本上,最好创建两个控制器,一个用于odata,另一个用于其他。在您的场景中,您将它们混合在一起。你应该小心这一点。您可以使用 'app.UseODataRouteDebug()' 中间件来帮助您调试。