Data Annotations and Validdation -By Scott Allen

 

本章内容

  • 为验证添加数据注解
  • 创建自定义验证逻辑
  • 使用元数据模型注解

 

-使用验证注解

 

Required

[Required]
public string FirstName { get; set; }
[Required]
public string LastName { get; set; }

 

StringLength

[Required]
[StringLength(160)]
public string FirstName { get; set; }
[Required]
[StringLength(160)]
public string LastName { get; set; }

 

RegularExpression

[RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”)]
public string Email { get; set; }

 

Range

[Range(35,44)]
public int Age { get; set; }

[Range(typeof(decimal), “0.00”, “49.99”)]
public decimal Price { get; set; }

 

 

-Validation Attributes from System.Web.Mvc

 

Remote

[Remote(“CheckUserName”, “Account”)]
public string UserName { get; set; }

public JsonResult CheckUserName(string username)
{
    var result = Membership.FindUsersByName(username).Count == 0;
    return Json(result, JsonRequestBehavior.AllowGet);
}

 

 

Compare

[RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”)]
public string Email { get; set; }
[Compare(“Email”)]
public string EmailConfirm { get; set; }

 

自定义错误信息及本地化

[RegularExpression(@”[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}”,
                   ErrorMessage=”Email doesn’t look like a valid email address.”)]
public string Email { get; set; }

[Required(ErrorMessage=”Your last name is required”)]
[StringLength(160, ErrorMessage=”Your last name is too long”)]
public string LastName { get; set; }
[Required(ErrorMessage=”Your {0} is required.”)]
[StringLength(160, ErrorMessage=”{0} is too long.”)]
public string LastName { get; set; }

读取资源文件(下面代码假设资源文件名为ErrorMessages.resx,它包含LastNamerequired及LastNameTooLong):

[Required(ErrorMessageResourceType=typeof(ErrorMessages),
          ErrorMessageResourceName=”LastNameRequired”)]
[StringLength(160, ErrorMessageResourceType = typeof(ErrorMessages),
              ErrorMessageResourceName = “LastNameTooLong”)]
public string LastName { get; set; }

 

-了解注解是如何工作的

首先,mvc框架是在模型绑定期间执行验证逻辑。如第四章介绍的,下面两种情况都会触发模型绑定:

[HttpPost]
public ActionResult Create(Album album)
{
    // the album parameter was created via model binding
    // ..
}


[HttpPost]
public ActionResult Edit(int id, FormCollection collection)
{
    var album = storeDB.Albums.Find(id);
    if(TryUpdateModel(album))
    {
// ...
    }
}

当模型绑定完成属性更新后,模型绑定通过当前模型的元数据来获取所有验证。运行时提供了DataAnnotationsModelValidator来处理数据注解,它能够找到所有验证属性并执行验证逻辑。模型绑定会捕获所有验证失败的规则并存放在模型状态中。

模型绑定时会对模型状态产生影响,这不仅是因为模型状态包含了所有属性值,模型状态还包含了所有属性的关联错误(每个错误又与模型对像本身相关联)。如果模型状态里面包含错误,那么ModelState.isValid的值将返回false。

假设用户在付款时没有填写LastName就将信息提交了,由于Required验证注解的作用,下面的表达式在模型绑定后都会返回ture:

ModelState.IsValid == false
ModelState.IsValidField(“LastName”) == false
ModelState[”LastName”].Errors.Count > 0

 

查看错误信息:

var lastNameErrorMessage = ModelState[“LastName”].Errors[0].ErrorMessage;

 

当然,你极少情况下需要这样去查看错误信息。直接在视图中使用Validationmessage helper显示错误信息即可:

@Html.ValidationMessageFor(m => m.LastName)

 

控制器行为通常只需要判断ModelState是否为已验证就行了。

