Logo

Maarten Balliauw {blog}

ASP.NET, ASP.NET MVC, Azure, PHP, OpenXML, VSTS, ...

About the author

Maarten Balliauw is currently employed as .NET Technical Consultant at RealDolmen. His interests are mainly web applications developed in ASP.NET (C#) or PHP and the Windows Azure cloud platform.
More about me More about me
Send mail E-mail me


ASP.NET MVC Quickly Subscribe to my RSS feed Follow me on Twitter! View Maarten Balliauw's profile on LinkedIn
View Maarten Balliauw's MVP profile

Search

Latest Twitter

    Follow me on Twitter...

    My projects

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

    © Copyright Maarten Balliauw 2010

    Form validation with ASP.NET MVC preview 5

    In earlier ASP.NET MVC previews, form validation was something that should be implemented "by hand". Since the new ASP.NET MVC preview 5, form validation has become more handy. Let me show you how you can add validation in such a ridiculously easy manner.

    Here's an example controller:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Mvc.Ajax;

    namespace ValidationExample.Controllers
    {
        [HandleError]
        public class HomeController : Controller
        {
            // ... some other action methods ...

            [AcceptVerbs("GET")]
            public ActionResult Contact()
            {
                return View();
            }

            [AcceptVerbs("POST")]
            public ActionResult Contact(string name, string email, string message)
            {
                // Add data to view
                ViewData["name"] = name;
                ViewData["email"] = email;
                ViewData["message"] = message;

                // Validation
                if (string.IsNullOrEmpty(name))
                    ViewData.ModelState.AddModelError("name", name, "Please enter your name!");
                if (string.IsNullOrEmpty(email))
                    ViewData.ModelState.AddModelError("email", email, "Please enter your e-mail!");
                if (!string.IsNullOrEmpty(email) && !email.Contains("@"))
                    ViewData.ModelState.AddModelError("email", email, "Please enter a valid e-mail!");
                if (string.IsNullOrEmpty(message))
                    ViewData.ModelState.AddModelError("message", message, "Please enter a message!");

                // Send e-mail?
                if (ViewData.ModelState.IsValid)
                {
                    // send email...
                    return RedirectToAction("Index");
                }
                else
                {
                    return View();
                }
            }
        }
    }

    You may notice an starnge thing here... Why is Contact defined twice, and why is it with this strange AcceptVerbs attribute? The AcceptVerbs attribute determines which action method to call, based on the HTTP method of the request. In this case, when I do not post a form, the first action method will be called, simply rendering a view. When posting a form, the second action method will be called, allowing me to do some validations.

    Speaking of validations... Notice that I can set errors on the ViewData.ModelState collection, and use this ViewData.ModelState.IsValid property to check if everything is OK.

    UPDATE: You can also use the controller's UpdateModel method (which updates a model object with form values) for setting data on the model. If the model throws an exception, this will be added to the ViewData.ModelState dictionary too.

    One thing left with validation: the view itself!


    <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" AutoEventWireup="true" CodeBehind="Contact.aspx.cs" Inherits="ValidationExample.Views.Home.Contact" %>


    <asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
        <h2>Contact Us</h2>
        <p><%=Html.ValidationSummary()%></p>
        <% using (Html.Form<ValidationExample.Controllers.HomeController>( c => c.Contact("", "", ""), FormMethod.Post)) { %>
            <table border="0" cellpadding="2" cellspacing="0">
                <tr>
                    <td>Name:</td>
                    <td>
                        <%=Html.TextBox("name", ViewData["name"] ?? "")%>
                        <%=Html.ValidationMessage("name")%>
                    </td>
                </tr>
                <tr>
                    <td>Email:</td>
                    <td>
                        <%=Html.TextBox("email", ViewData["email"] ?? "")%>
                        <%=Html.ValidationMessage("email")%>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">Message:</td>
                </tr>
                <tr>
                    <td colspan="2">
                        <%=Html.TextArea("message", ViewData["message"] ?? "")%>
                    </td>
                </tr>
                <tr>
                    <td colspan="2">
                        <%=Html.ValidationMessage("message")%>
                    </td>
                </tr>
                <tr>
                    <td>&nbsp;</td>
                    <td>
                        <%=Html.SubmitButton("send", "Send e-mail")%>
                    </td>
                </tr>
            </table>
        <% } %>
    </asp:Content>

    Notice that there are 2 new HtmlHelper extension methods: ValidationMessage and ValidationSummary. The first one displays a validation message for one key in the ViewData.ModelState collection, while the latter displays a validation summary of all messages. Here's what my invalid post looks like:

    Validation example

    kick it on DotNetKicks.com


    Categories: ASP.NET | C# | General | MVC

    Comments

    DotNetKicks.com | Reply

    Friday, August 29, 2008 3:40 PM

    trackback

    Trackback from DotNetKicks.com

    Form validation with ASP.NET MVC preview 5

    Troy Goode United States | Reply

    Friday, August 29, 2008 4:41 PM

    Troy Goode

    Looks like an improvement, but it really is only half a solution without any way to propagate the rules down for client-side validation. Hopefully they'll do something with that in Preview 6?

    maartenba Belgium | Reply

    Friday, August 29, 2008 4:45 PM

    maartenba

    Agree with that, but it is a step forward. Bit strange they did not think of client-side validation immediately too?

    Simone Italy | Reply

    Friday, August 29, 2008 4:46 PM

    Simone

    That's a good thing... I don't think these things have been added to the readme file of P5

    maartenba Belgium | Reply

    Friday, August 29, 2008 4:54 PM

    maartenba

    There's even more undocumented goodies in there Smile Will post one more next monday.

    Jesse United States | Reply

    Friday, August 29, 2008 6:24 PM

    Jesse

    I'm not sure about the pessimists above. I would just use Ajax to post to the action you nicely summarized above and I would have client side validation.
    This is very cool.

    Sean United States | Reply

    Friday, August 29, 2008 7:31 PM

    Sean

    Ok, stupid question. What are those HTML helper methods for? Do they render as client-side JavaScript validation?

    blogger.forgottenskies.com | Reply

    Saturday, August 30, 2008 1:31 PM

    pingback

    Pingback from blogger.forgottenskies.com

    ASP.NET MVC Preview 5 Released at { null != Steve }

    Johan Danforth's Blog | Reply

    Saturday, August 30, 2008 4:19 PM

    trackback

    Trackback from Johan Danforth's Blog

    ASP.NET MVC Preview 5 Released

    Johan's Blog | Reply

    Saturday, August 30, 2008 4:19 PM

    trackback

    Trackback from Johan's Blog

    ASP.NET MVC Preview 5 Released

    Brad Wilson United States | Reply

    Sunday, August 31, 2008 6:43 AM

    Brad Wilson

    This:

    <% using (Html.Form<ValidationExample.Controllers.HomeController>( c => c.Contact("", "", ""), FormMethod.Post)) { %>

    could just be:

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

    maartenba Belgium | Reply

    Monday, September 01, 2008 7:56 AM

    maartenba

    @Sean: these helper methods simply render some HTML tags. For example, HtmlHelper.Form() will render a <form> tag, HtmlHelper.ValidationSummary() will render an <ul> with validation messages.

    @Brad: True! Thanks for noticing. Will fix in this post.

    Mike | Reply

    Tuesday, September 02, 2008 9:10 PM

    Mike

    Client side validation is possible, you have to look for a validation framework that uses attributes. These attributes can be inspected, and correct javascript can be written to the page based on them (such as required, compare, regex).

    But you have to get the name of the form element coupled with the property of your model class somehow. Hopefully the modelbinder is capable of that.

    dotnetwitter.wordpress.com | Reply

    Wednesday, September 03, 2008 6:39 PM

    pingback

    Pingback from dotnetwitter.wordpress.com

    links for 2008-09-03 « Praveen’s Blog

    nishzone Australia | Reply

    Sunday, December 07, 2008 3:18 PM

    nishzone

    I'm created an mvc project with the first beta release and automatically the AccountController had generated ModelState.AddModelError like your example. When I updated to preview 5 from codeplex, I could no longer access ModelState.AddModelError from System.web.mvc.dll....How come you don't seem to be having this issue? Am I missing something?

    maartenba Belgium | Reply

    Sunday, December 07, 2008 10:35 PM

    maartenba

    I would say: stick with beta 1 as it is a newer version than preview 5.

    answerspluto.com | Reply

    Tuesday, July 14, 2009 4:12 AM

    pingback

    Pingback from answerspluto.com

    list of urls - 5 « Answers Pluto

    Naresh Yadav United States | Reply

    Thursday, October 15, 2009 12:29 PM

    Naresh Yadav

    Shouldn't email be verified as name@domainname.tld . In your example even N@resh will be a valid email.

    Maarten Belgium | Reply

    Thursday, October 15, 2009 12:37 PM

    Maarten

    True, this was just an example of the concept.

    Add comment




      Country flag

    biuquote
    • Comment
    • Preview
    Loading