How to use the Html.EditorFor method

This post will cover the following points (aprox. reading time 15mins):

What is the Html.EditorFor method?

Microsoft defines the Html.EditorFor method as follows (EditorFor on MSDN):

The EditorFor method is used to generate MVCHtmlString mark-up depending on the data type of the expression passed into it.

Simply put, the Html.EditorFor method allows the developer to retain control over the display of form elements by data type (ie. string, boolean, int…etc) or model attribute at a global level rather than at an individual view level. This allows for cleaner ASP markup and easily scalable form controls.

Simple EditorFor example

The following example is a simple implementation of the Html.EditorFormethod. For the following Model class:

public class ViewModel  
{
    public string MyString { get; set; }
    public decimal MyDecimal { get; set; }
    public bool MyBool { get; set; }
    public DateTime MyDateTime { get; set; }
}

Each individual output element could be rendered using the following syntax:

<%: Html.TextBoxFor(o => o.MyString) %>  
<%: Html.TextBoxFor(o => o.MyDecimal) %>  
<%: Html.CheckBoxFor(o => o.MyBool) %>  
<%: Html.TextBoxFor(o => o.MyDateTime) %>  

Alternatively you could implement the exact same front-end functionality using the Html.EditorFor method, as follows:

<%: Html.EditorFor(o => o.MyString) %>  
<%: Html.EditorFor(o => o.MyDecimal) %>  
<%: Html.EditorFor(o => o.MyBool) %>  
<%: Html.EditorFor(o => o.MyDateTime) %>  

This method is a great example of how Html.EditorFor will modify the output depending on the datatype of the underlying object property (ie. Html.EditorFor(o => o.MyBool)). The resulting output for either method will look something similar to the following image:

Editor.For example output

Extending EditorFor with templates based on Data Type (ie. Decimal)

The Html.EditorFor method can be extended with the use of templates for specific data types at a global level. As an example, I may wish to display all decimal values with 3 digits after the decimal point and comma thousands separator (ie. 1,020.300) instead of the default (ie. 1020.30). I can achieve this by defining a decimal editor template which will reside in ./Views/Shared/EditorTemplates/ folder of our MVC application project. Create a new file Decimal.ascx with the following content, note that the filename maps to the data type:

<%@ Control  
    Language="C#" 
    Inherits="System.Web.Mvc.ViewUserControl<decimal?>" 
%>
<%: Html.TextBox(  
        string.Empty,
        Model.HasValue ? Model.Value.ToString("#,0.000#") : string.Empty
    )
%>

The Inherits="System.Web.Mvc.ViewUserControl<decimal?>" defines the data type that the template expects to receive, which in this scenario is a nullable decimal. The following lines check that the Model has a value and returns the value formatted as specified earlier. If no value is provided then it will be displayed as an empty text box. The resulting output will look as follows:

Editor.For decimal template

Extending EditorFor with templates based on Model Attributes

The above example allows us to modify the editor output for all model elements of a specific data type, however what happens if we only want a sub-set of model elements to have a modified editor output? This can be done through the UIHint model attribute, which acts as a template override parameter for your model element. Update the ViewModel class we created earlier to look like the following:

[UIHint("DateTimePicker")]
public DateTime MyDateTime { get; set; }  

Please note that you will need include the System.ComponentModel.DataAnnotations library at the start of your file to use this annotation.

Then create a new Editor Template named DateTimePicker.ascx with the following content:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>  
<% var uid = Guid.NewGuid(); %>  
<%: Html.TextBox(  
        string.Empty,
        Model.HasValue ? Model.Value.ToString("MMM d, yyyy") : string.Empty,
        new { @id = uid }
    )
%>
<script type="text/javascript">  
    $("#<%: uid %>").datepicker({ dateFormat: 'M d, yy' });
</script>  

The above code works in a similar way as the Decimal.ascx we created earlier, but with a few additions. There is now a uid variable being generated, which is used for the id of the textbox, there is then javascript code which uses the uid to bind to the textbox and display the datepicker.

Editor.For datetime template