[HttpPost]
public ActionResult AddressAndPayment(Order newOrder)
{
    if (ModelState.IsValid)
    {                
        newOrder.Username = User.Identity.Name;
        newOrder.OrderDate = DateTime.Now;
        storeDB.Orders.Add(newOrder);
        storeDB.SaveChanges();
         // Process the order
        var cart = ShoppingCart.GetCart(this);
        cart.CreateOrder(newOrder);                
        return RedirectToAction(“Complete”, new { id = newOrder.OrderId });
    }
    // Invalid -- redisplay with errors
    return View(newOrder);         
}
[HttpPost]
public ActionResult AddressAndPayment(FormCollection collection)
{
    var newOrder = new Order();
    TryUpdateModel(newOrder);
    if (ModelState.IsValid)
    {  
newOrder.Username = User.Identity.Name;
        newOrder.OrderDate = DateTime.Now;
        storeDB.Orders.Add(newOrder);
        storeDB.SaveChanges();
         // Process the order
        var cart = ShoppingCart.GetCart(this);
        cart.CreateOrder(newOrder);                
        return RedirectToAction(“Complete”, new { id = newOrder.OrderId });
    }
    // Invalid -- redisplay with errors
    return View(newOrder);         
}

 

 

-自定义验证逻辑

自定义注解

using System.ComponentModel.DataAnnotations;

public class MaxWordsAttribute : ValidationAttribute
{
    public MaxWordsAttribute(int maxWords):base(“{0} has too many words.”)
    {
        _maxWords = maxWords;
    }
    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
    if (value != null) { var valueAsString = value.ToString(); if (valueAsString.Split('').Length > _maxWords) { var errorMessage = FormatErrorMessage( validationContext.DisplayName); return new ValidationResult(errorMessage); } } return ValidationResult.Success; } private readonly int _maxWords; }
[Required]
[StringLength(160)]
[MaxWords(10)]
public string LastName { get; set; }


[Required]
[StringLength(160)]
[MaxWords(10, ErrorMessage=”There are too many words in {0}”)]
public string LastName { get; set; }

 

 

IValidatableObject

public class Order : IValidatableObject 
{
    public IEnumerable<ValidationResult> Validate(
                           ValidationContext validationContext)
    {
        if (LastName != null &&
            LastName.Split(‘ ‘).Length > 10)
        {
            yield return new ValidationResult(“The last name has too many words!”, 
                                             new []{“LastName”});
        }
    }
    
    // rest of Order implementation and properties
    // ...
}

 

当需要通过多个属性来判断验证结果时,可以使用这种方法来自定义验证。

 

-用于显示与编辑的注解

 

Display

[Required]        
[StringLength(160, MinimumLength=3)]
[Display(Name=”First Name”)]
public string FirstName { get; set; }
[Display(Name = “Last Name”, Order = 15001)]
[MaxWords(10, ErrorMessage = “There are too many words in {0}”)]
public string LastName { get; set; }
[Required]        
[StringLength(160, MinimumLength=3)]       
[Display(Name=”First Name”, Order=15000)]
public string FirstName { get; set; }        

Order的作用是排序,默认值是10000,各项会以该值按升序排列。

 

ScaffoldColumn

[ScaffoldColumn(false)]
public string Username { get; set; }

作用是在EditorForModel及DisplayForModel中隐藏相关字段。

 

DisplayFormat

[DisplayFormat(ApplyFormatInEditMode=true, DataFormatString=”{0:c}”)]
public decimal Total { get; set; }

result:
$12.10

 

 

ReadOnly

[ReadOnly(true)]        
public decimal Total { get; set; }

 

设置了ReadOnly的属性在模型绑定时不会被更新值。

 

DataType

[Required]
[DataType(DataType.Password)]
[Display(Name = “Password”)]
public string Password { get; set; }

 

除了Password,还有其他类型设置: Currency, Date, Time, and MultilineText

 

HiddenInput

生成一个type类型为hidden的input元素

 

-SUMMARY

本章你了解了如何给验证添加数据注解,运行时如何使用模型元数据及模型绑定。验证同时提供了客户端及服务端的验证而无需编写额外的代码。另外你还学习了如何创建自定义验证,如何通过数据注解来改变html helper所生成的html代码。

 

END

posted on 2012-06-20 12:29  elycir  阅读(132)  评论(0)    收藏  举报