ASP.NET MVC验证框架中关于属性标记的通用扩展方法

  之前写过一篇文章《ASP.NET MVC中的验证》,唯一的遗憾就是在使用Data Annotation Validators方式验证的时候,如果数据库是Entityframework等自动生成的文件,就没有办法使用扩展属性标记进行标记。现在已经开始有了一些其它的Asp.net MVC 验证框架,使用上跟Data Annotation Validators差不太多,但是普遍有这样的问题,如果数据库是Entityframework生成的edm文件,没有办法进行扩展属性标记。

  今天在网上发现了另外一个 Asp.net MVC 验证框架---xVal框架,使用上跟Data Annotation Validators非常接近,也有类似的问题。

  简单介绍下,xVal是一个开源的asp.net mvc验证框架,有关它的介绍,可以参考:《xVal - a validation framework for ASP.NET MVC》

  xVal使用了MS-PL的开源协议 ,也就是说,它允许用户看、修改和分发源代码,而不论出自商业用途还是非商业用途,类似BSD许可证。

  xVal可以通过IRulesProvider接口,通过这个接口可以进行扩展,很明显,它只扩展了Castle框架跟NHibernate框架,通过如下两个程序集就可以看出来:

xVal.RulesProviders.CastleValidator.dll

xVal.RulesProviders.NHibernateValidator.dll

  基本上可以得出结论:xVal没有提供对Entityframework框架的扩展,还需要我们做扩展。

  最终,网上的一片文章给了我提示,问题得到了解决,解决的思路就是建立一个伙伴类,这个伙伴类跟原来的类的结构定义是一样的,在进行验证的时候,不对edm文件中的类进行验证,而是对伙伴类进行验证。

  这里就以xVal框架为例进行Demo演示吧。

  首先我们建立一个类模拟Entityframework生成的edm文件中的类,类的定义代码如下:

模拟EF中的User类    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;}

    }

   接下来我们建立一个伙伴类

伙伴类的代码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; }

    }

  再接下来,我们使用partial关键字为User类进行扩展,扩展类的定义如下:

扩展类的定义    [MetadataType(typeof(UserMetadata))]

    public partial class User

    { 

        

    }

  注意这段代码:[MetadataType(typeof(UserMetadata))]

  为了方便大家阅读,我把整体代码贴出来,整体代码如下:

整体代码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; }

    }

}

  接下来,我们要实现伙伴类跟原类的替换方法了,代码如下所示:

DataAnnotationsValidationRunner类的代码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<ErrorInfo> GetErrors(object instance)

        //{

        //    return from prop in TypeDescriptor.GetProperties(instance).Cast<PropertyDescriptor>()

        //           from attribute in prop.Attributes.OfType<ValidationAttribute>()

        //           where !attribute.IsValid(prop.GetValue(instance))

        //           select new ErrorInfo(prop.Name, attribute.FormatErrorMessage(string.Empty), instance);

        //}

/// <summary>

        /// Get any errors associated with the model also investigating any rules dictated by attached Metadata buddy classes.

        /// </summary>

        /// <param name="instance"></param>

        /// <returns></returns>

        public static IEnumerable<ErrorInfo> GetErrors(object instance)

        {

            var metadataAttrib = instance.GetType().GetCustomAttributes(typeof(MetadataTypeAttribute), true).OfType<MetadataTypeAttribute>().FirstOrDefault();

            var buddyClassOrModelClass = metadataAttrib != null ? metadataAttrib.MetadataClassType : instance.GetType();

            var buddyClassProperties = TypeDescriptor.GetProperties(buddyClassOrModelClass).Cast<PropertyDescriptor>();

            var modelClassProperties = TypeDescriptor.GetProperties(instance.GetType()).Cast<PropertyDescriptor>();

return from buddyProp in buddyClassProperties

                   join modelProp in modelClassProperties on buddyProp.Name equals modelProp.Name

                   from attribute in buddyProp.Attributes.OfType<ValidationAttribute>()

                   where !attribute.IsValid(modelProp.GetValue(instance))

                   select new ErrorInfo(buddyProp.Name, attribute.FormatErrorMessage(string.Empty), instance);

        }

    }

}

  完成以上的代码以后,大部分工作就完成了,接下来,我们在Controller中编写一个create方法,来模拟Create操作,代码如下所示:

时间: 2024-12-04 08:52:43

ASP.NET MVC验证框架中关于属性标记的通用扩展方法的相关文章

《ASP.NET MVC验证框架中关于属性标记的通用扩展方法》之继续扩展

