此MSDN link解释了为什么将DTO类用于Web API是一种好习惯。这是可以理解的,令我困惑的是在同一页面中,post方法使用模型类而不是简单的DTO如下:
[ResponseType(typeof(BookDTO))]
public async Task<IHttpActionResult> PostBook(Book book)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
db.Books.Add(book);
await db.SaveChangesAsync();
// New code:
// Load author name
db.Entry(book).Reference(x => x.Author).Load();
var dto = new BookDTO()
{
Id = book.Id,
Title = book.Title,
AuthorName = book.Author.Name
};
return CreatedAtRoute("DefaultApi", new { id = book.Id }, dto);
}
我猜我的问题是:发布/投放操作应采用模型还是DTO参数?
更新: 从答案看来,即使在后期处理中也建议使用dto,但这将引发另一个问题,如何在后期处理中将dto映射到Model类?假设我们使用AutoMapper,我发现许多链接,例如this和this都警告不要在反向映射中使用它(即dto => Model类)。
答案 0 :(得分:1)
对于我的个人项目和正在工作的项目,我所遵循的约定是我们将使用附加了Request
或Response
的DTO对象,以帮助维护和提供清晰的API表面每个人都可以理解。
public CreateBookResponse CreateBook(CreateBookRequest request)
{
}
此外,在某些情况下,根据Web服务的需要,我们使用HttpResponseMessage
,IActionResult
或其他返回值,但是明确定义了请求和响应对象使操作非常容易对于我们所有的开发人员,甚至包括诸如ASP之类的不同技能的开发人员,都可以理解生成的JSON结构。
我建议不要直接暴露业务实体或数据访问对象。这些中的每一个在您的应用程序体系结构中都有不同的用途,您可能会暴露太多的细节,或者发现维护跨领域的问题很困难。
答案 1 :(得分:0)
首先,是的,您应该始终使用DTO。无论您是使用常规网站还是使用API,都应该从不直接保存从帖子数据实例化的对象。这打开了一个巨大的安全漏洞,人们可以在其中操纵帖子数据并进行各种恶作剧。具有讽刺意味的是,您实际上可以绑定到您的实体类,但是如果这样做,则永远不要保存该实例,而应该创建一个新实例,映射到已发布实例的数据上,然后保存您创建的该实例-这很重要部分永远不会保存发布的实例。使用视图模型/ DTO可以使您更加明显地知道应该对等式进行映射,因此是推荐的方法。
就AutoMapper而言,建议不要用于反向映射,因为映射到要保存到数据库的内容涉及许多细微差别。特别是当您涉及到诸如实体框架之类的ORM时。您可以使用AutoMapper,但您只需要了解所有这些细微差别并进行相应处理即可。一般而言,在这些情况下,手动进行映射可能更容易,因为它通常涉及对AutoMapper之类的大量配置,因此从长远来看您不会节省很多精力。听起来就像手动映射。如果要创建新的Book
,则只需新建一个Book
的实例。如果要修改现有的Book
,请从数据库中提取该实例。无论哪种方式,您现在都有一个Book
的实例和一个BookDTO
之类的实例,它们是从发布数据中创建的。然后您就可以:
book.Title = bookDto.Tile;
// etc.
对于类似作者关系的内容,您可能需要执行其他查询。例如:
var author = _context.Authors.SingleOrDefault(x => x.Name == bookDto.AuthorName);
book.Author = author;
答案 2 :(得分:0)
简短的回答:由您决定。
更长的答案:我想将DTO视为一种层(例如服务)从简单/平面数据结构中接收数据或将数据暴露于外部的方式。通过此定义,Web Api中的模型只是DTO的一种,您可以在其中添加验证属性(例如,Required,MinLength等),并且api控制器可以通过检查ModelState.IsValid(并且它是错误)。但是您也可以在DTO类中添加这些属性。因此,实际上差别不大。