【问题标题】:OData ASP.Net Core on GET with Id?带有 ID 的 GET 上的 OData ASP.Net Core?
【发布时间】:2019-09-23 06:18:53
【问题描述】:

我正在尝试[EnableQuery] 以 id 作为示例的路线(用户),如果我执行以下操作:

GET /users/1?$expand=Character

我想获取 ID 为 1 的用户及其字符,但目前它在字符上返回 null:

{"character":null,"id":1,"username":"Iterer","password":"motdepasse","characterId":1}

但是在获取所有用户的(全局)路线上:

GET /users?$expand=Character

如您所见,我得到了用户的角​​色:

[{"character":{"id":1,"name":"Name"},"id":1,"username":"Iterer","password":"motdepasse","characterId":1}]

这是我的控制器的操作:

    // GET: api/Users
    [HttpGet]
    [EnableQuery]
    public ActionResult<IQueryable<UserEntity>> GetUsers()
    {
        return Ok(_context.Users);
    }

    // GET: api/Users/5
    [HttpGet("{id}")]
    [EnableQuery]
    public ActionResult<IQueryable<UserEntity>> GetUserEntity(long id)
    {
        var userEntity = _context.Users.Where(u => u.Id == id).FirstOrDefault();

        if (userEntity == null)
        {
            return NotFound();
        }

        return Ok(userEntity);
    }

两者都使用 IQueryable 接口,但我仍然不明白为什么它不起作用,这是完整的控制器:

https://github.com/myerffoeg/gaium-api/blob/master/Gaium/Controllers/UsersController.cs

还有我的启动文件:

https://github.com/myerffoeg/gaium-api/blob/master/Gaium/Startup.cs

此外,如果您有一些最佳实践可以分享,我们将不胜感激!

【问题讨论】:

  • 尝试 odata 语法 GET /users(1)?$expand...
  • 当我尝试 GET /users(1) 或 /Users(1) 我得到 404。
  • 好的,那么您缺少在启动时配置的 odata 路由前缀,例如 /odata/users(1)...
  • 我添加了我的 MapODataServiceRoute 与 api 作为路由前缀 & 我扩展了我的控制器上的 ODataController 但我仍然得到一个带有 /users(1) 的 404。
  • 看看他的 github-repo:github.com/damienbod/AspNetCoreOData

标签: c# asp.net-core entity-framework-core odata


【解决方案1】:

两者都使用 IQueryable 接口,但我仍然不明白为什么它不起作用

嗯,不同的是,虽然“非工作”方法声称返回IQueryable&lt;UserEntity&gt;

public ActionResult<IQueryable<UserEntity>> GetUserEntity(long id)

实现返回单个具体化的UserEntity 实例。

为了匹配声明,实现应该是这样的(基本上是第一个应用Where子句的方法):

return Ok(_context.Users.Where(u => u.Id == id));

【讨论】:

  • 通过这样做,我得到了一个 json 数组(其中包含我的角色)[{...}] 但我希望它成为一个对象:{} 我该如何做到这一点?
  • 嗯,以上是基于你的方法定义。我对 OData 不太熟悉,但从 EF Core 的角度来看,如果您返回物化对象,那么在其上应用 expandselect 等运算符为时已晚——它们需要访问底层查询。跨度>
  • @Myerffoeg:Ivan Stoev 的观点完全正确。如果你调用 FirstOrDefault();你已经完成了 DB-call。只需删除 FirstOrDefault ,一切都会按预期工作。另请参阅延迟执行以了解更多的方式和原因..
【解决方案2】:

参数名称应该是key而不是id,即

    [EnableQuery]
    public IActionResult Get(int key)
    {
       return Ok(_repository.Get(key));
    }

【讨论】:

    【解决方案3】:

    如 Ivan 所述,您的代码返回单个实体化实体。您确实需要返回IQueryable&lt;UserEntity&gt;,但正如您在评论中所说:

    return Ok(_context.Users.Where(u =&gt; u.Id == id));

    将返回一个具有单个实体的 Array,而不是您想要的。

    您需要使用SingleResult 告诉 OData 此查询将仅返回零个或一个实体:

    return Ok(SingleResult.Create(_context.Users.Where(u =&gt; u.Id == id)));

    这将返回您想要的:单个实体(无数组),可以应用 $expand。

    【讨论】:

      猜你喜欢
      • 2017-12-02
      • 2018-02-17
      • 2016-11-19
      • 2018-09-27
      • 1970-01-01
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多