ASP.NETMVCModel驗(yàn)證(四)-創(chuàng)新互聯(lián)

ASP.NETMVC Model驗(yàn)證(四)

專注于為中小企業(yè)提供網(wǎng)站設(shè)計(jì)、成都網(wǎng)站設(shè)計(jì)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)延壽免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了千余家企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過(guò)網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

前言

本篇主要講解ModelValidatorProvider和ModelValidator兩種類型的自定義實(shí)現(xiàn),前者是Model驗(yàn)證提供程序,而ModelValidator類型則是Model驗(yàn)證執(zhí)行類型,在下面的示例中會(huì)使用Model驗(yàn)證提供程序結(jié)合Model驗(yàn)證執(zhí)行類型來(lái)執(zhí)行Model驗(yàn)證,就是使用上個(gè)篇幅中所講的實(shí)現(xiàn)個(gè)Model綁定器繼承自DefaultModelBinder類型,在自定義Model綁定器中使用ModelValidator類型。

Model驗(yàn)證

  • Model驗(yàn)證簡(jiǎn)單運(yùn)用示例

  • ModelValidator使用生成過(guò)程

  • 自定義實(shí)現(xiàn)DefaultModelBinder進(jìn)行驗(yàn)證

  • 自定義ModelValidatorProvider和ModelValidator

  • ValidationAttribute特性類使用

  • 自定義ValidationAttribute特性類的示例實(shí)現(xiàn)

自定義ModelValidatorProvider和ModelValidator

ModelValidator

深呼吸一下,直接進(jìn)入主題。

在我們定義自定義的ModelValidator類型之前,先看一下ModelValidator類型的定義,代碼1-1.

代碼1-1

    public abstract class ModelValidator
    {
        protectedModelValidator(ModelMetadata metadata, ControllerContext controllerContext);
        protectedinternal ControllerContextControllerContext { get; }
        public virtual boolIsRequired { get; }
        //
        // 摘要:
        //     獲取模型驗(yàn)證程序的元數(shù)據(jù)。
        //
        // 返回結(jié)果:
        //     模型驗(yàn)證程序的元數(shù)據(jù)。
        protected internal ModelMetadata Metadata { get;}
        public virtual IEnumerable<ModelClientValidationRule>GetClientValidationRules();
        public static ModelValidatorGetModelValidator(ModelMetadata metadata, ControllerContext context);
        //
        // 摘要:
        //     在派生類中實(shí)現(xiàn)時(shí)驗(yàn)證對(duì)象。
        //
        // 參數(shù):
        //   container:
        //     容器。
        //
        // 返回結(jié)果:
        //     驗(yàn)證結(jié)果的列表。
        public abstract IEnumerable<ModelValidationResult> Validate(object container);
    }

代碼1-1中,我們可以看到ModelValidator類型的構(gòu)造是可以重寫(xiě)的,這樣便于我們自定義一些所需的數(shù)據(jù),不過(guò)下面的示例中并沒(méi)有這么做,目的是在于簡(jiǎn)單的演示,然后我們?cè)倏匆幌翸etadata屬性,這個(gè)屬性非常重要了,它表示封裝著所要進(jìn)行驗(yàn)證的Model或者是Model屬性的信息在此提醒大家關(guān)注一下,最后要看的就是Validate()抽象方法了,我們自定義類型必須實(shí)現(xiàn)的這么一個(gè)方法,在它的返回類型中有個(gè)ModelValidationResult類型,我們就來(lái)看一下ModelValidationResult類型,代碼1-2.

代碼1-2

    public class ModelValidationResult
    {
        publicModelValidationResult();
 
        // 摘要:
        //     獲取或設(shè)置成員名。
        //
        // 返回結(jié)果:
        //     成員名。
        public string MemberName { get;set; }
        //
        // 摘要:
        //     獲取或設(shè)置驗(yàn)證結(jié)果消息。
        //
        // 返回結(jié)果:
        //     驗(yàn)證結(jié)果消息。
        public string Message { get;set; }
    }

正如大家所看到的,代碼1-2沒(méi)啥好說(shuō)的,看完本篇自然明白。

