Steve Michelotti

A .NET Developer's Toolbox

  Home  |   Contact  |   Syndication    |   Login
  199 Posts | 0 Stories | 1106 Comments | 51 Trackbacks

News

View Steve Michelotti's profile on LinkedIn

profile for Steve Michelotti at Stack Overflow, Q&A for professional and enthusiast programmers




Google My Blog

What I'm Reading:

Shelfari: Book reviews on your book blog

Tag Cloud


Archives

Post Categories

Code

Publications

One of the cool new features of MVC 2 is the ability to automatically pick an editor template based on the meta data of each property. This meta data can be as simple as the data type of the property itself.  Take an example where we have a Contact object that has a DateTime? property for DateOfBirth.

   1:  public partial class Contact
   2:  {
   3:      [DisplayName("First Name")]
   4:      public string FirstName { get; set; }
   5:   
   6:      [DisplayName("Last Name")]
   7:      public string LastName { get; set; }
   8:   
   9:      [DisplayName("Date of Birth")]
  10:      public DateTime? DateOfBirth { get; set; }
  11:  }

We can then display the property using markup like this:

   1:  <%=Html.LabelFor(m => m.Contact.DateOfBirth) %>
   2:  <%=Html.EditorFor(m => m.Contact.DateOfBirth)%>

This results in a view that looks something like this:

This is ugly.  It’s not user friendly for the user to have to type this and in many cases (like date of birth) we don’t care about the time portion – only the date.  With MVC 2 we can now, by convention, change the display for all of our DateTime data types just by adding a partial view called “DateTime.ascx” to a well-known folder called “EditorTemplates”:

Notice the EditorTemplates folder is in the Shared folder of views but you could scope this to a specific view folder as well. Now I can add my own partial view for DateTime. In fact, this will work for a nullable DateTime as well:

   1:  <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
   2:  <%=Html.TextBox("", (Model.HasValue ? Model.Value.ToShortDateString() : string.Empty), new { @class = "datePicker" }) %>

The aspect that I *really* like about this functionality is the rendered HTML:

   1:  <input class="datePicker" id="Contact_DateOfBirth" name="Contact.DateOfBirth" type="text" value="4/1/1975" />

Notice how that “id” and “name” attributes were still correctly set despite that fact this this was in a partial view where we were just referring to the “Value” property of a nullable DateTime. This would have been tricky to do just using partial views with MVC 1 but here the framework is taking care of this for me. This means that the model binders will “just work” when the form is posted.

Another thing to note is that I’ve added a class attribute of “datePicker” because I’m using the jQuery datepicker to give a nice little calendar UI for the end user.

   1:  <script src="../../Scripts/jquery-datepicker.js" type="text/javascript"></script>
   2:  <script type="text/javascript">
   3:      $(function() {
   4:          $(".datePicker").datepicker({ showOn: 'both', buttonImage: "/images/calendar.gif" });
   5:      });
   6:  </script>

This gives a much nicer user experience:

MVC 2 editors result in a much nicer development experience. My call to the EditorFor() HTML helper method remains unchanged. But rather than just rendering a simple HTML text box with no formatting of the DateTime, it will now automatically pick up my DateTime editor template for ALL my DateTime properties and show a nice UI with better formatting.  Also note that if you have a date time that is an exception to this and you want to display a different editor, you can still use the [UIHint] attribute to control the meta data and therefore select a different editor for a DateTime.

posted on Friday, February 5, 2010 4:26 AM

Feedback

# MVC 2 Editor Template with String 2/6/2010 1:29 PM Chris
I tried create custom editor template for all String fields.
I prepare String.ascx file:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.String>" %>
<%= ViewData.ModelMetadata.IsRequired? "*" : ""%>
<%= Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line" }) %>

I put this file into Views\Shared\EditorTemplates\String.ascx

...and I see any changes.

# re: MVC 2 Editor Template with DateTime 2/6/2010 8:19 PM Steve
@Chris - The partial view itself (String.ascx) should be displayed (you can put some text in there to verify). I think what you're saying is that you're not seeing the "*" appear for required fields. The IsRequired property is true for non-nullable values types, false for all others - which means for a string it's going to be false. That is the default behavior out of the box - the default behavior doesn't look at the data annotations you've applied. See this post for more info: http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-2-modelmetadata.html

# Problem with custom editor tamplate 2/7/2010 2:56 AM Chris
Thanks for replay.
I use new MVC 2 RC 2. I tried put additional text like:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.String>" %>
XXXX
<%= Html.TextBox("", ViewData.TemplateInfo.FormattedModelValue, new { @class = "text-box single-line" }) %>
...and I still see any changes. It seems mvc dosen't my template.

