changing viewmodel's MetadataType attribute at

2019-04-28 11:02发布

问题:

In Microsoft MVC 3.0,I have a class:

public class Product{
    public string Title {get;set;}
}

This class can be represent as Product or as Service , the only difference between them is just the field labels at View time.

so I create two classes :

 public class ProductMetaData
    {
        [Display(Name = "Product")]
        public object Title { get; set; }
    }

and

public class ServiceMetaData
    {
        [Display(Name = "Service")]
        public object Title { get; set; }
    }

How can I set these classes at runtime as MetadataType?

------------------------ EDIT --------------------------

I found we can set/change metadata for a type through inheriting DataAnnotationsModelMetadataProvider and DataAnnotationsModelValidatorProvider classes and overriding GetTypeDescriptor method in both like this:

 public class xx : DataAnnotationsModelMetadataProvider
{

    protected override ICustomTypeDescriptor GetTypeDescriptor(Type type)
    {

        if (type == typeof(InvoiceItemViewModel))
            return (new AssociatedMetadataTypeTypeDescriptionProvider(typeof(InvoiceItemViewModel), typeof(InvoiceItemMetaData))).GetTypeDescriptor(type);
        else
            return base.GetTypeDescriptor(type);
    }
}

 public class yy : DataAnnotationsModelValidatorProvider
{

    protected override ICustomTypeDescriptor GetTypeDescriptor(Type type)
    {

        if (type == typeof(InvoiceItemViewModel))
            return (new AssociatedMetadataTypeTypeDescriptionProvider(typeof(InvoiceItemViewModel), typeof(InvoiceItemMetaData))).GetTypeDescriptor(type);
        else
            return base.GetTypeDescriptor(type);
    }

}

And the following changes in Global.ascx

ModelMetadataProviders.Current = new xx();

ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add(new yy());

BUT the question is how can depend it on Model Instance and not just type?!...As I see there is no any access to Model through these classes. Is there any place in MVC pipleline to change these two provider classess based on Model data? (for example in : OnActionExecuting or something else?)

回答1:

You could write a custom model metadata provider. For example you may take a look at MvcExtensions. They implemented such provider in order to be able to dynamically associate metadata to a given type at runtime. The same technique is used by FluentValidation.NET.