ASP.NET MVC Model驗(yàn)證(三)和ASP.NET MVCModel驗(yàn)證(一)中的示例想必有的朋友是看過(guò)了,沒(méi)看過(guò)的朋友建議去快速的看一下篇幅一和篇幅三的示例部分(本篇示例的基礎(chǔ)依賴上篇的基礎(chǔ)部分,篇幅長(zhǎng)度原因這里就不再次說(shuō)明了),在這里我想說(shuō)的是Model驗(yàn)證也是分級(jí)別的,就是上篇中也有提到過(guò)的Model級(jí)驗(yàn)證和Model屬性級(jí)驗(yàn)證,在下面的示例中,我把上篇篇幅中的驗(yàn)證過(guò)程拆成三個(gè)部分(可以寫(xiě)在一起,便于理解)。

我把第一個(gè)部分定義為Model屬性級(jí)驗(yàn)證,我們來(lái)看一下示例代碼1-3。

代碼1-3

    public class MyCustomModelPropertyValidator : ModelValidator
    {
        publicMyCustomModelPropertyValidator(ModelMetadatamodelMetadata, ControllerContextcontrollContext)
            : 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= "請(qǐng)輸入ID,ID不能為空!"
                               }
                            };
                    }
                    break;
                case"UserID":
                    if(string.IsNullOrEmpty((string)container)|| (string)container == "")
                    {
                        return new ModelValidationResult[]
                            { 
                               new ModelValidationResult()
                               {
                                   MemberName="UserID",
                                   Message= "請(qǐng)輸入用戶賬戶,用戶賬戶不能為空!"
                               }
                            };
                    }
                    break;
                case"Password1":
                    if(string.IsNullOrEmpty((string)container)|| (string)container == "")
                    {
                       ControllerContext.Controller.TempData.Add("Password1",false);
                        return new ModelValidationResult[]
                            { 
                               new ModelValidationResult()
                               {
                                   MemberName="Password1",
                                   Message= "請(qǐng)輸入登錄密碼,登錄密碼不能為空!"
                               }
                            };
                    }
                    break;
                case"Password2":
                    if(string.IsNullOrEmpty((string)container)|| (string)container == "")
                    {
                       ControllerContext.Controller.TempData.Add("Password2",false);
                        return new ModelValidationResult[]
                            { 
                               new ModelValidationResult()
                               {
                                   MemberName="Pssword2",
                                   Message= "請(qǐng)?jiān)俅屋斎朊艽a,密碼不能為空!"
                               }
                            };
                    }
                    break;
                case"Name":
                    returnEnumerable.Empty<ModelValidationResult>();
 
            }
            returnEnumerable.Empty<ModelValidationResult>();
        }
    }

首先我們?cè)诖a1-3中定義了個(gè)MyCustomModelPropertyValidator類型,并且定義了構(gòu)造函數(shù)這點(diǎn)非常重要(看到Model驗(yàn)證提供程序部分就明白了),在Validate()方法中對(duì)一些屬性進(jìn)行了基本的的驗(yàn)證,并且依據(jù)方法所約束的返回類型去返回,對(duì)于代碼的實(shí)現(xiàn)部分,看過(guò)上篇的朋友就知道了在默認(rèn)的Model綁定器執(zhí)行Model屬性綁定的時(shí)候會(huì)進(jìn)行Model屬性驗(yàn)證,會(huì)在遍歷中循環(huán)的調(diào)用這個(gè)MyCustomModelPropertyValidator類型的驗(yàn)證方法,這里有不明白的朋友可以去看一下上篇。

我們?cè)賮?lái)看第二部分,第二部分的主要驗(yàn)證是驗(yàn)證兩次輸入的密碼是否是相同的,來(lái)看示例代碼1-4。

代碼1-4

    public class MyCustomModelPassWordValidator : ModelValidator
    {
        publicMyCustomModelPassWordValidator(ModelMetadatamodelMetadata, ControllerContextcontrollerContext)
            : base(modelMetadata,controllerContext)
        { }
 
        public override IEnumerable<ModelValidationResult> Validate(object container)
        {
            Models.RegistrationInformationregInfo = 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="請(qǐng)重新輸入密碼,與上次輸入密碼不同!"
                            }
                        };
                    }
                }
            }
            returnEnumerable.Empty<ModelValidationResult>();
        }
    }

