mvc基础系列说谈(6)——数据验证(上)

(一)基本验证

通过htmlhelper来验证。

Customer为例:

在创建(Create)视图中,如果应用了验证:

<%= Html.ValidationSummary("Create was unsuccessful. 
Please correct the errors and try again.") %>
    <% using (Html.BeginForm("Create""Customer"
       FormMethod.Post, 
new {enctype = "application/x-www-form-urlencoded" }))
   {
%>
    
<fieldset>
    
<legend>Fields</legend>
    
<p>
      
<label for="FirstName">FirstName:</label>
      
<%= Html.TextBox("FirstName"%>
      
<%= Html.ValidationMessage("FirstName""*"%>
    
</p>
    
<p>
      
<label for="LastName">LastName:</label>
      
<%= Html.TextBox("LastName"%>
      
<%= Html.ValidationMessage("LastName""*"%>
    
</p>
    
<p>
      
<input type="submit" value="Create" />
    
</p>
    
</fieldset>
<% } %>

以名字(FirstName)与姓氏(LastName)来说,

<%= Html.TextBox("FirstName"%>
<%= Html.ValidationMessage("FirstName""*"%>

通过helperValidationMessage来验证FirstName文本框,然后如果验证不通过,则文本框后加显示*符号(就像平常注册的一样,必填项有些类似,当然做为字符串,可以改的)

然后在控制器的动作中,通过ModelState来验证:

if (customer.FirstName == string.Empty)
{
    ModelState.AddModelError(
"FirstName""名字不能为空!");
}

if (customer.LastName == string.Empty)
{
    ModelState.AddModelError(
"LastName""姓氏不能为空!");


if (Convert.ToInt32(customer.FirstName) > 10)
{
    ModelState.AddModelError(
"FirstName""名字不能大于!");


if (!ModelState.IsValid)
{
    
return View();
}

这个ModelStateController的一个属性:

public ModelStateDictionary ModelState
{
    
get
    {
        
return base.ViewData.ModelState;
    }
}

从这里可以看出:控制器的ModelState属性其实是ViewData的一个属性。看来ViewData用处真大(Model部分其实也是放到了这个属性中)。而ViewData是一个ViewDataDictionary 类型的。然后,这个类型的一个属性:就是ModelState,这个属性就是一个ModelStateDictionary 类型。它的方法很多,其中之一就是:

public void AddModelError(string key, string errorMessage)
{
    
this.GetModelStateForKey(key).Errors.Add(errorMessage);
}

就是程序中用到的。其中GetModelStateForKey方法是得到一个ModelState类实例,ModelState类定义为:

public class ModelState
{
    
// Fields
    private ModelErrorCollection _errors;

    [CompilerGenerated]
    
private ValueProviderResult <Value>k__BackingField; 

    
// Methods
    public ModelState(); 

    
// Properties
    public ModelErrorCollection Errors { get; }
    
public ValueProviderResult Value { [CompilerGenerated] get; [CompilerGenerated] set; }
}

当调用ModelState.AddModelError方法时:

·调用ControllerModelState属性

·调用ControllerModelState属性就是调用ControllerViewData属性的ModelState

·其实调用的就是ViewDataDictionary类的ModelState属性

·当添加错误信息时,就是调用ModelState属性的AddModelError方法,

其中ModelState属性是ModelStateDictionary类型

·当添加错误信息时,就是向ModelState类实例中Errors属性中添加kv对,也就是对ModelErrorCollection

添加错误信息

 

然后再提一下IsValid属性:

public bool IsValid
{
    
get
    {
        
return this.Values.All<ModelState>(delegate (ModelState modelState) 
        {
            
return (modelState.Errors.Count == 0);
        });
    }
}

这下就一目了然了:验证数据后,会在ModelState

 

Post提交过来的数据被验证时,当有错误信息时,被添加到ModelState类实例的ModelErrorCollection集合属性中,然后控制器的ModelState属性的Values属性(ModelState类型),如果这个ModelState中的错误的信息的数目为0时,则验证通过,否则验证不通过。

 

当验证不通过时,不会执行创建动作中的IsValid之后的逻辑,而直接返回视图。这时,错误信息已经添加到了控制器的ViewData中。然后,在视图中显示。

(二)通过实现IDataErrorInfo接口

IDataErrorInfo 接口定义:

public interface IDataErrorInfo
{
    
// Properties
    string Error { get; }
    
string this[string columnName] { get; }
}

如果要实现这个接口:

·partial类型的类实体中继承这个接口

·实现这个接口

·对数据进行验证时,只要实现[On属性Changing]即可

例如:我是直接在LinqToSql文件的Customer类中添加的接口(因为做了一个partial类,在别的地方写也是可以的,它表示可分写。)

public partial class Customer : INotifyPropertyChanging, 
                                INotifyPropertyChanged, IDataErrorInfo

实现部分为:

#region IDataErrorInfo 成员

private Dictionary<stringstring> _errors = new Dictionary<stringstring>(); 

partial void OnFirstNameChanging(string value)
{
    
if (value.Trim().Length == 0)
        _errors.Add(
"FirstName""名字不能为空.");
    
else
    {
        
if (Convert.ToInt32(value.Trim()) > 10)
           _errors.Add(
"FirstName""不能大于10");
    }
}

partial void OnLastNameChanging(string value)
{
    
if (value.Trim().Length == 0)
        _errors.Add(
"LastName""姓氏不能为空.");   
}

public string Error
{
    
get
    {
        
return string.Empty;
    }
}

public string this[string columnName]
{
    
get
    {
       
if (_errors.ContainsKey(columnName))
            
return _errors[columnName];
       
return string.Empty;
    }
}

#endregion

这部分相当容易实现,一个Error属性,一个实现索引,添加对验证字段(文本框)的方法。即可,然后在控制器中:

//if (customer.FirstName == string.Empty)

//{

//    ModelState.AddModelError("FirstName", "名字不能为空!");

//} 

这些部分就可以不要了。

 

原文地址:https://www.cnblogs.com/jams742003/p/1666345.html