MVC 模仿MVC源生校验,生成Easyui校验规则

MVC的自带的model校验觉得很不错,可惜只能使用jquery源生的校验,如果我们希望系统生成Easyui的校验规则该如何做呢?

1,MVC自带校验

 先简单说下 MVC是如何根据ValidationAttribute生成前台校验的.

   <div class="editor-field">
                @Html.PasswordFor(m => m.Password)
                @Html.ValidationMessageFor(m => m.Password)
            </div>
            <div class="editor-field">
                <input data-val="true" data-val-length="密码 必须至少包含 6 个字符。" data-val-length-max="100" data-val-length-min="6" data-val-required="密码 字段是必需的。" id="Password" name="Password" type="password" />
                                <span class="field-validation-valid" data-valmsg-for="Password" data-valmsg-replace="true"></span>
            </div>

通过对比以上代码可以看到编译器通过 htmlhelper类中的@html.PasswordFor方法生成了<input>标签,看到为了自身校验的添加众多的Attribute如<data-val>等。

真正校验代码还是前台的做的,通过我们引用的validate.js和jquery.validate.unobtrusive.js进行的。

<script src="@Url.Content("~/Scripts/jquery.validate.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")" type="text/javascript"></script>

2,自定义htmlhelper

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Linq.Expressions;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Reflection;
using System.Web.Routing;

namespace EasyUIValidationByMvc3.Helper
{
    public static class MyHtmlHelper
    {
        /// <summary>
        /// 自定义一个@html.validatebox()
        /// </summary>
        /// <param name="helper"></param>
        /// <returns></returns>
        public static MvcHtmlString Validatebox<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes)
        {
            MemberInfo Member = ((MemberExpression)expression.Body).Member;

            var builder = new TagBuilder("input");

            builder.AddCssClass("easyui-validatebox");
            builder.MergeAttribute("Name", Member.Name);
            builder.MergeAttribute("id", Member.Name);
            builder.MergeAttributes(new RouteValueDictionary(htmlAttributes));
            //if (htmlAttributes != null)
            //{
            //    foreach (var item in htmlAttributes.GetType().GetProperties())
            //    {
            //        builder.MergeAttribute(item.Name, item.GetValue(htmlAttributes, null).ToString());
            //    }
            //}
            GetValidationAttribute(builder, Member);

            builder.ToString(TagRenderMode.SelfClosing);
            return MvcHtmlString.Create(builder.MyToString());
        }

        private static ICustomTypeDescriptor GetTypeDescriptor(Type type)
        {
            return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
        }

        private static void GetValidationAttribute(TagBuilder builder,MemberInfo Member)
        {
            var descriptor = GetTypeDescriptor(Member.ReflectedType);

            foreach (PropertyDescriptor propertyDescriptor in descriptor.GetProperties())
            {
                foreach (var validationAttribute in propertyDescriptor.Attributes.OfType<ValidationAttribute>())
                {
                    if (Member.Name == propertyDescriptor.Name)
                    {
                        if (validationAttribute is IValidation)
                        {
                            ((IValidation)validationAttribute).SetHtmlAttribute(builder);
                        }
                    }
                }
            }
        }
        //多重校验还是有问题,前台的东西没有详细调
        public static void MyMergeAttribute(this TagBuilder builder, string key, string value, bool replaceExisting)
        {
            if (builder.Attributes.ContainsKey(key))
            {
                value = @"[‘" + builder.Attributes[key].ToString() + "‘,‘" + value + "‘]";
            }

            builder.MergeAttribute(key, value, true);
        }

        public static string MyToString(this TagBuilder builder)
        {
            return builder.ToString().Replace("&#39;", "‘").Replace("amp;", "");
 
        }
    }
}

可以看到我自定义了一个htmlhelper的扩展方法Validatebox,通过这个扩展方法我们可以通过获取model中的属性attribute调用属性中的IValidation接口方法进行TagBuilder的htmlattribute扩展。

            <div class="editor-field">
                @Html.Validatebox(m => m.UserName, null)
                @Html.ValidationMessageFor(m => m.UserName)
            </div>
            <div class="editor-field">
                <input Name="UserName" class="easyui-validatebox" data-options="required:true" id="UserName" missingMessage="请输入用户名!"></input>
                <span class="field-validation-valid" data-valmsg-for="UserName" data-valmsg-replace="true"></span>
            </div>

这是我调用了自己扩展方法生成的html页面代码。

3,自定义ValidationAttribute

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel.DataAnnotations;

namespace EasyUIValidationByMvc3.Helper
{
    public class MyRequiredAttribute : RequiredAttribute, IValidation
    {
        public MyRequiredAttribute()
            : base()
        { }

        #region IValidation 成员

        public void SetHtmlAttribute(System.Web.Mvc.TagBuilder builder)
        {
            builder.MergeAttribute("data-options", "required:true");
            
            if (this.ErrorMessage != null && this.ErrorMessage.Length > 0)
            {
                builder.MergeAttribute("missingMessage", this.ErrorMessage);
            }
        }

        #endregion
    }
}

建议采用自定义的 ValidationAttribute,当然自带的也可以,需要对type的名字进行比对,然后进行htmlattribute进行添加就可以了!

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。