Localization with ASP.NET MVC ModelMetadata
- by kazimanzurrashid
When using the DisplayFor/EditorFor there has been built-in support in ASP.NET MVC to show localized validation messages, but no support to show the associate label in localized text, unless you are using the .NET 4.0 with Mvc Future. Lets a say you are creating a create form for Product where you have support both English and German like the following. English German I have recently added few helpers for localization in the MvcExtensions, lets see how we can use it to localize the form. As mentioned in the past that I am not a big fan when it comes to decorate class with attributes which is the recommended way in ASP.NET MVC. Instead, we will use the fluent configuration (Similar to FluentNHibernate or EF CodeFirst) of MvcExtensions to configure our View Models. For example for the above we will using: public class ProductEditModelConfiguration : ModelMetadataConfiguration<ProductEditModel>
{
public ProductEditModelConfiguration()
{
Configure(model => model.Id).Hide();
Configure(model => model.Name).DisplayName(() => LocalizedTexts.Name)
.Required(() => LocalizedTexts.NameCannotBeBlank)
.MaximumLength(64, () => LocalizedTexts.NameCannotBeMoreThanSixtyFourCharacters);
Configure(model => model.Category).DisplayName(() => LocalizedTexts.Category)
.Required(() => LocalizedTexts.CategoryMustBeSelected)
.AsDropDownList("categories", () => LocalizedTexts.SelectCategory);
Configure(model => model.Supplier).DisplayName(() => LocalizedTexts.Supplier)
.Required(() => LocalizedTexts.SupplierMustBeSelected)
.AsListBox("suppliers");
Configure(model => model.Price).DisplayName(() => LocalizedTexts.Price)
.FormatAsCurrency()
.Required(() => LocalizedTexts.PriceCannotBeBlank)
.Range(10.00m, 1000.00m, () => LocalizedTexts.PriceMustBeBetweenTenToThousand);
}
}
As you can we are using Func<string> to set the localized text, this is just an overload with the regular string method. There are few more methods in the ModelMetadata which accepts this Func<string> where localization can applied like Description, Watermark, ShortDisplayName etc. The LocalizedTexts is just a regular resource, we have both English and German:
Now lets see the view markup:
<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Demo.Web.ProductEditModel>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
<%= LocalizedTexts.Create %>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2><%= LocalizedTexts.Create %></h2>
<%= Html.ValidationSummary(false, LocalizedTexts.CreateValidationSummary)%>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm()) {%>
<fieldset>
<%= Html.EditorForModel() %>
<p>
<input type="submit" value="<%= LocalizedTexts.Create %>" />
</p>
</fieldset>
<% } %>
<div>
<%= Html.ActionLink(LocalizedTexts.BackToList, "Index")%>
</div>
</asp:Content>
As we can see that we are using the same LocalizedTexts for the other parts of the view which is not included in the ModelMetadata like the Page title, button text etc. We are also using EditorForModel instead of EditorFor for individual field and both are supported.
One of the added benefit of the fluent syntax based configuration is that we will get full compile type checking for our resource as we are not depending upon the string based resource name like the ASP.NET MVC.
You will find the complete localized CRUD example in the MvcExtensions sample folder.
That’s it for today.