# re: Problem with custom editor tamplate 2/7/2010 5:33 AM Chris
I found where is the problem.
I use
<%= Html.TextBoxFor(model => model.Nazwa) %>
instead
<%= Html.EditorFor(Product=> item.SellStartDate) %> </td>

# re: Problem with custom editor tamplate 2/7/2010 5:36 AM Chris
I found where is the problem.
I use
<%= Html.TextBoxFor(model => model.Nazwa) %>
instead
<%= Html.EditorFor(model => model.Nazwa) %> </td>

# re: MVC 2 Editor Template with DateTime 2/23/2010 9:06 AM Stefan
Very useful! thanks!

I am trying to do the same for a Boolean. but not in the Edit view, but the index view listing all the items.
I have a few columns which represent Booleans.

my code:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.Boolean?>" %>
<%=Html.Encode(Model.HasValue ? ((bool)Model.Value)?"Yes":"No" : string.Empty) %>

so this code would translate True or False to Yes or No

in the index view ofcourse you have the foreach of the items and : <%= Html.Encode(item.Proj_ModulesIngevoerd) %>

i tried editfor but i don't get it to work. because 'item.Proj_ModulesIngevoerd' does not seem to be a valid input for that method.

# re: MVC 2 Editor Template with DateTime 2/23/2010 10:27 AM Steve
@Stefan - in your Index view, use the Html.DisplayFor() method. Then make sure you're custom template is in the well-known folder called "DisplayTemplates".

# re: MVC 2 Editor Template with DateTime 2/24/2010 8:39 AM Stefan
thanks steve for answering me.

however i still have 1 problem.
i don't know how to make this work in the end.

i have the List view (index) so, there is the generated Foreach:

<% foreach (var item in Model) { %>
<td>
<%= Html.Encode(item.Proj_Afgelast)%>
</td>
<% } %>

how do i get this to use the displaytemplate? I know i should use DisplayFor but i dont know what parameters it needs... i called the file Bool.ascx.

# re: MVC 2 Editor Template with DateTime 2/24/2010 9:18 AM Steve
Hmm, this is a little more interesting problem than I thought. :) Normally, you could just change your code to this:
<td>
<%:Html.DisplayFor(m => m.Proj_Afgelast) %>
<td>

but the problem with that is that in your example, you're trying to access it in a loop. The DisplayFor() and EditorFor() methods naturally refer to properties on a (non-collection) view model. But you've got a collection here that you're looping over.

Given this, I'm thinking your simplest solution might be to just create a normal HTML helper method that does the translation for you so that you can call it like this:
<% foreach (var item in Model) { %>
<td>
<%: Html.TranslateBool(item.Proj_Afgelast)%>
</td>
<% } %>

Also are you using ASP.NET 4? If so, you can just use <%: syntax and not worry about having to call Html.Encode().

# re: MVC 2 Editor Template with DateTime 2/24/2010 9:37 AM Steve
@Stefan - I would also look at this: http://leriksen71.wordpress.com/2009/09/20/asp-net-mvc-2-oft-item-for-html-displayfor/

# re: MVC 2 Editor Template with DateTime 2/24/2010 5:36 PM Stefan
i checked out your link and it looks that the best solution is an ordinary, very simple HTML helper :D making a wrapper class for this small thing looks rather overkill.

In the end i still have to change the auto generated code of MVC to DisplayFor(), so i might as well change it to my own call for the html helper. thanks for your help!!

in the end it does make me wonder, what's the use of DisplayFor if you can have ordinary HTML helpers just as easy?

# re: MVC 2 Editor Template with DateTime 2/24/2010 9:08 PM Steve
@Stefan - Based on your example, I can see why you would wonder that but if you look at the example above, it starts to make more sense. It's nice not to have to type in the appropriate HTML helper every single time and the metadata on the model will automatically pick it up. This gets even more useful when you're using DisplayForModel() and the entire screen becomes metadata driven. But yes, inside loops, it's not the most convenient.

# re: MVC 2 Editor Template with DateTime 2/25/2010 5:00 AM Stefan
thanks for all the help steve!

# re: MVC 2 Editor Template with DateTime 3/3/2010 9:15 AM Nick Masao
How do you set this up on the view?

# re: MVC 2 Editor Template with DateTime 3/3/2010 9:42 AM Steve
@Nick - all the code is contained in the blog post. For the view, you just need to make sure it contains the call to the jQuery datepicker(). And make sure you're using the EditorFor() HTML helper on your DateTime property.

