Just a quick post to hopefully save others some time. ASP.NET MVC 2.0 has built-in support for client-side validation, but it doesn’t work with the expression-based BeginForm HtmlHelper methods that are available in the ASP.NET MVC Futures assembly. I also don’t like that I have to call a separate helper method to set my form up for validation. To address these two limitations, I wrote my own extension method:
public static class ValidationHelper
{
private const string LAST_FORM_ID_KEY = "_lastFormId";
public static MvcForm BeginValidatedForm<TController>(this HtmlHelper helper, Expression<Action<TController>> action)
where TController : Controller
{
helper.EnableClientValidation();
var id = GetNextFormId(helper);
TagBuilder builder = new TagBuilder("form");
string str = helper.BuildUrlFromExpression(action);
builder.MergeAttribute("action", str);
builder.MergeAttribute("method", "POST");
builder.GenerateId(id);
helper.ViewContext.HttpContext.Response.Write(builder.ToString(TagRenderMode.StartTag));
var form = new MvcForm(helper.ViewContext);
helper.ViewContext.FormContext.FormId = id;
return form;
}
private static string GetNextFormId(HtmlHelper helper)
{
int count = (int) (helper.ViewContext.HttpContext.Items[LAST_FORM_ID_KEY] ?? 0);
count++;
helper.ViewContext.HttpContext.Items[LAST_FORM_ID_KEY] = count;
return string.Format("form{0}", count);
}
}
Now you can simply do like this:
<h1>Sign-up</h1>
<p>Signing up is easy <em>and</em> free!</p>
<% using (Html.BeginValidatedForm<SignupController>(c => c.Create(null)))
{ %>
<fieldset>
<div>
<p>1) Choose a username:</p>
<%=Html.EditorFor(m => m.Username) %><%=Html.ValidationMessageFor(c => c.Username) %>
</div>
<div>
<p>2) What's your E-mail address? <span class="note">(<a href="#">Why do we need this?</a>)</span></p>
<%=Html.EditorFor(m => m.Email)%><%=Html.ValidationMessageFor(c => c.Email) %>
</div>
<%=Html.SubmitButton("submit", "Start Raging Now!") %>
</fieldset>
<%} %>
and get client-side validation (assuming you’ve set everything else up correctly).
Tags: