在调用PUT(编辑)端点时,如何从模型中省略变量?

时间:2015-08-31 20:24:43

标签: c# asp.net-mvc entity-framework asp.net-web-api asp.net-web-api2

我有一个处理各种对象的ASP.NET WEB API 2服务。我们使用此服务来执行基本的CRUD功能。它们都非常简单,但在尝试编辑对象时遇到了一个问题。

我会让代码解释一下:

    [HttpGet]
    [Route("{companyId}")]
    public IHttpActionResult GetCompanyByCompanyId([FromUri] int companyId)
    {
        // get company
    }

    [HttpPost]
    [Route("")]
    public IHttpActionResult AddCompany([FromBody] CompanyDto companyModel)
    {
        // Insert a company
    }

    [HttpPut]
    [Route("{companyId}")]
    public IHttpActionResult UpdateCompany([FromUri] int companyId, [FromBody] Company companyModel)
    {
        // Update the company
    }

所以我所做的就是创建公司和公司的Dto模型。两者之间的唯一区别是CompanyDto不包含id。这样我们就可以发布对象并让数据库告诉我们id是什么。

在我们创建了公司对象之后,我们现在拥有了我们的ID。现在我们要编辑这个对象。我们将完整的Company对象传递给PUT方法,并让它覆盖所有值。但是,公司模型中有一个变量/属性,我们不允许更新。显然,我可以省略它被传递到存储库层中的数据库。但是,我不想混淆这项服务的消费者。我想只公开所需或可编辑的参数。我们应该怎么做?

以下是公司和公司的模型供参考:

public class Company
{
    [Required]
    [Range(1, int.MaxValue)]
    public int CompanyId { get; set; }

    [Required]
    [MaxLength(20)]
    public string CompanyName { get; set; }

    [Range(1, int.MaxValue)]
    public int DataCenterId { get; set; }
 }

 public class CompanyDto
 {
    [Required]
    [MaxLength(20)]
    public string CompanyName { get; set; }

    [Required]
    [Range(1, int.MaxValue)]
    public int DataCenterId { get; set; }
 }

请注意,当我们发布CompanyDto时,我们提供DataCenterId,但是当我们编辑Company对象时,我们不应该允许编辑DataCenterId。当我们获取Company对象时,我们应该接收所有3个属性。我是否需要制作第3个模型来实现这一目标,还是有数据注释可以帮助我实现这一目标?我们不是顺便使用EF。我们有自己的内部ORM解决方案。

1 个答案:

答案 0 :(得分:0)

要使解决方案完整并且自动生成的帮助是最正确的,是的,您将必须创建第三个DTO对象,该对象仅包含客户端实际允许编辑的那些属性。这是使用这些URI向消费者传达正确消息的唯一方法:

但是,如果您可以并且愿意更改URI:s并且如果它们恰好是您的域的更具描述性的变体,我还建议您考虑公司ID是否可以驻留在URI本身。这样你就可以把它从DTO中拿出来,而你不必为此而设置不同的类。

此外,PUT方法应将CompanyDto对象作为参数,因为URI中已提供公司ID。否则,如果URI公司ID与请求中Company对象中的公司ID不同,则用户期望发生什么?

还要注意,您不应将这些DTO这样交付到业务逻辑层,我怀疑您现在正在基于Company对象作为PUT方法的参数。相反,业务层应该定义另一个对象,并且应该将WebAPI对象映射到该对象,包括来自URI的ID。这样,对底层业务层DTO的更改不会破坏实际的公共API,即WebAPI。

我在以前的公司中有一个非常漂亮的系统我今天继续使用,我们将所有传入的类命名为请求类,即CompanyRequest,将所有传出的类命名为响应类,即CompanyResponse。这样,响应可以通过例如数据中心的名称来丰富,因为在查看公司实体时几乎总是需要它。然后,该名称不应出现在请求对象上,因为不应通过编辑公司来编辑该名称。