在代碼1-4中,有細(xì)心的朋友發(fā)現(xiàn)了跟代碼1-3的實(shí)現(xiàn)方式有很大的區(qū)別,對(duì)的因?yàn)槲野堰@個(gè)MyCustomModelPassWordValidator類型定義為Model級(jí)驗(yàn)證了,MyCustomModelPassWordValidator類型所被調(diào)用的位置是在默認(rèn)Model綁定器對(duì)Model屬性驗(yàn)證完畢并且進(jìn)行綁定了過(guò)后,再在默認(rèn)Model綁定器的OnModelUpdated()方法中調(diào)用的,所以上述可以直接通過(guò)Metadata的Model屬性直接獲取Model的值,由此來(lái)進(jìn)行驗(yàn)證,而這句ControllerContext.Controller.TempData.ContainsKey("Password1")代碼的含義是判斷在Model的Password1屬性在屬性級(jí)驗(yàn)證的時(shí)候是否通過(guò)了,因?yàn)槊總€(gè)Model驗(yàn)證器之間無(wú)法傳遞消息,只有ControllerContext是指向一個(gè)引用的,所有用它來(lái)做數(shù)據(jù)信息的承載。在代碼1-3中已經(jīng)定義了。(對(duì)于第二部分的理解不太明白的朋友可以結(jié)合上篇和本篇來(lái)看)

現(xiàn)在我們?cè)倏吹谌糠?,意思和第二部分一樣,示例代碼1-5。

代碼1-5

    public class MyCustomModelNameValidator : ModelValidator
    {
        publicMyCustomModelNameValidator(ModelMetadatamodelMetadata, ControllerContextcontrollerConttext)
            : base(modelMetadata,controllerConttext)
        { }
 
        public override IEnumerable<ModelValidationResult> Validate(object container)
        {
            Models.RegistrationInformationregInfo = Metadata.Model as Models.RegistrationInformation;
            if(regInfo != null)
            {
                if(string.Compare(regInfo.Name, "jinyuan", true)== 0)
                {
                    returnnew ModelValidationResult[]
                    {
                        new ModelValidationResult()
                        {
                            MemberName="",
                            Message="您輸入的名稱違法了,立即更改不然查水表"
                        }
                    };
                }
            }
            returnEnumerable.Empty<ModelValidationResult>();
        }
    }

代碼1-5的功能就是在Model級(jí)驗(yàn)證時(shí)對(duì)Model的Name屬性進(jìn)行驗(yàn)證。

ModelValidatorProvider

上個(gè)小節(jié)定義了三個(gè)部分,第一部分為Model屬性級(jí)驗(yàn)證,二三部分皆為Model級(jí)驗(yàn)證,然而在默認(rèn)的Model綁定器(DefaultModelBinder類型)執(zhí)行的時(shí)候,它才不管呢,它只負(fù)責(zé)從ModelValidatorProviders.Providers中獲取我們自定義的Model驗(yàn)證器提供程序(ModelValidatorProvider類型實(shí)例),再由Model驗(yàn)證器提供程序給它提供Model驗(yàn)證器,這個(gè)時(shí)候就需要我們的自定義的Model驗(yàn)證器提供程序具有判斷我們自身是在哪里被調(diào)用的,并且返回對(duì)應(yīng)的Model驗(yàn)證器,來(lái)看示例代碼1-6。

代碼1-6

namespace MvcApplication.ModelValidators
{
    public class MyCustomModelValidatorProvider:ModelValidatorProvider
    {
        public override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContextcontext)
        {
            if(metadata.ContainerType == typeof(Models.RegistrationInformation))
            {
                returnnew ModelValidator[]
                {
                    newMyCustomModelPropertyValidator(metadata,context)
                };
            }
            elseif (metadata.ModelType == typeof(Models.RegistrationInformation))
            {
                returnnew ModelValidator[]
                {
                    new MyCustomModelPassWordValidator(metadata,context),
                    newMyCustomModelNameValidator(metadata,context)
                };
            }
            returnEnumerable.Empty<ModelValidator>();
        }
    }
}

