简体   繁体   中英

Get ModelMetadata for specific instance

I am trying to get the metadata associated with an instance in an array. I have defined a HtmlHelper extension which is invoked in my view. I am trying to create a helper that displays a list of models and their error messages.

@model Domain.Models.Customer
@this.Html.Example(m => m.Orders)

Below is this implementation of my helper

public static class HtmlHelperExtensions
{
    public static IHtmlString Example<TModel, TInstance>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TInstance[]>> expression)
    {
        var instanceProvider = expression.Compile();
        var instances = instanceProvider.Invoke(helper.ViewData.Model);

        if(instances != null)
        {
            var properties = typeof (TInstance).GetProperties();
            for(var i = 0; i < instances.Length; i++)
            {
                var instanceExpression = Expression.ArrayIndex(expression.Body, Expression.Constant(i));

                foreach(var info in properties)
                {
                    var propertyExpression = Expression.Property(instanceExpression, info);

                    // How can i get access to the ModelMetadata
                    ModelMetadata.FromStringExpression(propertyExpression.ToString(), helper.ViewData);

                    // To get the model state we need the following...
                    var text = ExpressionHelper.GetExpressionText(Expression.Lambda(propertyExpression));
                    var fieldName = helper.ViewData.TemplateInfo.GetFullHtmlFieldName(text);

                    ModelState state;
                    if(helper.ViewData.ModelState.TryGetValue(fieldName, out state))
                    {
                        // Output errors....
                    }
                }

            }
        }

        return MvcHtmlString.Empty;
    }
}

Using the following domain classes

public class Customer
{
    public Order[] Orders { get; set; }
}

public class Order
{
    public string Description { get; set; }
}

As far as I know it's not there!

The ModelMetadata will be for the Properties of the Model which is in this case the properties of the array itself not the element inside the array.

So if you need ModelMetadata for the elements inside the array, you will need to create Custom Model Metadata Provider which will get the attributes that you need and add them to the ModelMetadata, example guide code snippet

public class ArrayMetadataProvider : DataAnnotationsModelMetadataProvider
{

    protected override ModelMetadata CreateMetadata(IEnumerable<Attribute> attributes, Type containerType,
                                                    Func<object> modelAccessor, Type modelType, string propertyName)
    {
        var metadata = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);

        // Add your metadata here

        return metadata;
    }

}

And then you will need to register this provider as the following:

 protected void Application_Start()
    {

        ModelMetadataProviders.Current = new ArrayMetadataProvider();

    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM