当前位置: 移动技术网 > IT编程>开发语言>.net > ASP.NET MVC Model验证(四)

ASP.NET MVC Model验证(四)

2019年01月06日  | 移动技术网IT编程  | 我要评论

重庆教育网,小学英语课程标准,莆田快乐农庄

前言

本篇主要讲解modelvalidatorprovider 和modelvalidator两种类型的自定义实现,前者是model验证提供程序,而modelvalidator类型则是model验证执行类型,在下面的示例中会使用model验证提供程序结合model验证执行类型来执行model验证,就是使用上个篇幅中所讲的实现个model绑定器继承自defaultmodelbinder类型,在自定义model绑定器中使用modelvalidator类型。

 

 

 

model验证

model验证简单运用示例

modelvalidator使用生成过程

自定义实现defaultmodelbinder进行验证

自定义modelvalidatorprovider 和modelvalidator 

validationattribute特性类使用

自定义validationattribute特性类的示例实现

 

 

自定义modelvalidatorprovider 和modelvalidator

modelvalidator

 

深呼吸一下,直接进入主题。

 

在我们定义自定义的modelvalidator类型之前,先看一下modelvalidator类型的定义,代码1-1.

 

代码1-1

 

复制代码

    public abstract class modelvalidator

    {

        protected modelvalidator(modelmetadata metadata, controllercontext controllercontext);

        protected internal controllercontext controllercontext { get; }

        public virtual bool isrequired { get; }

        //

        // 摘要:

        //     获取模型验证程序的元数据。

        //

        // 返回结果:

        //     模型验证程序的元数据。

        protected internal modelmetadata metadata { get; }

        public virtual ienumerable<modelclientvalidationrule> getclientvalidationrules();

        public static modelvalidator getmodelvalidator(modelmetadata metadata, controllercontext context);

        //

        // 摘要:

        //     在派生类中实现时验证对象。

        //

        // 参数:

        //   container:

        //     容器。

        //

        // 返回结果:

        //     验证结果的列表。

        public abstract ienumerable<modelvalidationresult> validate(object container);

    }

复制代码

代码1-1中,我们可以看到modelvalidator类型的构造是可以重写的,这样便于我们自定义一些所需的数据,不过下面的示例中并没有这么做,目的是在于简单的演示,然后我们再看一下metadata属性,这个属性非常重要了,它表示封装着所要进行验证的model或者是model属性的信息在此提醒大家关注一下,最后要看的就是validate()抽象方法了,我们自定义类型必须实现的这么一个方法,在它的返回类型中有个modelvalidationresult类型,我们就来看一下modelvalidationresult类型,代码1-2.

 

代码1-2

 

复制代码

    public class modelvalidationresult

    {

        public modelvalidationresult();

 

        // 摘要:

        //     获取或设置成员名。

        //

        // 返回结果:

        //     成员名。

        public string membername { get; set; }

        //

        // 摘要:

        //     获取或设置验证结果消息。

        //

        // 返回结果:

        //     验证结果消息。

        public string message { get; set; }

    }

复制代码

 

 

正如大家所看到的,代码1-2没啥好说的,看完本篇自然明白。

 

asp.net mvc model验证(三)和asp.net mvc model验证(一)中的示例想必有的朋友是看过了,没看过的朋友建议去快速的看一下篇幅一和篇幅三的示例部分(本篇示例的基础依赖上篇的基础部分,篇幅长度原因这里就不再次说明了),在这里我想说的是model验证也是分级别的,就是上篇中也有提到过的model级验证和model属性级验证,在下面的示例中,我把上篇篇幅中的验证过程拆成三个部分(可以写在一起,便于理解)。

 

我把第一个部分定义为model属性级验证,我们来看一下示例代码1-3。

 

代码1-3

 

复制代码