# re: MVC 2 Editor Template with DateTime 3/28/2010 8:53 PM Steve
@Mike - the jQuery datepicker is completely customizable including localization. See this link here: http://jqueryui.com/demos/datepicker/#localization

# re: MVC 2 Editor Template with DateTime 4/26/2010 11:41 AM DalSoft
I've extended the template and jQuery UI concept in my blog post http://bit.ly/a48frG, I show how you can make reusable templates.

# re: MVC 2 Editor Template with DateTime 4/28/2010 7:11 PM Abx78
Great article, I found it very useful.

I have a problem with the htmlAttributes parameter: I tried to set up the class as you show, but in my output html I get the following: class="text-box single-line"

Suggestions? Thanks again

# re: MVC 2 Editor Template with DateTime 4/28/2010 7:33 PM Abx78
It seems it doesn't care of my ascx

It gives the same output, even when ascx is empty!

# re: MVC 2 Editor Template with DateTime 4/29/2010 8:23 AM Steve
@Abx78 - Did you verify that you put your partial view in the Views\Shared\EditorTemplates folder structure? Verify you're using the Html.EditorFor() method? Paste the code if you're doing something different.

# re: MVC 2 Editor Template with DateTime 4/29/2010 4:07 PM Abx78
You got it! :D I called the folder EditorTemplate instead of EditorTemplates!!!

Thank you!

# re: MVC 2 Editor Template with DateTime 5/30/2010 2:30 AM Anoosh Rahman
Thanks .. It is perfect

# re: MVC 2 Editor Template with DateTime 6/1/2010 9:21 PM Sanjay
Editor templates are great and they get used all over the place.

Say we used this DateTime editor in a buch of different places, but we wanted to change them all to accept dates in a friendlier format (say like '5th December 1992').

There seems to be no way to add a translation layer in between the edit template and the value presented to the action. We either need to update a hidden field on the client with the DateTime in a machine-friendly format, or change all of the actions that receive DateTimes from this editor and lose the ability to stuff these parameters into model objects.

# re: MVC 2 Editor Template with DateTime 6/1/2010 9:32 PM Steve
@Sanjay - I'm not sure I'm following you. You're saying you want to use an editor templates (e.g., the DataTime.ascx editor template) but you want the ability to control the format on *some* of the data time's? If so, have you looked at the [DisplayFormat] attribute (http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.displayformatattribute.aspx) that you can selectively apply to the view model property?

# re: MVC 2 Editor Template with DateTime 6/14/2010 2:59 AM gregor suttie
can you post the code for this please?

# re: MVC 2 Editor Template with DateTime 6/17/2010 8:46 AM Steve
@gregor - The complete code for this is on the blog. The editor template is fully contained in the snippet of code above and the jQuery with $(".datePicker").datepicker is all you need to do to invoke it once the jQuery files have been referenced.

# re: MVC 2 Editor Template with DateTime 6/24/2010 7:07 AM Stuart Dawson
Great post, very helpful - thanks!

# re: MVC 2 Editor Template with DateTime 7/30/2010 12:20 PM diuk
I created exactly the same partial view as in the post, but it works only when I specify name of partial view in Html.EditorFor(). Any hint why it doesn't work without the name ?

<%= Html.EditorFor(x => x.Date) %> - DOESN'T WORK
<%= Html.EditorFor(x => x.Date, "DateTime") %> - WORKS

# re: MVC 2 Editor Template with DateTime 8/6/2010 5:22 PM Steve
@diuk - A couple of things to check for. First, are you sure you put the DateTime.ascx file in a folder called "EditorTemplates"? (make sure there is no [space] between "Editor" and "Templates"). Is the Date property that you're using in fact a DateTime data type?

# re: MVC 2 Editor Template with DateTime 8/11/2010 7:44 AM Steve
@Willy - You can get it from the jQuery UI page: http://jqueryui.com/demos/datepicker/. You can name the *.js file anything you want.

# re: MVC 2 Editor Template with DateTime 8/11/2010 7:50 AM Willy
Thank yo uvery much form the extrem fast reply!

Works fine now!

Very very nice tutotrial - also for me as an absolute MVC 2 - newbie!

Go on and make more tutorials :-)

# re: MVC 2 Editor Template with DateTime 9/7/2010 12:51 PM Peter
"it will now automatically pick up my DateTime editor template for ALL my DateTime properties"
So far ok.
"and show a nice UI with better formatting"
This is less ok. Where did you put the datepickerizer js code? Is it in the editor template ascx? And if I have 3 datetimes on one page then it will run three times?

# re: MVC 2 Editor Template with DateTime 9/7/2010 12:57 PM Steve
@Peter - the datepicker code should be included just 1 time on the page. It will look for any elements that have class="datePicker" and apply the date picker plug in. You could put this in a master page, for example, if you wanted it to be globally available to any page of your application.

