首页 > 解决方案 > 您是否应该为参数创建一个 DTO,为正文创建一个 DTO,为查询创建一个,...?

问题描述

所以让我们假设你有一个 API 端点

您想创建一个 DTO 来获取和验证所有这些值。您可能知道整个请求不可能有一个 DTO 类,所以这不起作用:

public class Dto
{
    [FromRoute]
    public int Id { get; set; }

    [FromBody]
    public int Foo { get; set; }
}

解析器只会设置Foo字段并忽略该Id字段。调用https://localhost:5001/foo/1时,该Id字段的默认值为 0,而不是 1。可以为 url 参数创建一个 DTO,为正文创建一个 DTO,为查询创建一个 DTO,如下所示

public class ParamsDto
{
    public int FirstId { get; set; }
    public int SecondId { get; set; }
}

// ... same for the body and queries ...

然后你可以像这样标记那些 dto [FromRoute] ParamsDto paramsDto, [FromBody] BodyDto bodyDto, [FromQuery] QueryDto queryDto。您可能有一个多层架构,并且您的 Web API 项目与一个需要 DTO 的层通信,该 DTO 是上面显示的所有 3 个 DTO 的组合。因此,您必须将这 3 个对象合并为一个大 DTO,例如使用AutoMapper将请求 DTO 转换为命令对象(来自Mediatr)。

在文件夹结构、命名约定等方面是否有处理多个 DTO 的最佳实践?因为您可能必须为 params 创建一个 DTO,为 body创建一个 DTO,而不是调用 DTOUpdateProductAmountFromOrderByIds来获取orderId,productId和(of products) 。我知道这不是最好的例子,因为这里并不真正需要 DTO,但我们假设您将对 ID 进行复杂的验证,并且正文包含多个值。你不想在你的控制器文件中有那么多的验证注解。在将这些单独的 DTO 合并为一个大的方面,这种方法对我来说看起来真的很混乱,所以也许有更好的方法。amountUpdateProductAmountFromOrderByIdsParamsDtoUpdateProductAmountFromOrderByIdsBodyDto

标签: c#.net-coreasp.net-core-webapidto

解决方案


这是 asp.net core 3.0 的工作演示:

模型:

public class Dto
{
    [FromRoute(Name = "")]
    public Test Test { get; set; }

    [FromBody]
    public Sample Sample { get; set; }
    public ApiVersion ApiVersion { get; set; }
}
public class Test
{
    public string Col1 { get; set; }
    public int Col2 { get; set; }
    public bool Col3 { get; set; }
}
public class ApiVersion
{
    public int VersionId { get; set; }
    public string VersionName { get; set; }
}
public class Sample
{
    public int Foo { get; set; }
    public string Name { get; set; }
}

控制器:

[ApiController]
[Route("api/[controller]")]
public class ValuesController : Controller
{
    // GET: api/<controller>
    [HttpGet("col1/{col1}/col2/{col2}/col3/{col3}")]
    public async Task<IActionResult> Get([FromQuery]Dto dto)
    {           
        return Ok(dto);
    }
}

请求网址:https://localhost:44393/api/values/col1/1/col2/2/col3/true?apiversion.versionId=1&apiversion.versionName=aaa

结果: 在此处输入图像描述

更新:

public class Dto
{
    //[FromRoute(Name = "")]
    //public Test Test { get; set; }
    [FromRoute]
    public string Col1 { get; set; }
    [FromRoute]
    public int Col2 { get; set; }
    [FromRoute]
    public bool Col3 { get; set; }
    [FromBody]
    public Sample Sample { get; set; }
    public ApiVersion ApiVersion { get; set; }
}

推荐阅读