在Asp.Net Core 2.0和EF Core中,如何覆盖属性的验证属性?如果我在属性中添加[Required]注释,则会发生两件事:
ModelState
将此属性报告为验证失败(因此ModelState.IsValid
返回false
)->错误。此属性从HTML表单中排除,因为我仅在控制器中添加了FK值。我有一个带有“作者”必填属性的模型,该模型映射到IdentityUser。在数据库中,该列不应为空,但我不想在客户端和服务器之间传递用户ID。相反,当收到POST时,我只是从上下文中获取用户ID并在模型上设置FK属性。
因此,我想要的结果是一些数据注释,该注释指定该属性对于数据库目的是必需的,而对于ModelState而言,对于验证目的是可选的/跳过的。
模型
public class ArticleModel
{
[Required]
public string Title {get;set}
[Required]
public string Body {get;set;}
[Required]
public IdentityUser Author { get; set; }
[ForeignKey("Author")]
public string AuthorId { get; set; }
}
视图 (视图不了解或不在乎作者)
<div class="row">
<div class="col-md-4">
<form asp-action="Create">
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="Body" class="control-label"></label>
<input asp-for="Body" class="form-control" />
<span asp-validation-for="Body" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Title" class="control-label"></label>
<input asp-for="Title" class="form-control" />
<span asp-validation-for="Title" class="text-danger"></span>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-default" />
</div>
</form>
</div>
</div>
控制器的创建方法
(由于Author的无效状态,ModelState.IsValid始终为false)
[HttpPost]
[ValidateAntiForgeryToken]
[Authorize]
public IActionResult Create([Bind("Body,Title")] ArticleModel articleModel)
{
articleModel.AuthorId = User.FindFirstValue(ClaimTypes.NameIdentifier);
if (ModelState.IsValid)
{
DoStuff();
return RedirectToAction(nameof(Index));
}
return View(articleModel);
}
一个修正(丑陋,脆弱,并在多个处理程序上重复出现)
检查所有所需的字段均有效,然后忽略其余字段...
将
if (ModelState.IsValid)
替换为
if (ModelState.Where(k => k.Key != "Author").All(v => v.Value.ValidationState == ModelValidationState.Valid))
更好的(?)修复程序(正确-使用DTO)
我在这里尝试使用MS的默认脚手架,该脚手架采用模型并将其仅馈送到视图。过去,我通常使用DTO手动完成此操作,而这一切都是没有问题的。在Asp.Net Core时代,这仍然是更好的方法吗?
我认为可以找到的解决方法
在模型中。...
[Required]
[Validation(Mode=ValidationModes.Manual)]
public IdentityUser Author {get;set;}
答案 0 :(得分:1)
直接使用实体类绑定到POST等存在很多问题。需要不同验证规则的视图当然是其中之一,但是您还必须处理过分张贴,潜在的上下文冲突等问题。将实体类与“模型”相结合是ASP.NET MVC的原始缺点,不幸的是, Microsoft在阻止这种与ASP.NET Core的合并方面做得更好。简而言之,实体类不是模型。实体类有一个简单的用途,将数据库表行表示为一个对象。期。除此之外,将其用于其他任何事情都将导致问题。
简短的说,是的,您应该使用视图模型,DTO等。无论您怎么说,它们本质上都是同一件事。您正在创建一个类,以用于查看或从特定方法返回的目的,以使数据库表示与之分离。您的实体类应仅包含数据库所需的逻辑。您的视图模型/ DTO应该只包含它们所要馈送的逻辑。然后,将一个映射到另一个。这不仅可以解决您的问题,也可以解决其他问题,而且还可以消除代码中的依赖关系,这总是一件好事。