nac*_*10f 5 validation asp.net-mvc viewmodel
asp.net mvc中一个常见的推荐做法是不要将业务模型发送到您的视图中.相反,您应该创建特定于每个视图的视图模型.
完成后,您在控制器中调用ModelState.IsValid方法,您将有效地检查viewmodel的有效性,但不检查业务对象的有效性.
处理这个问题的传统方法是什么?
public class Person
{
public int ID {get; set;};
[Required]
public string Name {get; set;}
[Required]
public string LastName {get; set;}
public virtual ICollection<Exam> Exams {get; set;}
}
public class PersonFormViewModel
{
public int ID {get; set;};
[Required]
public string Name {get; set;}
[Required]
public string LastName {get; set;}
}
Run Code Online (Sandbox Code Playgroud)
这正是我现在所拥有的,但我不确定[Required]属性是出现在两个模型上还是只出现在ViewModel上,或者只是商业模型上.
有关此问题的任何提示都表示赞赏.
更多链接支持我声称始终使用视图模型是一种常见的良好做法.
http://blogs.msdn.com/b/simonince/archive/2010/01/26/view-models-in-asp-net-mvc.aspx
我的偏好是在视图模型上进行输入验证,在域模型上进行业务验证.
换句话说,任何数据注释(如必填字段,长度验证,正则表达式等)都应在视图模型上完成,并在发生错误时添加到模型状态.
而且您可能拥有的业务/域规则不仅仅依赖于"表单",因此您应该在域模型中执行此操作(在映射后执行验证)或服务层.
我们所有的模型都有一个名为"Validate"的方法,我们在持久化之前在服务中调用它.如果业务验证失败,它们会抛出自定义异常,这些异常会被控制器捕获并添加到模型状态.
可能不是每个人的一杯茶,但它是一致的.
业务验证示例,如要求:
这是我们拥有的域模型的示例,它代表一般的"帖子"(问题,照片,视频等):
public abstract class Post
{
// .. fields, properties, domain logic, etc
public void Validate()
{
if (!this.GeospatialIdentity.IsValidForThisTypeOfPost())
throw new DomainException(this, BusinessException.PostNotValidForThisSpatial.);
}
}
Run Code Online (Sandbox Code Playgroud)
你看到那里,我正在检查业务规则,并抛出自定义异常.DomainException是我们的基础,我们有许多派生的实现.我们有一个名为enum的枚举BusinessException,它包含我们所有异常的值.我们在枚举上使用扩展方法来提供基于资源的错误消息.
这不仅仅是模型即时检查上的一个字段,例如"所有帖子必须有一个主题",因为虽然这是域的一部分,但它首先是输入验证,因此通过视图模型上的数据注释来处理.
现在,控制器:
[HttpPost]
public ActionResult Create(QuestionViewModel viewModel)
{
if (!ModelState.IsValid)
return View(viewModel);
try
{
// Map to ViewModel
var model = Mapper.Map<QuestionViewModel,Question>(viewModel);
// Save.
postService.Save(model); // generic Save method, constraint: "where TPost: Post, new()".
// Commit.
unitOfWork.Commit();
// P-R-G
return RedirectToAction("Index", new { id = model.PostId });
}
catch (Exception exc)
{
var typedExc = exc as DomainException;
if (typedExc != null)
{
// Internationalised, user-friendly domain exception, so we can show
ModelState.AddModelError("Error", typedExc.BusinessError.ToDescription());
}
else
{
// Could be anything, e.g database exception - so show generic msg.
ModelState.AddModelError("Error", "Sorry, an error occured saving the Post. Support has been notified. Please try again later.");
}
}
return View(viewModel);
}
Run Code Online (Sandbox Code Playgroud)
因此,当我们在服务上使用"Save"方法时,模型已通过输入验证.然后Save方法调用post.Validate(),调用业务规则.
如果引发异常,控制器会捕获它并显示消息.如果它通过了Save方法并且发生了另一个错误(例如,90%的时间,它是实体框架),我们会显示一般错误消息.
正如我所说,不是每个人都这样,但这对我们的团队来说很有效.我们清楚地分离了表示和域验证,以及从原始HTTP POST到成功后重定向的一致控制流.
HTH
| 归档时间: |
|
| 查看次数: |
2858 次 |
| 最近记录: |