技术承载元数据视图模型与AutoMapper [英] Technique for carrying metadata to View Models with AutoMapper

查看:177
本文介绍了技术承载元数据视图模型与AutoMapper的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我用AutoMapper到我的域对象映射到我的视图模型。我有元数据我的域名层,我想结转到视图层和成ModelMetadata。 (该元数据是不是UI逻辑,但我的意见提供了必要的信息)。

I use AutoMapper to map my domain objects to my view models. I have metadata in my domain layer, that I would like to carry over to the view layer and into ModelMetadata. (This metadata is not UI logic, but provides necessary information to my views).

现在,我的解决方法是使用一个单独的MetadataProvider(独立ASP.NET MVC的),使用约定通过AssociatedMetadataProvider相关的元数据应用到ModelMetadata对象。这种方法的问题是,我从域绑定ModelMetadata时,我用我的自动映射做测试相同的约定,而且好像应该有一种方法,使这更是正交的。谁能推荐一个更好的方式来做到这一点?

Right now, my solution is to use a separate MetadataProvider (independently of ASP.NET MVC), and use conventions to apply the relevant metadata to the ModelMetadata object via an AssociatedMetadataProvider. The problem with this approach is that I have to test for the same conventions when binding the ModelMetadata from the domain as I do with my AutoMapping, and it seems like there should be a way to make this more orthogonal. Can anyone recommend a better way to accomplish this?

推荐答案

我用下面的方法自动数据注解从我的实体复制到我的视图模型。这确保了之类的东西StringLength和所需值始终为实体/视图模型是一样的。

I use the approach below to automatically copy data annotations from my entities to my view model. This ensures that things like StringLength and Required values are always the same for entity/viewmodel.

它的工作原理使用Automapper配置,因此如果工作的性质不同的视图模型只要AutoMapper是设置正确命名。

It works using the Automapper configuration, so works if the properties are named differently on the viewmodel as long as AutoMapper is setup correctly.

您需要创建一个自定义ModelValidatorProvider和定制ModelMetadataProvider得到这个工作。我为什么有点云里雾里,但我相信它是如此的服务器和客户端验证工作,以及任何其他格式化你基于元数据存储(如一个星号旁边必填项)。

You need to create a custom ModelValidatorProvider and custom ModelMetadataProvider to get this to work. My memory on why is a little foggy, but I believe it's so both server and client side validation work, as well as any other formatting you do based on the metadata (eg an asterix next to required fields).

请注意:我已经简化了我的code稍微因为我在下面加了,所以可能会有一些小问题。

Note: I have simplified my code slightly as I added it below, so there may be a few small issues.

元数据提供商

public class MetadataProvider : DataAnnotationsModelMetadataProvider
{        
    private IConfigurationProvider _mapper;

    public MetadataProvider(IConfigurationProvider mapper)
    {           
        _mapper = mapper;
    }

    protected override System.Web.Mvc.ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
    {           
        //Grab attributes from the entity columns and copy them to the view model
        var mappedAttributes = _mapper.GetMappedAttributes(containerType, propertyName, attributes);

        return base.CreateMetadata(mappedAttributes, containerType, modelAccessor, modelType, propertyName);

}
}

验证Provivder

public class ValidatorProvider : DataAnnotationsModelValidatorProvider
{
    private IConfigurationProvider _mapper;

    public ValidatorProvider(IConfigurationProvider mapper) 
    {
        _mapper = mapper;
    }

    protected override System.Collections.Generic.IEnumerable<ModelValidator> GetValidators(System.Web.Mvc.ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
    {   
        var mappedAttributes = _mapper.GetMappedAttributes(metadata.ContainerType, metadata.PropertyName, attributes);
        return base.GetValidators(metadata, context, mappedAttributes);
    }
}

上面提到的在

helper方法2班

public static IEnumerable<Attribute> GetMappedAttributes(this IConfigurationProvider mapper, Type sourceType, string propertyName, IEnumerable<Attribute> existingAttributes)
{
    if (sourceType != null)
    {
        foreach (var typeMap in mapper.GetAllTypeMaps().Where(i => i.SourceType == sourceType))
        {
            foreach (var propertyMap in typeMap.GetPropertyMaps())
            {
                if (propertyMap.IsIgnored() || propertyMap.SourceMember == null)
                    continue;

                if (propertyMap.SourceMember.Name == propertyName)
                {
                    foreach (ValidationAttribute attribute in propertyMap.DestinationProperty.GetCustomAttributes(typeof(ValidationAttribute), true))
                    {
                        if (!existingAttributes.Any(i => i.GetType() == attribute.GetType()))
                            yield return attribute;
                    }
                }
            }
        }
    }

    if (existingAttributes != null)
    {
        foreach (var attribute in existingAttributes)
        {
            yield return attribute;
        }
    }

}

其他注意事项


  • 如果您正在使用依赖注入,请确保您的容器是不是已经更换内置的元数据提供者或验证提供者。在我来说,我用它创建内核之后绑定其中的一Ninject.MVC3包,然后我不得不重新绑定之后这样实际使用我的课。我得到大约只需要被允许添加一次例外,大多数花了一天的跟踪下来。

这篇关于技术承载元数据视图模型与AutoMapper的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