ASP.NET MVC: Accessing ViewModel Attributes on the view
Asked Answered
H

2

6

Is there any way to access any attributes (be it data annotation attributes, validation attributes or custom attributes) on ViewModel properties from the view? One of the things I would like to add a little required indicator next to fields whose property has a [Required] attribute.

For example if my ViewModel looked like this:

public class MyViewModel
{
    [Required]
    public int MyRequiredField { get; set; } 
}

I would want to do something in the EditorFor template like so:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<int?>" %>

<div class="label-container">
    <%: Html.Label("") %>

    <% if (PROPERTY_HAS_REQUIRED_ATTRIBUTE) { %>
        <span class="required">*</span>
    <% } %>
</div>
<div class="field-container">
    <%: Html.TextBox("") %>
    <%: Html.ValidationMessage("") %>
</div>
Hallowmas answered 21/9, 2011 at 23:52 Comment(0)
T
8

The information you're looking for is in ViewData.ModelMetadata. Brad Wilson's blog post series on Templates should explain it all, especially the post on ModelMetadata.

As far as the other ValidationAttributes go, you can access them via the ModelMetadata.GetValidators() method.

ModelMetadata.IsRequired will tell you if a complex type (or value type wrapped in Nullable<T>) is required by a RequiredAttribute, but it will give you false positives for value types that are not nullable (because they are implicitly required). You can work around this with the following:

bool isReallyRequired = metadata.IsRequired 
    && (!metadata.ModelType.IsValueType || metadata.IsNullableValueType);

Note: You need to use !metadata.ModelType.IsValueType instead of model.IsComplexType, because ModelMetadata.IsComplexType returns false for MVC does not consider to be a complex type, which includes strings.

Terryn answered 22/9, 2011 at 1:43 Comment(3)
What about validation attributes like my EditorFor needs above? In that blog post Brad says the the only attributes that affect ModelMetadata are [HiddenInput], [UIHint], [DataType], [ReadOnly], [DisplayFormat], [ScaffoldColumn] and [DisplayName]Hallowmas
They're accessible via the GetValidators method. I've updated my answer to reflect this. I'm not sure about other non-validation attributes though.Terryn
The other way to get attribute information is via reflection. e.g. typeof(YourModel).GetProperty("PropertyName").GetCustomAttributes(), but you definitely shouldn't be doing that in a view.Terryn
D
1

I would suggest not doing that way because you're adding logic in the view which is a bad practice. Why don't you create a HtmlHelper or LabelExtension, you can call ModelMetaProvider inside the method and find out whether the property has Required attribute decorated?

Deltadeltaic answered 22/9, 2011 at 1:41 Comment(1)
Good point, though my example above was simplified. My question is more around how I find out whether the property has the required attribute. I had seen the ModelMetaProvider but its IsRequired property isn't dependent on the [Required] attribute. All I want is a list of attributes...Hallowmas

© 2022 - 2024 — McMap. All rights reserved.