惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
J
Java Code Geeks
Martin Fowler
Martin Fowler
宝玉的分享
宝玉的分享
V
Visual Studio Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
M
MIT News - Artificial intelligence
U
Unit 42
博客园 - 三生石上(FineUI控件)
博客园 - 聂微东
The GitHub Blog
The GitHub Blog
I
InfoQ
WordPress大学
WordPress大学
H
Help Net Security
D
Docker
B
Blog
腾讯CDC
A
About on SuperTechFans
Recent Announcements
Recent Announcements
雷峰网
雷峰网
有赞技术团队
有赞技术团队
C
Check Point Blog
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC

博客园 - 阿不

10年总结,得到与失去 Windows phone7 软件发布:理财计算器(包括wp7房贷计算器,wp7个税计算器,wp7存款利息计算器) 从.NET到Mono-记Kooboo CMS对Mono的兼容历程:三、平台的兼容性 从.NET到Mono-记Kooboo CMS对Mono的兼容历程:二、大小写敏感问题,到处都是地雷 从.NET到Mono-记Kooboo CMS对Mono的兼容历程:一、Mono以及移平台的基本注意要点 ASP.NET MVC3 on Mono的折腾(一):Windows下的部署 ASP.NET MVC3 on Mono的折腾(二):Linux(openSUSE)下的部署 迟到的2010总结 周末随想之移动随笔 NVelocity for ASP.NET MVC ASP.NET 4.0在IIS6原生支持没有后缀名的URL请求 闲语MVC3和Razor ASP.NET MVC3 RC2和一些小bug ASP.NET MVC 的统一异常处理有多难?(衍生的意图,出错后如何保持表单的状态?) Attribute与TypeDescriptor的故事 DataContext是否可以静态化? 今日手记:ASP.NET进程内的定时任务 有趣的同名不同约束泛型扩展方法的编译问题 在程序中动态执行T4模板,如何传参数给T4模板?
DataAnnotation脱离MVC独立验证
阿不 · 2010-11-07 · via 博客园 - 阿不

我们知道DataAnnotations是一个通用的数据模型元数据定义框架,其中最主要的部分是验证框架的定义。DataAnnotations可用户.NET平台的任何应用框架,但我们的项目中都是借助MVC来使用DataAnnotations。在MVC框架中,还对DataAnnotations进行了很多的扩展和适配:比如需要根据定义的DataAnnotations,生成客户端的验证;在Controller模型中绑定模型对数据进行有效性验证等等。我们的数据模型如果都是通过MVC入口,用户输入有的有效性验证的工作都可以交给MVC框架和DataAnnotations来完成。在我们的实践中,这样确实给我们带来了很大的的方便。

但是,当我们的数据入口不是走MVC通道,而是通过其它的入口(WebService,或其它服务)进来,这时我们就很难利用现有的MVC验证框架,我们可以模拟很多请求Context,并最终模拟ControllerContext,但是这样的工作实在太麻烦了。既然使用了DataAnnotations的验证标签定义,最好的方案还是复用这些标签,使用同一套验证机制。翻开DataAnnotations源码,希望能找到一个独立验证的辅助方法,很遗憾,并没有找到。

还是只能自己来实现这个功能,在没有下手之前好像还是有点麻烦的感觉(好像这是我们一贯的毛病,总是把很多事情都想的很难的样子,而且很多时候心里总会有点抵触,这点一定要在工作中好好改进)。不过,一切还是很简单的,主要还是要归功于TypeDescriptor。TypeDescriptor为我们准备好了类型相关的所有元信息,而且还可以通过它得到属性的PropertyDescriptor,这一下就简化了太多的工作。

public class ModelValidationError
{
    public string FieldName { get; set; }
    public string Message { get; set; }
}
public static class DataAnnotationHelper
{
    public static IEnumerable<ModelValidationError> IsValid<T>(this T o)
    {
        var descriptor = GetTypeDescriptor(typeof(T));

        foreach (PropertyDescriptor propertyDescriptor in descriptor.GetProperties())
        {
            foreach (var validationAttribute in propertyDescriptor.Attributes.OfType<ValidationAttribute>())
            {
                if (!validationAttribute.IsValid(propertyDescriptor.GetValue(o)))
                {
                    yield return new ModelValidationError() { FieldName = propertyDescriptor.Name, Message = validationAttribute.FormatErrorMessage(propertyDescriptor.Name) };
                }
            }
        }
    }
    private static ICustomTypeDescriptor GetTypeDescriptor(Type type)
    {
        return new AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type);
    }
}

很简单,只需要几行代码就可以完成基于DataAnnotations的独立验证。值得注意的是,上面使用AssociatedMetadataTypeTypeDescriptionProvider来获取TypeDescriptor,是希望兼容MetadataType的方式注入元数据。有了上面的辅助方法,我们验证实体的有效性就变得非常轻松:

public class Model1
{
    [Required]
    public string Name { get; set; }

    [Range(1, 100)]
    public int Age { get; set; }
}
class Program
{
    static void Main(string[] args)
    {
        Model1 model = new Model1();
        foreach (var item in model.IsValid())
        {
            Console.WriteLine("FieldName:{0} Error Message:{1}", item.FieldName, item.Message);
        }
        Console.ReadLine();
    }
}

非常简单的扩展,非常完美的解决了我的问题。希望也对你有所帮助。