在代碼1-6中,我們定義了個(gè)自定義的Model驗(yàn)證器提供程序MyCustomModelValidatorProvider類型,在MyCustomModelValidatorProvider類型中是根據(jù)GetValidators()方法的參數(shù)metadata所包含的信息來(lái)判斷自己被默認(rèn)的Model綁定器(DefaultModelBinder類型)調(diào)用的位置。(對(duì)于Model元數(shù)據(jù)部分大家可查看我前面跟大家分享的Model元數(shù)據(jù)系列)

到了這里幾乎就已經(jīng)全部完成了,現(xiàn)在注冊(cè)到系統(tǒng)中是不能使用的,有的朋友會(huì)罵了,不能用瞎扯蛋扯半天,大家莫急,聽(tīng)我解釋,是因?yàn)槲覀冏远x的Model驗(yàn)證器和Model驗(yàn)證器提供程序都要受到MVC框架的默認(rèn)的Model綁定器(DefaultModelBinder類型)調(diào)用的約束,是必須按照它方法內(nèi)部定義的來(lái)往下寫(xiě),在這里我們不圖省事,再定義一個(gè)自定義實(shí)現(xiàn)DefaultModelBinder類型的Model綁定器,來(lái)看示例代碼1-7。

代碼1-7

    public class MyCustomModelValidatorDefaultModelBinder : DefaultModelBinder
    {
        protectedoverride voidSetProperty(ControllerContextcontrollerContext, ModelBindingContextbindingContext, PropertyDescriptorpropertyDescriptor, 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 modelValidationResultin modelValidationResults)
                {
                   bindingContext.ModelState.AddModelError(modelValidationResult.MemberName,modelValidationResult.Message);
                }
            }
 
        }
        protectedoverride voidOnModelUpdated(ControllerContextcontrollerContext, ModelBindingContextbindingContext)
        {
            //base.OnModelUpdated(controllerContext,bindingContext);
            foreach(ModelValidator modelValidator in ModelValidatorProviders.Providers.GetValidators(bindingContext.ModelMetadata,controllerContext))
            {
                IEnumerable<ModelValidationResult> modelValidationResults =modelValidator.Validate(null);
                foreach(ModelValidationResult modelValidationResultin modelValidationResults)
                {
                    bindingContext.ModelState.AddModelError(modelValidationResult.MemberName,modelValidationResult.Message);
                }
            }
        }
    }

有了代碼1-7中的Model綁定器就可以吻合我們前面所定義的Model驗(yàn)證器以及提供程序了。

我要把MyCustomModelValidatorProvider類型和MyCustomModelValidatorDefaultModelBinder類型注冊(cè)到系統(tǒng)中,將示例代碼1-8部分添加至Global.asax文件的Application_Start()方法中。

代碼1-8

ModelBinders.Binders.Add(typeof(Models.RegistrationInformation), newBinders.MyCustomModelValidatorDefaultModelBinder());
ModelValidatorProviders.Providers.Insert(0, newModelValidators.MyCustomModelValidatorProvider());

看下圖1,圖1為初始的展示頁(yè)面,圖2為圖1中點(diǎn)擊提交后執(zhí)行驗(yàn)證過(guò)后。

圖1

ASP.NETMVC Model驗(yàn)證(四)

圖2

ASP.NETMVC Model驗(yàn)證(四)

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無(wú)理由+7*72小時(shí)售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國(guó)服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡(jiǎn)單易用、服務(wù)可用性高、性價(jià)比高”等特點(diǎn)與優(yōu)勢(shì),專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場(chǎng)景需求。

當(dāng)前標(biāo)題:ASP.NETMVCModel驗(yàn)證(四)-創(chuàng)新互聯(lián)
本文網(wǎng)址:http://bm7419.com/article20/dihgco.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)外貿(mào)網(wǎng)站建設(shè)、微信公眾號(hào)、域名注冊(cè)、網(wǎng)站導(dǎo)航、做網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都app開(kāi)發(fā)公司