NET Core:使用 HttpGet 进行过滤

NET Core: Filtering with HttpGet

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

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

FilterDto

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

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

[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 标记。期望输入以一个有效的 JSON 标记,当 isFinalBlock 为真时。路径:$ | 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);
}

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

看看docs

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

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

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

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

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

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

按如下方式更改您的代码:

[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