新聞中心
本文將討論的是ASP.NET MVC中屬性標(biāo)記的通用擴(kuò)展方法,在這里我們也將更進(jìn)一步的了解ASP.NET MVC的作用。希望大家能用好ASP.MVC。

創(chuàng)新互聯(lián)公司堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)、成都網(wǎng)站制作、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的烏什網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
#T#
之前寫(xiě)過(guò)一篇文章《ASP.NET MVC中的驗(yàn)證》,唯一的遺憾就是在使用Data Annotation Validators方式驗(yàn)證的時(shí)候,如果數(shù)據(jù)庫(kù)是Entityframework等自動(dòng)生成的文件,就沒(méi)有辦法使用擴(kuò)展屬性標(biāo)記進(jìn)行標(biāo)記?,F(xiàn)在已經(jīng)開(kāi)始有了一些其它的ASP.NET MVC 驗(yàn)證框架,使用上跟Data Annotation Validators差不太多,但是普遍有這樣的問(wèn)題,如果數(shù)據(jù)庫(kù)是Entityframework生成的edm文件,沒(méi)有辦法進(jìn)行擴(kuò)展屬性標(biāo)記。
今天在網(wǎng)上發(fā)現(xiàn)了另外一個(gè) ASP.NET MVC 驗(yàn)證框架---xVal框架,使用上跟Data Annotation Validators非常接近,也有類(lèi)似的問(wèn)題。
簡(jiǎn)單介紹下,xVal是一個(gè)開(kāi)源的ASP.NET MVC驗(yàn)證框架,有關(guān)它的介紹,可以參考:《xVal - a validation framework for ASP.NET MVC》
xVal使用了MS-PL的開(kāi)源協(xié)議 ,也就是說(shuō),它允許用戶看、修改和分發(fā)源代碼,而不論出自商業(yè)用途還是非商業(yè)用途,類(lèi)似BSD許可證。
xVal可以通過(guò)IRulesProvider接口,通過(guò)這個(gè)接口可以進(jìn)行擴(kuò)展,很明顯,它只擴(kuò)展了Castle框架跟NHibernate框架,通過(guò)如下兩個(gè)程序集就可以看出來(lái):
xVal.RulesProviders.CastleValidator.dllxVal.RulesProviders.NHibernateValidator.dll基本上可以得出結(jié)論:xVal沒(méi)有提供對(duì)Entityframework框架的擴(kuò)展,還需要我們做擴(kuò)展。
最終,網(wǎng)上的一片文章給了我提示,問(wèn)題得到了解決,解決的思路就是建立一個(gè)伙伴類(lèi),這個(gè)伙伴類(lèi)跟原來(lái)的類(lèi)的結(jié)構(gòu)定義是一樣的,在進(jìn)行驗(yàn)證的時(shí)候,不對(duì)edm文件中的類(lèi)進(jìn)行驗(yàn)證,而是對(duì)伙伴類(lèi)進(jìn)行驗(yàn)證。
這里就以xVal框架為例進(jìn)行Demo演示吧。
首先我們建立一個(gè)類(lèi)模擬Entityframework生成的edm文件中的類(lèi),類(lèi)的定義代碼如下:
模擬EF中的User類(lèi)
- public partial class User
- {
- public string UserName { get; set; }
- public string Password { get; set; }
- public string Address { get; set; }
- public string Telephone { get; set; }
- public int Age { get; set; }
- public string Email { get;set;}
- }
接下來(lái)我們建立一個(gè)伙伴類(lèi)
伙伴類(lèi)的代碼
- public class UserMetadata
- {
- [Required]
- [StringLength(10)]
- public string UserName { get; set; }
- [Required]
- [StringLength(18)]
- [DataType(DataType.Password)]
- public string Password { get; set; }
- [Required]
- [StringLength(100)]
- public string Address { get; set; }
- [Required]
- [DataType(DataType.PhoneNumber)]
- public string Telephone { get; set; }
- [Required]
- [Range(1, 100)]
- public int Age { get; set; }
- [Required]
- [DataType(DataType.EmailAddress)]
- public string Email { get; set; }
- }
再接下來(lái),我們使用partial關(guān)鍵字為User類(lèi)進(jìn)行擴(kuò)展,擴(kuò)展類(lèi)的定義如下:
擴(kuò)展類(lèi)的定義
- [MetadataType(typeof(UserMetadata))]
- public partial class User
- {
- }
注意這段代碼:[MetadataType(typeof(UserMetadata))]
為了方便大家閱讀,我把整體代碼貼出來(lái),整體代碼如下:
整體代碼
- using System.ComponentModel.DataAnnotations;
- namespace MVCValidate.Models
- {
- public partial class User
- {
- public string UserName { get; set; }
- public string Password { get; set; }
- public string Address { get; set; }
- public string Telephone { get; set; }
- public int Age { get; set; }
- public string Email { get;set;}
- }
- [MetadataType(typeof(UserMetadata))]
- public partial class User
- {
- }
- public class UserMetadata
- {
- [Required]
- [StringLength(10)]
- public string UserName { get; set; }
- [Required]
- [StringLength(18)]
- [DataType(DataType.Password)]
- public string Password { get; set; }
- [Required]
- [StringLength(100)]
- public string Address { get; set; }
- [Required]
- [DataType(DataType.PhoneNumber)]
- public string Telephone { get; set; }
- [Required]
- [Range(1, 100)]
- public int Age { get; set; }
- [Required]
- [DataType(DataType.EmailAddress)]
- public string Email { get; set; }
- }
- }
接下來(lái),我們要實(shí)現(xiàn)伙伴類(lèi)跟原類(lèi)的替換方法了,代碼如下所示:
DataAnnotationsValidationRunner類(lèi)的代碼
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.ComponentModel.DataAnnotations;
- using System.Linq;
- using xVal.ServerSide;
- namespace MVCValidate.Models
- {
- internal static class DataAnnotationsValidationRunner
- {
- // TODO: DOES NOT SUPPORT METADATA TYPE
- ///// Warning: For some reason, DataTypeAttribute.IsValid() always returns "true", regardless of whether
- ///// it is actually valid. Need to improve this test runner to fix that.
- //public static IEnumerable
GetErrors(object instance) - //{
- // return from prop in TypeDescriptor.GetProperties(instance).Cast
() - // from attribute in prop.Attributes.OfType
() - // where !attribute.IsValid(prop.GetValue(instance))
- // select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), instance);
- //}
- ///
- /// Get any errors associated with the model also investigating any rules dictated by attached Metadata buddy classes.
- ///
- ///
- ///
- public static IEnumerable
GetErrors(object instance) - {
- var metadataAttrib = instance.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true)
- .OfType
().FirstOrDefault(); - var buddyClassOrModelClass = metadataAttrib != null ? metadataAttrib.MetadataClassType : instance.GetType();
- var buddyClassProperties = TypeDescriptor.GetProperties(buddyClassOrModelClass).Cast
(); - var modelClassProperties = TypeDescriptor.GetProperties(instance.GetType()).Cast
(); - return from buddyProp in buddyClassProperties
- join modelProp in modelClassProperties on buddyProp.Name equals modelProp.Name
- from attribute in buddyProp.Attributes.OfType
() - where !attribute.IsValid(modelProp.GetValue(instance))
- select new ErrorInfo(buddyProp.Name, attribute.FormatErrorMessage(string.Empty), instance);
- }
- }
- }
完成以上的代碼以后,大部分工作就完成了,接下來(lái),我們?cè)贑ontroller中編寫(xiě)一個(gè)create方法,來(lái)模擬Create操作,代碼如下所示:
Controller層的代碼
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Web;
- using System.Web.Mvc;
- using System.Web.Mvc.Ajax;
- using MVCValidate.Models;
- using xVal.ServerSide;
- namespace MVCValidate.Controllers
- {
- public class UserController : Controller
- {
- [AcceptVerbs(HttpVerbs.Post)]
- public ActionResult Create(User user)
- {
- var errors = DataAnnotationsValidationRunner.GetErrors(user);
- if (errors.Any())
- {
- new RulesException(errors).AddModelStateErrors(ModelState,"user");
- }
- return View();
- }
- }
- }
接下來(lái),編寫(xiě)View層的代碼,比較簡(jiǎn)單,我就直接貼出來(lái)了,代碼如下:
View層的代碼
- <%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage
" %> - >
- xmlns="http://www.w3.org/1999/xhtml" >
- runat="server">
Create - <%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>
- <% using (Html.BeginForm()) {%>
- Fields
- <%= Html.TextBox("user.UserName") %>
- <%= Html.ValidationMessage("user.UserName")%>
- <%= Html.TextBox("user.Password") %>
- <%= Html.ValidationMessage("user.Password")%>
- <%= Html.TextBox("user.Address")%>
- <%= Html.ValidationMessage("user.Address")%>
- <%= Html.TextBox("user.Telephone")%>
- <%= Html.ValidationMessage("user.Telephone")%>
- <%= Html.TextBox("user.Age")%>
- <%= Html.ValidationMessage("user.Age")%>
- <%= Html.TextBox("user.Email")%>
- <%= Html.ValidationMessage("user.Email")%>
- type="submit" value="Create" />
- <% } %>
- <%=Html.ActionLink("Back to List", "Index") %>
最終的效果如下圖所示:
ASP.NET MVC開(kāi)源驗(yàn)證框架非常的多,只是有相似問(wèn)題的更多,有了這個(gè)通用的方法,就可以很容易對(duì)其他驗(yàn)證框架進(jìn)行擴(kuò)展了。
新聞名稱(chēng):詳解ASP.NET MVC中屬性標(biāo)記的通用擴(kuò)展方法
當(dāng)前地址:http://m.fisionsoft.com.cn/article/dhhgiod.html


咨詢
建站咨詢
