views:

532

answers:

1

Brad Wilson posted a great blog series on ASP.NET MVC's new ModelMetaData: http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html

In it, he describes how the ModelMetaData class is now exposed in the Views and templated helpers. What I'd like to do is display an asterisk beside a form field label if the field is required, so I thought about using the IsRequired property of ModelMetaData. However, IsRequired by default is true for all non-nullable properties, while it's false for all nullable properties. The problem is, strings are always nullable, so the IsRequired property is always false for strings. Does anyone know how to override the default of how IsRequired is set? Alternatively, I thought about leveraging the RequiredAttribute attribute that I've been decorating my properties with, but the RequiredAttribute doesn't seem to be exposed through the ModelMetaData class. Does anyone know how to get around this problem?

Thanks in advance.

+3  A: 

You need to create your own ModelMetadataProvider. Here's an example using the DataAnnotationsModelBinder

public class MyMetadataProvider : DataAnnotationsModelMetadataProvider
{
        protected override ModelMetadata CreateMetadata(Collections.Generic.IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName)
        {
            var _default = base.CreateMetadata(attributes, containerType, modelAccessor, modelType, propertyName);
            _default.IsRequired = attributes.Where(x => x is RequiredAttribute).Count() > 0;
            return _default;
        }
}

Then in your AppStartup in Global.asax, you will want to put the following in to hookup the MyMetadataProvider as the default metadata provider:

ModelMetadataProviders.Current = new MyMetadataProvider();
zowens
Thanks. This is exactly the kind of solution that I was looking for. However, I can't seem to get this to work properly. Even through my property is decorated with RequiredAttribute and it's showing up properly in the "attributes" list in CreateMetadata(), attributes.Where(x => x.Equals(typeof(RequiredAttribute))) returns an empty list, which results in IsRequired still being false. Is there something wrong that I'm doing with this lambda expression?
JohnnyO
"x.Equals(typeof(RequiredAttribute))" should read "x is RequiredAttribute". *x* is an instance of an attribute, not the type of the attribute.
Levi
Thanks Zowens and Levi. My problem is now solved.
JohnnyO
Thanks for catching that Levi! I'll edit my answer.
zowens
Awesome, thanks for the solution. You can also simplify the LINQ query to a simple `attributes.Any(x => x is RequiredAttribute);`.
kdawg