首先需要对xVal有点熟悉: http://www.codeplex.com/xval 建议下载最新源码而不是编译版本 再看两篇文章: http://goneale.com/2009/03/04/using-metadatatype-attribute-with-aspnet-mvc-xval- validation-framework/ 深山老林将之翻译为:<ASP.NET MVC验证框架中关于属性标记的通用扩展方法> http://www.cnblogs.com/wlb/archive/2

一起谈.NET技术,ASP.NET MVC验证框架中关于属性标记的通用扩展方法

之前写过一篇文章<ASP.NET MVC中的验证>,唯一的遗憾就是在使用Data Annotation Validators方式验证的时候,如果数据库是Entityframework等自动生成的文件,就没有办法使用扩展属性标记进行标记.现在已经开始有了一些其它的Asp.net MVC 验证框架,使用上跟Data Annotation Validators差不太多,但是普遍有这样的问题,如果数据库是Entityframework生成的edm文件,没有办法进行扩展属性标记. 今天在网上发现了另外一

解决Asp.net Mvc返回JsonResult中DateTime类型数据格式问题的方法_实用技巧

问题背景:            在使用asp.net mvc 结合jquery esayui做一个系统,但是在使用使用this.json方法直接返回一个json对象,在列表中显示时发现datetime类型的数据在转为字符串是它默认转为Date(84923838332223)的格式,在经过查资料发现使用前端来解决这个问题的方法不少,但是我又发现在使用jquery easyui时,加载列表数据又不能对数据进行拦截,进行数据格式转换之后再加载,后来发现可以通过自定义JsonResult实现,认为这种

ASP.NET MVC+EF框架+EasyUI实现权限管理系列(17)-注册用户功能的细节处理(各种验证)

原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(17)-注册用户功能的细节处理(各种验证) ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装    (5):前台Jquery easyUI实现    (6):EF上下文实例管理    (7):DBSession的封装   (8):DBSession线程内唯一     (9):TT摸版

ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加

原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(16)-类库架构扩展以及DLL文件生成修改和用户的简单添加 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装    (5):前台Jquery easyUI实现    (6):EF上下文实例管理    (7):DBSession的封装   (8):DBSession线程内唯一     

ASP.NET MVC+EF框架+EasyUI实现权限管理系列(23)-设置角色遗留问题和为权限设置角色以及EasyUI Tabs的使用

原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(23)-设置角色遗留问题和为权限设置角色以及EasyUI Tabs的使用 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装          (5):前台Jquery easyUI实现   (6):EF上下文实例管理    (7):DBSession的封装   (8):DBSessi

ASP.NET MVC+EF框架+EasyUI实现权限管理系列(22)-为用户设置角色

原文:ASP.NET MVC+EF框架+EasyUI实现权限管理系列(22)-为用户设置角色 ASP.NET MVC+EF框架+EasyUI实现权限管系列 (开篇)   (1):框架搭建    (2):数据库访问层的设计Demo    (3):面向接口编程   (4 ):业务逻辑层的封装          (5):前台Jquery easyUI实现   (6):EF上下文实例管理    (7):DBSession的封装   (8):DBSession线程内唯一          (9):TT摸版

ASP.NET MVC 验证方式(1)

实现一个简单的验证(C#) 本部分主要目的是说明如何在ASP.NET MVC应用程序中实现验证.例如,将了解如何验证一个表单提交时必填内容的合法性.了解如何应用model state和验证相关的HTML helpers. 理解Model State 你使用model state,更准确点说是使用model state 字典去表示验证错误.比如,列表一中的Create()方法,在产品类保存入库之前去验证产品类的属性. 把验证和数据逻辑加到控制类中是违反编程方法的,控制类中应该仅包含程序的流程逻辑.

“.NET研究”专访微软MVP衣明志:走进ASP.NET MVC 2框架开发

日前微软已经发布ASP.NET MVC 2框架RC版,究竟这次RC版本的发布对于WEB开发者带来怎样的改变?以及未来ASP.NET MVC 2正式版还会有哪些改进?带着这样的问题,我们51CTO记者彭凡专门采访了微软MVP衣明志老师.ASP.NET MVC是微软官方提供的MVC模式编写ASP.NET WEB应用程序的一个框架. MVP专访人物介绍 衣明志,蝉联五届微软MVP,烟台.NET俱乐部主席,现主要从事.NET平台下的Web应用开发.解决方案.构架设计及技术培训等工作.   照片居中者为衣