Asp.net Mvc自定义客户端验证(CheckBox列表的验证)

最近在使用MVC进行开发时,使用进行客户端的输入验证,加上使用MVC3的新视图引擎感觉还是挺方便的,不用自己去写很多js了,并且效果也能让人接受

可是遇上要向外输出比如一个CheckBox列表时就纠结了,验证代码还得自己去写,这样就造成了客户端采用了两套验证,感觉不统一也不优雅,于是就琢磨了一下,便有了如下实现方式。

HtmlHelper的扩展类主要包括CheckBoxList,CheckBoxListFor等方法,有了这些方法,你可以这样生成checkBox 列表

@Html.CheckBoxListFor(m=>m.RoleList,"li")

 下来就是扩展的全部代码 

HtmlHelperExtention.cs
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Web.Mvc;

namespace Newborn.BSCommon
{
    
/// <summary>
    
/// HtmlHelper扩展
    
/// </summary>
    public static class HtmlHelperExtention
    {
        
public static MvcHtmlString InputList(this HtmlHelper helper, IEnumerable<SelectListItem> selectList, string checkBoxName, string splitTagName, InputType inputType)
        {
            
return InputList(helper, null, selectList, checkBoxName,splitTagName, inputType);
        }

        
/// <summary>
        
/// 生成CheckBox列表
        
/// </summary>
        
/// <param name="helper">HtmlHelper</param>
        
/// <param name="checkBoxName">name属性</param>
        
/// <param name="splitTagName">每个SelectList外层</param>
        
/// <param name="inputType">inputType</param>
        
/// <param name="selectList">selectList</param>
        
/// <param name="metadata">metadata</param>
        
/// <returns>MvcHtmlString</returns>
        public static MvcHtmlString InputList(this HtmlHelper helper,ModelMetadata metadata, IEnumerable<SelectListItem> selectList, string checkBoxName, string splitTagName, InputType inputType)
        {
            
if (helper == nullthrow new ArgumentNullException("helper");
            
if (selectList == nullthrow new ArgumentNullException("selectList");
            
if (string.IsNullOrEmpty(checkBoxName)) throw new ArgumentNullException("checkBoxName");
            
            StringBuilder sb 
= new StringBuilder();
            
int idIndex = 0;
            TagBuilder tagBuilder 
= new TagBuilder("span");
            
foreach (SelectListItem item in selectList)
            {
                TagBuilder splitTagBuilder 
= null;
                
if (!string.IsNullOrEmpty(splitTagName))
                    splitTagBuilder 
= new TagBuilder(splitTagName);
                TagBuilder checkTagBuilder 
= new TagBuilder("input");
                checkTagBuilder.Attributes[
"type"= inputType.ToString();
                checkTagBuilder.Attributes[
"name"= checkBoxName;
                checkTagBuilder.Attributes[
"value"= item.Value;

                
string checkBoxId = checkBoxName + "_id_" + idIndex;
                checkTagBuilder.Attributes[
"id"= checkBoxId;
                
if (item.Selected)
                    checkTagBuilder.Attributes[
"checked"= "checked";
                TagBuilder labelTagBuilder 
= new TagBuilder("label") { InnerHtml = helper.Encode(item.Text) };

                labelTagBuilder.Attributes[
"for"= checkBoxId;
                
string checkHtml = checkTagBuilder.ToString() + labelTagBuilder.ToString();
                
if (splitTagBuilder != null)
                {
                    splitTagBuilder.InnerHtml 
+= checkHtml;
                    sb.AppendLine(splitTagBuilder.ToString());
                }
                
else
                    sb.AppendLine(checkHtml);

                idIndex
++;
            }
            
            TagBuilder hiddenTagBuilder 
= new TagBuilder("input");
            hiddenTagBuilder.Attributes[
"type"= "hidden";
            hiddenTagBuilder.MergeAttribute(
"name", checkBoxName);
            hiddenTagBuilder.MergeAttribute(
"id""hidden"+ checkBoxName);
            hiddenTagBuilder.MergeAttributes
<stringobject>(helper.GetUnobtrusiveValidationAttributes(checkBoxName, metadata));
            tagBuilder.InnerHtml 
= hiddenTagBuilder + sb.ToString();
            
return MvcHtmlString.Create(tagBuilder.ToString());
        }
        
/// <summary>
        
/// 生成CheckBox列表
        
/// </summary>
        
/// <param name="helper">HtmlHelper</param>
        
/// <param name="selectList"></param>
        
/// <param name="checkBoxName">name属性</param>
        
/// <returns>MvcHtmlString</returns>
        public static MvcHtmlString CheckBoxList(this HtmlHelper helper, IEnumerable<SelectListItem> selectList, string checkBoxName)
        {
            
return helper.InputList(selectList, checkBoxName, null, InputType.CheckBox);
        }

        
public static MvcHtmlString InputListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression,string splitTag,InputType inputType)
        {
            ModelMetadata modelMetadata 
= ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            List
<SelectListItem> list = ((List<SelectListItem>)modelMetadata.Model);
            
return htmlHelper.InputList(modelMetadata, list, modelMetadata.PropertyName, splitTag, inputType);
        }
        
public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            
return htmlHelper.InputListFor(expression, "span",InputType.CheckBox);
        }
        
public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression,string splitTag)
        {
            
return htmlHelper.InputListFor(expression, splitTag, InputType.CheckBox);
        }

        
/// <summary>
        
///  生成CheckBox列表
        
/// </summary>
        
/// <param name="helper"></param>
        
/// <param name="selectList"></param>
        
/// <param name="checkBoxName"></param>
        
/// <param name="splitTagName">每项分隔符的Tag名称</param>
        
/// <returns></returns>
        public static MvcHtmlString CheckBoxList(this HtmlHelper helper, IEnumerable<SelectListItem> selectList, string checkBoxName, string splitTagName)
        {
            
return InputList(helper, selectList, checkBoxName, splitTagName, InputType.CheckBox);
        }



        
public static MvcHtmlString RadioBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            
return htmlHelper.InputListFor(expression, "span", InputType.Radio);
        }

        

        
/// <summary>
        
/// 生成RadioButton列表
        
/// </summary>
        
/// <param name="helper"></param>
        
/// <param name="selectList"></param>
        
/// <param name="checkBoxName"></param>
        
/// <param name="splitTag"></param>
        
/// <returns></returns>
        public static MvcHtmlString RadioButtonList(this HtmlHelper helper, IEnumerable<SelectListItem> selectList, string checkBoxName, string splitTag)
        {
            
return InputList(helper, selectList, checkBoxName, splitTag, InputType.Radio);
        }

        
/// <summary>
        
/// 生成RadioButton列表
        
/// </summary>
        
/// <param name="helper"></param>
        
/// <param name="selectList"></param>
        
/// <param name="checkBoxName"></param>
        
/// <returns></returns>
        public static MvcHtmlString RadioButtonList(this HtmlHelper helper, IEnumerable<SelectListItem> selectList, string checkBoxName)
        {
            
return InputList(helper, selectList, checkBoxName, null, InputType.Radio);
        }
    }
}

 由于使用到客户端验证所以要引用如下的js文件。

脚本部分

<script src="@Url.Content("~/Scripts/jquery-1.4.4.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/Custom/jquery.validate.unobtrusive.extension.js")" type="text/javascript"></script>
<script type="text/javascript">
      $(
function () {
           
new checkBoxList("RoleList""hiddenRoleList");//初始验证
      });
</script>

页面上还要写这个一句

 $(function () {
           
new checkBoxList("RoleList""hiddenRoleList");//初始验证

      }); 

 是为了让脚本去绑定事件,可能还会有更好的方式,这里有待研究。

页面上代码如下: 

HTML部分
<div class="select">    
    @Html.CheckBoxListFor(m=>m.RoleList,"li")
   
@Html.ValidationMessageFor(m => m.RoleList)
</div>

ListSlectRangeAttribute.cs 文件

View Code
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;

namespace Newborn.BSCommon
{
    [AttributeUsage(AttributeTargets.Property 
| AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)]
    
public class ListSlectRangeAttribute : ValidationAttribute, IClientValidatable
    {
        
private const string errFormat = "该项最少选择项为{0}最多选择项为{1}";

        
public ListSlectRangeAttribute()
        {
            MinSelected 
= 0;
            MaxSelected 
= -1;
        }

        
public int MinSelected { getset; }

        
public int MaxSelected { getset; }

        
public override bool IsValid(object value)
        {
            
return true;
        }


        
public override string FormatErrorMessage(string name)
        {
            
return string.Format(errFormat, MinSelected > 0 ? MinSelected.ToString() : "不限", MaxSelected > 0 ? MaxSelected.ToString() : "不限");
        }


        
public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            ModelClientValidationRule rule 
= new ModelClientValidationRule
            {
                ValidationType 
= "list",
                ErrorMessage 
= FormatErrorMessage(metadata.GetDisplayName())
            };
            rule.ValidationParameters[
"min"= MinSelected;
            rule.ValidationParameters[
"max"= MaxSelected;

            
yield return rule;
        }
    }
}
jquery.validate.unobtrusive.extension.js文件主要完成客户端如checkbox列表的验证,细心的朋友会发现因为checkbox列表是多个input所以我没有基于它来做,而是采用一个隐藏域还记录现在选择的项数目(目前只记录选择了多少项,没记录选择的项值之类的,不过目前暂无此类需求,如果有扩展起来也行方便)。
//by xianhong
//
添加验证如验证框必须选择一定数量的验证
$.validator.addMethod("maxminselected"function (value, element, param) {
    
var min = param[0];
    
var max = param[1];
    
if (value >= min && (max <= 0 || value <= max))
        
return true;
    
return false;
});
$.validator.unobtrusive.adapters.addMinMax(
"list""min""max""maxminselected");


var checkBoxList = function (name/*input name属性*/, hiddenId/*记录选择的隐藏域*/) {
    
this.checkedCount = function () {
        
var selected = $("input[name='" + name + "']:checked");
        
return selected.length;
    };
    
this.All = function () {
        
return $("input[name='" + name + "']");
    };
    
this.BindClick = function () {
        
var thisobj = this;
        
this.All().click(function () {
            $(
"#" + hiddenId).val(thisobj.checkedCount());
        });
    };
    
this.BindClick();
};
原文地址:https://www.cnblogs.com/xianhong/p/2023831.html