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 == null) throw new ArgumentNullException("helper");
            if (selectList == null) throw 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<string, object>(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 { get; set; }

        public int MaxSelected { get; set; }

        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();
};

posted @ 2011-06-08 10:01  ido  阅读(2464)  评论(1编辑  收藏  举报