Asp.net MVC源码分析--Model Validation(Server端)实现(1)
一.MVC Validation 用法:
在Asp.net MVC 框架中如果需要对Model 对象加入验证,我们可以在Model的属性上标记所有继承于ValidationAttribute的Attribute特性.
例如下面的代码中,StringLength/Range/Compare 都是继承于ValidationAttribute类.
public class LogOnModel
{
[Required]
[StringLength(10)]
public string UserName { get; set; }
[Required]
[Range(5,10)]
public string Password { get; set; }
[Compare("NewPassword", ErrorMessage = "The new password and confirmation password do not match.")]
public string ConfirmPassword { get; set; }
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
复制代码
在Action 中我们可以调用 ValidateModel 方法对Model对象进行验证,如果验证没有通过则会抛出InvalidOperationException异常,同时ModelState.IsValid状态为false
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
this.ValidateModel(model);
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
复制代码
这里需要注意的是如果我们不调用ValidateModel 方法Action上的Model对象默认也是能够验证的,这是因为在绑定对象阶段DefaultModelBinder.BindComplexElementalModel方法中MVC触发了验证的方法。
DefaultModelBinder.cs
internal void BindComplexElementalModel(ControllerContext controllerContext, ModelBindingContext bindingContext, object model) {
// need to replace the property filter + model object and create an inner binding context
ModelBindingContext newBindingContext = CreateComplexElementalModelBindingContext(controllerContext, bindingContext, model);
// validation
if (OnModelUpdating(controllerContext, newBindingContext)) {
BindProperties(controllerContext, newBindingContext);
OnModelUpdated(controllerContext, newBindingContext);
}
}
protected virtual void OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) {
Dictionary<string, bool> startedValid = new Dictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
foreach (ModelValidationResult validationResult in ModelValidator.GetModelValidator(bindingContext.ModelMetadata, controllerContext).Validate(null)) {
string subPropertyName = CreateSubPropertyName(bindingContext.ModelName, validationResult.MemberName);
if (!startedValid.ContainsKey(subPropertyName)) {
startedValid[subPropertyName] = bindingContext.ModelState.IsValidField(subPropertyName);
}
if (startedValid[subPropertyName]) {
bindingContext.ModelState.AddModelError(subPropertyName, validationResult.Message);
}
}
}
复制代码
二.ValidateModel方法源码分析
下面我们看一下MVC 是如何实现ValidateModel方法验证的.
1 protected internal void ValidateModel(object model) {
2 ValidateModel(model, null /* prefix */);
3 &n
补充:Web开发 , ASP.Net ,