# re: MVC 2 Editor Template with DateTime 9/8/2010 1:04 PM Peter
I know Steve. My issue is that if the js code is put on the page (aspx) then the template is not self-containing. It would be nice if the page wouldn't know about the ascx's js requirements. And I have no idea how to do it :(.

# re: MVC 2 Editor Template with DateTime 9/8/2010 5:10 PM Steve
@Peter - Ah, misunderstood your question. Yes, there is a way to do that too. Just use the GetFullHtmlFieldId() method and inline the javascript as shown below:

<%:Html.TextBox("", (Model.HasValue ? Model.Value.ToShortDateString() : string.Empty)) %>
<script type="text/javascript">
$(function () {
$("#<%: this.ViewData.TemplateInfo.GetFullHtmlFieldId("") %>").datepicker({ showOn: 'both', buttonImage: "/images/calendar.gif" });
});
</script>

# re: MVC 2 Editor Template with DateTime 9/9/2010 4:54 PM Richard
Works great. Thank-you!

# re: MVC 2 Editor Template with DateTime 10/10/2010 9:46 AM Bhoomi
Thank you so much..i was searching for this solution since many days now..

# re: MVC 2 Editor Template with DateTime 11/3/2010 8:26 PM Eric H
Steve,

Where did you put the following code, in your site.master?

<script src="../../Scripts/jquery-datepicker.js" type="text/javascript"></script>
2: <script type="text/javascript">
3: $(function() {
4: $(".datePicker").datepicker({ showOn: 'both', buttonImage: "/images/calendar.gif" });
5: });
6: </script>

# re: MVC 2 Editor Template with DateTime 11/3/2010 9:11 PM Steve
@Eric - You can put it in the MasterPage. Or, you can follow the example I showed in the comments above on 9/8/2010 5:10PM.

# re: MVC 2 Editor Template with DateTime 12/27/2010 4:14 PM programmer
hey,
can you give the source code?
i'm having problems following this tutorial without seeing the code, i don't know where to put some of the information, neither which of the jquery's to download, or where to put the files that comes with it

# re: MVC 2 Editor Template with DateTime 1/1/2011 5:24 PM Steve
@programmer - The complete source code is essentially all in this post. But you can download a working sample which contains everything here: https://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=michelotti&ReleaseId=4333

# re: MVC 2 Editor Template with DateTime 1/7/2011 12:28 PM Soonerjel
We are using the Razor view engine. What differences would we make to leverage that (vs. the classic view engine)?

# re: MVC 2 Editor Template with DateTime 1/15/2011 9:38 AM Steve
@Soonerjel - Virtually nothing will be different with Razor. The only difference will be that you'll have a more simplified syntax with Razor for the DateTime.ascx (which in razor will be DateTime.cshtml). But the editor templates infrastructure will work the same.

# re: MVC 2 Editor Template with DateTime 1/27/2011 10:02 PM sona
I want template for image field in database table. I want Image upload control in template. Any inputs will be highly appreciated.

# re: MVC 2 Editor Template with DateTime 4/26/2011 5:21 AM Arnab C
I have a simple form, one of the fields is date, as you have shown I have got the calendar like functionality and it looks nice.
Now, the ascx has:
<%=Html.TextBox("", (Model.HasValue ? Model.Value.ToShortDateString() : string.Empty), new { @class = "datePicker" }) %>
So the text box shows a string.
Now when I'm submitting the form, it is showing error stating "The value '04/13/2011' is not valid for End Date".
Am I doing something wrong?

# re: MVC 2 Editor Template with DateTime 4/26/2011 9:23 AM Steve
@Arnab - That is strange. What is the name and data type of the property you are trying to map to? Are you sure the calling syntax is correct and that you've wired up the attributes on your view model correctly?

# re: MVC 2 Editor Template with DateTime 5/2/2011 7:43 AM Simonkue
I am using the datepicker OK in MVC3 project for the index/list page for a table. However, on the Edit page, it won't show the graphic/button and I cannot use the function.
Note that the Edit page is OK for other functionality.
I've created the pages as C# ASPX pages via the scaffolding templates. It's as if the icon etc cannot be found when the Edit and partial view is displayed.
I've tried referencing the jquery ui functions in both the initial edit and partial view and neither help. Does anyone have ideas please!

# re: MVC 2 Editor Template with DateTime 5/2/2011 8:14 AM Steve
@Simonkue - Are you getting the datepicker to show up but just not the icon? Or is the datepicker not showing up at all? Is there any difference in the way you're referencing the <script> tag between the view that works and the view that doesn't work? Is there any difference in the way the EditorFor() method is being called?

# re: MVC 2 Editor Template with DateTime 5/2/2011 1:01 PM Simonkue
Thanks you for the response. I am placing the control on the form via:
<p><%= Html.DatePicker("Date", "/Content/images/calendar.gif", this.ViewData["TheDate"])%></p>
On the Index, both the text box and the icon show and function is correct. On the Edit form only the input box appears. I have placed this code in both the Edit form and the partial form it calls. I have tried the placement in various places and it always misses the icon. I have just tried with another table in the same app and the symptoms are the same. Also, I am using the jquery datepicker from http://jqueryui.com/download and have referred to http://www.codesprouts.com/post/Creating-A-DatePicker-Extension-In-ASPNet-MVC.aspx for help implementing it. I am using MVC3 and VS2010 and Win7.

# re: MVC 2 Editor Template with DateTime 5/2/2011 5:51 PM Steve
@Simonkue - And you're using an absolute path in all cases? (i.e., /images/calendar.gif). Also, I see you're using some custom Html.DatePicker() method rather than the EditorFor() method I described in the post. Something might be going on there but hard to know without me being about to look at it.

If you want to put a zip file on dropbox I'm happy to have a look. Sounds like just something very minor out of place.

# re: MVC 2 Editor Template with DateTime 5/4/2011 4:36 AM Simonkue
Steve, Thanks for the response. I'm currently having SQL Server problems and will send relevant code when they're sorted!

# re: MVC 2 Editor Template with DateTime 5/9/2011 12:28 AM Steve Gentile
for those on mvc 3 wanting to do this for Razor:

http://stackoverflow.com/questions/4249955/mvc-3-editor-template-with-datetime

Thanks Steve- good post!

# re: MVC 2 Editor Template with DateTime 8/2/2011 1:33 PM shawn z
When setting up an MVC 3 application, the foreign keys that should allow drop down lists to select an item do not get rendered as drop downs, but as static inputs. This can be resolved by creating a custom display and view for that field.
We will need to start by creating a custom partial view that will live in “~/Views/Shared/DisplayTemplates/UserGuid.cshtml”, and “~/Views/Shared/EditTemplates/UserGuid.cshtml”. The code for one is located below:
@model Guid

@{
incMvcSite.Models.MvcSiteDB db = new incMvcSite.Models.MvcSiteDB();
incMvcSite.Models.SecUser usr = db.SecUsers.Single(u => u.Guid == Model);
}
@usr.Display

This is a display for template that will look up the item in the referenced table and display it. We also need an edit for template as follows:
@model Guid
@{
incMvcSite.Models.MvcSiteDB db = new incMvcSite.Models.MvcSiteDB();
SelectList items = new SelectList(db.SecUsers.OrderBy(i => i.Display).ToList(), "Guid", "Display", Model);
}
@Html.DropDownList("", items)

The edit for template is implemented as a drop down list. Originally, we has used static HTML code, but the problem will appear of implementing a “prefix”. Static HTML code does get handled by HTML helpers, so it’s recommended that you use the HTML.DropDownList().
To force the MVC framework to use the new Display and Edit for templates, we need to annote our model item an add the following line:
[UIHint("UserGuid")]

This will cause MVC to use the Display and Edit templates named “UserGuid”, which are just partial views.


# re: MVC 2 Editor Template with DateTime 8/2/2011 2:11 PM Steve
@shawn - I would strongly recommend *against* writing the code the way you've shown it above. In that instance, you are making a call to your database from your view! This violates the separation of concerns established by MVC.

# re: MVC 2 Editor Template with DateTime 1/6/2012 2:33 AM Varma
Use this,

http://stackoverflow.com/a/4249988/505474

This is working perfectly....

# re: MVC 2 Editor Template with DateTime 1/23/2012 4:50 PM ricardo
Implemented the editor template but im getting ASPPARSE: Could not load type 'System.Web.Mvc.ViewUserControl<DateTime?>' on my build server.

# re: MVC 2 Editor Template with DateTime 9/6/2012 2:42 AM wecode
Thanks for the post this fix works for MVC3. Just now i have tested it works fine.
You Rock!

# re: MVC 2 Editor Template with DateTime 1/4/2013 10:09 AM g
Thanx for the post......
I m fresher to MVC ......
i tried this thing but it doesnt work for me..........
please send me the application code of this demo......
please please frnds help.....

thanks in advance....

mail_id = grv.jobs@gmail.com

Post A Comment
Title:
Name:
Email:
Comment:
Verification: