【问题标题】:NET Core: Filtering with HttpGetNET Core:使用 HttpGet 进行过滤
【发布时间】:2021-07-11 09:09:45
【问题描述】:

我想通过使用 httpGet 的 makeId 过滤车辆列表。我希望使用的 URL 是: https://localhost:5001/api/vehicle?makeId=2

下面,我将定义我用于此任务的 DTO 和控制器方法:

FilterDto

public class FilterDTO
{
    public int? MakeId { get; set; }
}

以下是我的控制器类中的 2 个 HTTPGet 方法。我希望调用第一个方法。

[HttpGet]
public async Task<IEnumerable<VehicleDTO>> Get(FilterDTO filterDto)
{
    var filter = _mapper.Map<Filter>(filterDto);
    var vehicles = await _vehicleRepository.GetAll(filter);
    return _mapper.Map<IEnumerable<VehicleDTO>>(vehicles);
}

[HttpGet("{id}")]
public async Task<ActionResult<VehicleDTO>> Get(long id)
{
    var vehicle = await _vehicleRepository.GetWithRelated(id);

    if (vehicle == default)
    {
        return BadRequest("Vehicle not found");
    }

    var result = _mapper.Map<VehicleDTO>(vehicle);
    return Ok(result);
}

使用上面的代码,当我调用上面的 URL 时,在 Postman 中我得到一个 400 错误,说“输入不包含任何 JSON 令牌。当 isFinalBlock 为真时,期望输入以有效的 JSON 令牌开头。路径:$ | LineNumber:0 | BytePositionInLine:0。” 我对 https://localhost:5001/api/vehicle 得到了相同的结果

如果我像下面这样更改第一个 Get 方法,我可以得到响应:

[HttpGet]
public async Task<IEnumerable<VehicleDTO>> Get(int? makeId)
{
    var filter = new Filter { MakeId = makeId};
    var vehicles = await _vehicleRepository.GetAll(filter);
    return _mapper.Map<IEnumerable<VehicleDTO>>(vehicles);
}

在这个(冗长的)介绍之后,我的问题是:

  • 为什么 HttpGet 支持“int”?但不是数据传输对象“FilterDto”?
  • 我应该使用不同的动词来代替 HttpGet 吗?
  • 将来我可能需要过滤一些其他类型(比如 customerId)。有什么方法可以更改方法以支持自定义对象,例如 FilterDto,理想情况下不更改动词?

【问题讨论】:

  • 这个问题可能会有所帮助:stackoverflow.com/questions/36280947/…
  • @Luuk 我想传递一个参数,而不是 4(请参阅 Bob 大叔的话),但在最坏的情况下我会尝试这个。
  • 使用 [FromQuery] 属性,你可以使用 DTO 作为参数
  • @SinaRiani 如果可以,请将其作为答案发布

标签: .net-core filtering http-get


【解决方案1】:

更改您的代码如下:

[HttpGet]
public async Task<IEnumerable<VehicleDTO>> Get([FromQuery] FilterDTO filterDto)
{
    var filter = _mapper.Map<Filter>(filterDto);
    var vehicles = await _vehicleRepository.GetAll(filter);
    return _mapper.Map<IEnumerable<VehicleDTO>>(vehicles);
}

然后这样称呼它:

baseUrl/Controller/Get?MarkId=1

【讨论】:

    【解决方案2】:

    看看docs

    基本支持原始类型,但控制器不知道如何将 Web 请求数据转换为 C# 对象。您需要明确告诉它您希望如何根据 Web 请求创建此自定义对象。

    【讨论】:

    • 感谢您的快速答复。我相信你可能是对的。我将在接下来的几个小时内对此进行测试并返回结果。你知道为什么这不适用于 HttpPut 或 Post 吗?在那里我可以安全地使用带有签名的方法:[HttpPut("{id}")] public async Task&lt;ActionResult&lt;VehicleDTO&gt;&gt; Update(long id, SaveVehicleDTO vehicleDTO)
    【解决方案3】:

    您可能已经想到 HttpGet 方法只能接收原始类型(字符串、整数、短、日期时间 - 使用特定格式 -),因为参数是通过查询字符串发送的,例如:

    myAddres.com/api/mymethod?id=5&filter1=value1&filter2=value2
    

    考虑到这一点,您会注意到无法发送任何对象,因为您需要使用 json 或其他表示法,请记住查询字符串有限制,因此使用“argument=value”表示法更好。

    另一方面,PUT 和 POST 能够通过“body”属性发送它们的数据,您可以在其中使用 json 表示法,这样您就可以在后端创建几乎任何对象。

    如果您需要使用对象作为参数,最好使用 POST 或 PUT(POST 比 PUT 更好)。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-02
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    • 2021-11-07
    相关资源
    最近更新 更多