【问题标题】:OData v4 Query To Filter Results In A Complex ObjectOData v4 查询以过滤复杂对象中的结果
【发布时间】:2021-06-22 20:24:48
【问题描述】:

我开发了一个 .NET Core v5 WebAPI 和 Integrated OData v4。 如果我从控制器返回正常的学生列表并执行 OData 查询,一切都会正常工作。

但我的 API 有一个标准的成功和失败响应结构。一切都只在 data 属性中。

{
    "status": "SUCCESS",
    "data": [
        {
            "name": "Student A",
            "age": 10
        },
        {
            "name": "Student B",
            "age": 11
        },
        {
            "name": "Student C",
            "age": 12
        },
        {
            "name": "Student D",
            "age": 13
        }
    ]
}

fetch Students with age > 11 的 OData URL 查询可以是什么。这是我尝试过的

https://localhost:44351/api/v2/Students/GetAll?$filter=data/age gt 11

但它抛出了这个错误

这是我的终点。 此外,我只为搜索、过滤、排序和计数配置了 OData。展开不是我现在考虑的事情

[HttpGet]
[MapToApiVersion("2.0")]
[Route("Success")]
[EnableQuery]
public IActionResult Success20()
{
    var listOfData = new List<Student>();
    listOfData.Add(new Student { Name = "Student A", Age = 10 });
    listOfData.Add(new Student { Name = "Student B", Age = 11 });
    listOfData.Add(new Student { Name = "Student C", Age = 12 });
    listOfData.Add(new Student { Name = "Student D", Age = 13 });
    return Ok(new SuccessResponse<List<Student>>
    {
        Data = listOfData
    });
}

这是我对成功的标准回应

public class Response
{
    protected ResponseStatus ResponseStatus { get; set; }
    public string Status { get; set; }
}

public class SuccessResponse<T> : Response
{
    public T Data { get; set; }

    public SuccessResponse()
    {
        ResponseStatus = ResponseStatus.SUCCESS;
        Status = ResponseStatus.SUCCESS.ToString();
    }
}

【问题讨论】:

    标签: c# rest asp.net-core odata webapi


    【解决方案1】:

    根据您的响应结构,我想您在 API 控制器中返回了一个匿名类型,代码如下,对吧?

        [EnableQuery]
        public IActionResult Get()
        {
            var result = _db.Students.ToList();
            return Ok(new { status = "success", data = result }); 
        }
    

    据我所知,OData 并非设计用于匿名类型(如果使用上述代码,它将显示您遇到的错误)。因此,为了解决这个错误,您可以创建包含statusdata 的ResponseModel,然后将其返回给客户端并过滤数据。

    这样的代码:

    public class ResponseModel
    {
        [Key]
        public string status { get; set; }
        public List<Student> data { get; set; }
    }
    

    API 控制器:

        [EnableQuery]
        public IActionResult Get()
        {
            var result = _db.Students.ToList();
            //return Ok(new { status = "success", data = result });
            return Ok(new ResponseModel { status="success", data = result});
        }
    

    然后,在GetEdmModel()方法中更改EntitySet模型:

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

    之后,我们可以使用 url 过滤数据:https://localhost:44387/odata/Students?$expand=data($filter= age gt 11)

    结果如下:

    【讨论】:

    • 感谢@ZhiLv 的建议。但是,我发送的不是匿名对象,而是通用对象。我已经修改了我的问题以包括我的端点。 (为简单起见,静态服务学生名单)
    【解决方案2】:

    我找到了解决方案。 原因是排除了 Expand on OData。 我添加了 Expand() 指的是@ZhiLv 的回答

    查询现在正在运行。

    【讨论】:

      猜你喜欢
      • 2012-10-15
      • 2021-05-03
      • 2021-05-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-12
      相关资源
      最近更新 更多