• 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", "名字不能为空!");

    //} 

    这些部分就可以不要了。

     

  • 相关阅读:
    【codeforces 755A】PolandBall and Hypothesis
    【codeforces 755B】PolandBall and Game
    【codeforces 755C】PolandBall and Forest
    Enhancing network controls in mandatory access control computing environments
    NPM 使用介绍
    【oracle】首次启动SQL Developer配置java.exe出错(Could not find jvm.cfg! )
    day70-oracle PLSQL_02光标
    day69-oracle 22-DBCA
    day70-oracle 12-Java调用存储过程和存储函数
    day17 16.关于sql注入与PreparedStatement介绍
  • 原文地址:https://www.cnblogs.com/jams742003/p/1666345.html
Copyright © 2020-2023  润新知