James Thorpe
James Thorpe

Reputation: 32202

How can I use a custom editor template when using data annotations?

I have a simple model:

public class MyViewModel {
    public MyCustomType EmailAddress {get; set; }
}

In a certain view, I need to present an input box to allow editing of this property. Ideally I want to keep using the standard @Html.EditorFor syntax, so I've created a /Views/Shared/EditorTemplates/MyCustomType.cshtml template:

@model MyNamespace.MyCustomType
@Html.TextBoxFor(m => m.SomeStringProperty, new { @class = "form-control" })

I also have a custom IModelBinder to read this input back into MyCustomType when it's submitted, this all works fine.

However, as you can see from the property name, this property contains an Email address. I'd like to use the standard data annotations attributes to mark it as such, and then update MyCustomType.cshtml to make use of it to render an <input type="email"> input box when necessary - not all uses of MyCustomType are email addresses, hence wanting to use the standard attributes to mark it as such. When I do so:

public class MyViewModel {
    [EmailAddress]
    public MyCustomType EmailAddress {get; set; }
}

My custom template is no longer used - it instead reverts back to using the standard EditorFor code, and essentially just displays the .ToString() version of MyCustomType inside an <input>, rather than my custom editor template which pulls out a specific property.

Is there a way to make it use my custom editor template functionality, while still only requiring models to add the standard data annotations attributes?

Upvotes: 0

Views: 621

Answers (1)

Chris Pratt
Chris Pratt

Reputation: 239290

Data annotations always take precedence over the type when it comes to editor templates. You have a few options:

  1. Create a custom "EmailAddress" attribute. Technically, I think you could pretty much just subclass EmailAddressAttribute without actually adding anything additional. The name of your custom attribute, though, would allow you to have a different editor template for that.

  2. Go ahead and use the EmailAddress.cshtml editor template, but branch inside. Assuming MyCustomType inherits from String:

    @model String
    @if (Model is MyCustomType)
    {
        ...
    }
    else
    {
        ...
    }
    
  3. Probably the easiest method, though, is to simply specify the template. It's not quite as automatic, but it doesn't require any additional work:

     @Html.EditorFor(m => m.EmailAddress, "MyCustomType")
    

    Which would then load MyCustomType.cshtml instead of the default EmailAddress.cshtml.

Upvotes: 2

Related Questions