我一直在关注关于如何使用 ASP.NET 构建我自己的 Web API 的教程。我已经完成了关于防止过度发帖的最后一节。据我了解,
TodoItem
类公开了特定模型的所有字段,包括秘密字段。 TodoItemDTO
类基本上是 TodoItem
的重复,但出于明显的安全原因,它可以防止秘密字段暴露给客户端。然而,这种技术违背了 DRY 原则。有更好的选择吗,还是这是唯一的方法?
但是,这种技术违背了 DRY 原则。
DTO 的目的是将领域逻辑层与表示逻辑层分离。尝试跨多个层应用 DRY 是完全无关的,因为分层影响的关注点分离才是更重要的因素。
良好的软件工程是平衡众多原则和模式的应用以实现最佳的最终结果,而不是教条地应用其中之一。
每条知识都必须在系统内有一个单一的、明确的、权威的表示
在这种特殊情况下,您可以将您的和
TodoItem
TodoItemDTO
视为独立的知识片段,因为“秘密字段”出于明显的安全原因不应暴露给客户。您可以尝试将“共享”部分移动到某些基类或接口,但我想说通常这是不值得的。
另请注意,代码重复是 DRY 违规的代码味道之一,但它仍然不一定意味着存在。作为 DTO 的替代方案,您可以使用匿名类型仅向客户发送特定项目:
如果您希望将实体类用于 POST/PUT 请求,您可以在控制器方法中使用
TryUpdateModelAsync()来防止过度发布。示例来自learn.microsoft.com
:
var emptyCourse = new Course();
if (await TryUpdateModelAsync<Course>(
emptyCourse,
"course", // Prefix for form value.
s => s.CourseID, s => s.DepartmentID, s => s.Title, s => s.Credits))
{
_context.Courses.Add(emptyCourse);
await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
您可以使用
和[JsonIgnore]
装饰您的属性。如果您使用 FromBody,[BindNever] 将被忽略。 我不会说使用实体类进行数据传输通常是一个坏主意。有一些优点(重用注释进行验证和 EF Core、节省映射器),但也有必须考虑的风险。