public class mycustommodelpropertyvalidator : modelvalidator

    {

        public mycustommodelpropertyvalidator(modelmetadata modelmetadata, controllercontext controllcontext)

            : base(modelmetadata, controllcontext)

        { }

 

        public override ienumerable<modelvalidationresult> validate(object container)

        {

            switch (metadata.propertyname)

            {

                case "id":

                    if (string.isnullorempty((string)container) || (string)container == "")

                    {

                        return new modelvalidationresult[]

                            { 

                               new modelvalidationresult()

                               {

                                   membername="id",

                                   message= "请输入id,id不能为空!"

                               }

                            };

                    }

                    break;

                case "userid":

                    if (string.isnullorempty((string)container) || (string)container == "")

                    {

                        return new modelvalidationresult[]

                            { 

                               new modelvalidationresult()

                               {

                                   membername="userid",

                                   message= "请输入用户账户,用户账户不能为空!"

                               }

                            };

                    }

                    break;

                case "password1":

                    if (string.isnullorempty((string)container) || (string)container == "")

                    {

                        controllercontext.controller.tempdata.add("password1", false);

                        return new modelvalidationresult[]

                            { 

                               new modelvalidationresult()

                               {

                                   membername="password1",

                                   message= "请输入登录密码,登录密码不能为空!"

                               }

                            };

                    }

                    break;

                case "password2":

                    if (string.isnullorempty((string)container) || (string)container == "")

                    {

                        controllercontext.controller.tempdata.add("password2", false);

                        return new modelvalidationresult[]

                            { 

                               new modelvalidationresult()

                               {

                                   membername="pssword2",

                                   message= "请再次输入密码,密码不能为空!"

                               }

                            };

                    }

                    break;

                case "name":

                    return enumerable.empty<modelvalidationresult>();

 

            }

            return enumerable.empty<modelvalidationresult>();

        }

    }

复制代码

 

 

首先我们在代码1-3中定义了个mycustommodelpropertyvalidator类型,并且定义了构造函数这点非常重要(看到model验证提供程序部分就明白了),在validate()方法中对一些属性进行了基本的的验证,并且依据方法所约束的返回类型去返回,对于代码的实现部分,看过上篇的朋友就知道了在默认的model绑定器执行model属性绑定的时候会进行model属性验证,会在遍历中循环的调用这个mycustommodelpropertyvalidator类型的验证方法,这里有不明白的朋友可以去看一下上篇。

 

我们再来看第二部分,第二部分的主要验证是验证两次输入的密码是否是相同的,来看示例代码1-4。

 

代码1-4

 

复制代码

public class mycustommodelpasswordvalidator : modelvalidator

    {

        public mycustommodelpasswordvalidator(modelmetadata modelmetadata, controllercontext controllercontext)

            : base(modelmetadata, controllercontext)

        { }

 

        public override ienumerable<modelvalidationresult> validate(object container)

        {

            models.registrationinformation reginfo = metadata.model as models.registrationinformation;

            if (reginfo != null)

            {

                if (!controllercontext.controller.tempdata.containskey("password1")

                    && !controllercontext.controller.tempdata.containskey("password2"))

                {

                    if (reginfo.password1 != reginfo.password2)

                    {

                        return new modelvalidationresult[]

                        {

                            new modelvalidationresult()

                            {

                                membername="password2",

                                message="请重新输入密码,与上次输入密码不同!"

                            }

                        };

                    }

                }

            }

            return enumerable.empty<modelvalidationresult>();

        }

    }

复制代码

 

 

在代码1-4中,有细心的朋友发现了跟代码1-3的实现方式有很大的区别,对的因为我把这个mycustommodelpasswordvalidator类型定义为model级验证了,mycustommodelpasswordvalidator类型所被调用的位置是在默认model绑定器对model属性验证完毕并且进行绑定了过后,再在默认model绑定器的onmodelupdated()方法中调用的,所以上述可以直接通过metadata的model属性直接获取model的值,由此来进行验证,而这句controllercontext.controller.tempdata.containskey("password1")代码的含义是判断在model的password1属性在属性级验证的时候是否通过了,因为每个model验证器之间无法传递消息,只有controllercontext是指向一个引用的,所有用它来做数据信息的承载。在代码1-3中已经定义了。(对于第二部分的理解不太明白的朋友可以结合上篇和本篇来看)

 

现在我们再看第三部分,意思和第二部分一样,示例代码1-5。

 

代码1-5

 

复制代码

public class mycustommodelnamevalidator : modelvalidator

    {

        public mycustommodelnamevalidator(modelmetadata modelmetadata, controllercontext controllerconttext)

            : base(modelmetadata, controllerconttext)

        { }

 

        public override ienumerable<modelvalidationresult> validate(object container)

        {

            models.registrationinformation reginfo = metadata.model as models.registrationinformation;

            if (reginfo != null)

            {

                if (string.compare(reginfo.name, "jinyuan", true) == 0)

                {

                    return new modelvalidationresult[] 

                    {

                        new modelvalidationresult()

                        {

                            membername="",

                            message="您输入的名称违法了,立即更改不然查水表"

                        }

                    };

                }

            }

            return enumerable.empty<modelvalidationresult>();

        }

    }

