In the last quick tip, I showed off how you can use the UIHint data annotation to specify a custom template for rendering of a particular field. An important part of that mechanism is the DisplayFor strongly-typed html helper that was introduced in ASP.NET MVC 2.

As mentioned before, we can also use the EditorFor html helper to format the rendering of a field in an Edit view. In this example, we will use the model we created in the last tip:

public class Author

{

    public string Name { get; set; }   

    public string Email { get; set; }

   

    [UIHint("Avatar")]

    public string Avatar { get; set; }

   

    public bool Active { get; set; }

}

 

public class Post

{

    public string Title { get; set; }

    public string Body { get; set; }

    public string Rating { get; set; }

    public DateTime Date { get; set; }

    public Author AuthorInfo { get; set; }

}


Let’s start off by modifying our Index action method in the Home Controller, in order to display an Edit view for the Post class:

public ActionResult Index()

{

    Post post = new Post();

    post.Title = "ASP.NET Quick Tip #1";

    post.Body = "Some awesome tip";

    post.Date = System.DateTime.Now;

    post.Rating = "Excellent";

   

    return View("Edit",post);

}


Next step, we ask Visual Studio to generate a strongly-typed view for the Post class, and choose the Edit template (according to this code, we need to name the view ‘Edit’):

add view dialog

Your view markup will be similar to this:

<h2>Edit</h2>

 

<%= Html.ValidationSummary("Edit was unsuccessful. Please correct the errors and try again."

 

<% using (Html.BeginForm()) {%>

 

    <fieldset>

        <legend>Fields</legend>

        <p>

            <label for="Title">Title:</label>

            <%= Html.TextBox("Title", Model.Title) %>

            <%= Html.ValidationMessage("Title", "*") %>

        </p>

        <p>

            <label for="Body">Body:</label>

            <%= Html.TextBox("Body", Model.Body) %>

            <%= Html.ValidationMessage("Body", "*") %>

        </p>

        <p>

            <label for="Rating">Rating:</label>

            <%= Html.TextBox("Rating", Model.Rating) %>

            <%= Html.ValidationMessage("Rating", "*") %>

        </p>

        <p>

            <label for="Date">Date:</label>

            <%= Html.TextBox("Date", String.Format("{0:g}", Model.Date)) %>

            <%= Html.ValidationMessage("Date", "*") %>

        </p>

        <p>

            <input type="submit" value="Save" />

        </p>

    </fieldset>

 

<% } %>


If we start our application now, we will see something like this:

default rendering

The default rendering for edit views is pretty much placing everything inside Textboxes. However, as you saw in the previous tip, we can override this by using templates. In this particular case, we’re interested in making it easier to edit the Rating field. Instead of asking the user to type the value, we want to display a drop down list of predefined values to choose from.

But first, we have to prepare our view so that it “listens” to the templates. Change the rendering of the Rating field to this:

<p>

    <label for="Rating">Rating:</label>

    <%= Html.EditorFor(model => model.Rating) %>

    <%= Html.ValidationMessage("Rating", "*") %>

</p>


Notice that, in this case, I’m using the EditorFor html helper to render the field. If you launch your application now, everything will be the same as the Rating field is simply a string, so it gets the default rendering.

Let’s create our template first: add a EditorTemplates folder under the Views for the Home Controller:

solution explorer

Inside the EditorTemplates folder, create a Partial view as we did in the last Quick Tip, and name it RatingsDropDown. Place the following code in the partial view:

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

<%= Html.DropDownList("",new SelectList(new [] {"Excellent", "Good", "Average", "Poor"},Model)) %>


This will generate a drop down list, using these hardcoded values, and also sets the current selected option to our Model value.

Using Data Annotations, we can now enrich our model by stating that the Rating field should be rendered (when possible) as a RatingsDropDown:

[UIHint("RatingsDropDown")]

public string Rating { get; set; }


If we now launch our application, we will now be presented with this:

Template rendering for Ratings

So, the EditorFor html helper realized there was a template called RatingsDropDown and followed our data annotation for this field, allowing us to create a better experience for our users. And, if we need to display this field in another view (also in edit mode) we will get the same experience automatically. Pretty cool stuff!

Every time I show off this demo I get a question: how can we avoid hardcoding the dropdown list values in the template? Well, like everything else in ASP.NET MVC, if you want to display information, you have to find a way to pass it on to your view.

Let me change the Index method to add that information to the view:

 public enum Ratings { Excellent, Good, Average, Poor, Awful };

 

public ActionResult Index()

{

    Post post = new Post();

    post.Title = "ASP.NET Quick Tip #1";

    post.Body = "Some awesome tip";

    post.Date = System.DateTime.Now;

    post.Rating = "Excellent";

 

    ViewData["Ratings"] = Enum.GetNames(typeof(Ratings));

 

    return View("Edit",post);

}


In this case, we are using an enum type to specify the values we want, which is a very common approach to make coding easier. We are passing all the values defined in the enum to our view using the ViewData dictionary (notice I added a new value).

Last step is changing the Partial view to read this information:

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

<%= Html.DropDownList("",new SelectList((string[]) ViewData["Ratings"],Model)) %>

 

Now, your output will be this:

template rendering with enumerable

You could use the exact same approach, only instead of using an enum, you could get the values from a database and pass it down to the view the same way.

The point is: the partial view will render as a part of your view. If the information is accessible then it can be used in your templates. It is irrelevant where it came from.

Hope you find this tip useful. I will talk more about Data Annotations in a later tip, where we will use it to add some custom validation to our model.

Until then, have fun!