复制代码

 

 

代码1-5的功能就是在model级验证时对model的name属性进行验证。

 

 

 

modelvalidatorprovider

 

上个小节定义了三个部分,第一部分为model属性级验证,二三部分皆为model级验证,然而在默认的model绑定器(defaultmodelbinder类型)执行的时候,它才不管呢,它只负责从modelvalidatorproviders.providers中获取我们自定义的model验证器提供程序(modelvalidatorprovider类型实例),再由model验证器提供程序给它提供model验证器,这个时候就需要我们的自定义的model验证器提供程序具有判断我们自身是在哪里被调用的,并且返回对应的model验证器,来看示例代码1-6。

 

代码1-6

 

复制代码

namespace mapplication.modelvalidators

{

    public class mycustommodelvalidatorprovider:modelvalidatorprovider

    {

        public override ienumerable<modelvalidator> getvalidators(modelmetadata metadata, controllercontext context)

        {

            if (metadata.containertype == typeof(models.registrationinformation))

            {

                return new modelvalidator[]

                {

                    new mycustommodelpropertyvalidator(metadata,context)

                };

            }

            else if (metadata.modeltype == typeof(models.registrationinformation))

            {

                return new modelvalidator[] 

                {

                    new mycustommodelpasswordvalidator(metadata,context),

                    new mycustommodelnamevalidator(metadata,context)

                };

            }

            return enumerable.empty<modelvalidator>();

        }

    }

}

复制代码

 

 

在代码1-6中,我们定义了个自定义的model验证器提供程序mycustommodelvalidatorprovider类型,在mycustommodelvalidatorprovider类型中是根据getvalidators()方法的参数metadata所包含的信息来判断自己被默认的model绑定器(defaultmodelbinder类型)调用的位置。(对于model元数据部分大家可查看我前面跟大家分享的model元数据系列)

 

到了这里几乎就已经全部完成了,现在注册到中是不能使用的,有的朋友会骂了,不能用瞎扯蛋扯半天,大家莫急,听我解释,是因为我们自定义的model验证器和model验证器提供程序都要受到mvc框架的默认的model绑定器(defaultmodelbinder类型)调用的约束,是必须按照它方法内部定义的来往下写,在这里我们不图省事,再定义一个自定义实现defaultmodelbinder类型的model绑定器,来看示例代码1-7。

 

代码1-7

 

复制代码

    public class mycustommodelvalidatordefaultmodelbinder : defaultmodelbinder

    {

        protected override void setproperty(controllercontext controllercontext, modelbindingcontext bindingcontext, propertydescriptor propertydescriptor, object value)

        {

            base.setproperty(controllercontext, bindingcontext, propertydescriptor, value);

            foreach (modelvalidator modelvalidator in modelvalidatorproviders.providers.getvalidators(bindingcontext.propertymetadata[propertydescriptor.name], controllercontext))

            {

                ienumerable<modelvalidationresult> modelvalidationresults = modelvalidator.validate(value);

                foreach (modelvalidationresult modelvalidationresult in modelvalidationresults)

                {

                    bindingcontext.modelstate.addmodelerror(modelvalidationresult.membername, modelvalidationresult.message);

                }

            }

 

        }

        protected override void onmodelupdated(controllercontext controllercontext, modelbindingcontext bindingcontext)

        {

            //base.onmodelupdated(controllercontext, bindingcontext);

            foreach (modelvalidator modelvalidator in modelvalidatorproviders.providers.getvalidators(bindingcontext.modelmetadata, controllercontext))

            {

                ienumerable<modelvalidationresult> modelvalidationresults = modelvalidator.validate(null);

                foreach (modelvalidationresult modelvalidationresult in modelvalidationresults)

                {

                    bindingcontext.modelstate.addmodelerror(modelvalidationresult.membername, modelvalidationresult.message);

                }

            }

        }

    }

复制代码

 

 

有了代码1-7中的model绑定器就可以吻合我们前面所定义的model验证器以及提供程序了。

 

我要把mycustommodelvalidatorprovider类型和mycustommodelvalidatordefaultmodelbinder类型注册到系统中,将示例代码1-8部分添加至global.asax文件的application_start()方法中。

 

代码1-8

 

modelbinders.binders.add(typeof(models.registrationinformation), new binders.mycustommodelvalidatordefaultmodelbinder());

modelvalidatorproviders.providers.insert(0, new modelvalidators.mycustommodelvalidatorprovider());

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网