- | rssFeed | My book on MSBuild and Team Build | Archives and Categories Monday, 18 May 2009

ASP.NET MVC: Validation Error ‘A value is required.’

If you are using the ASP.NET MVC DefaultModelBinder to manage the creating complex types from your views’ form data, as well as the validation summary helper provided with ASP.NET MVC then you may have run into the situation I did. I created a simple form, in a dummy app,  to create a new contact. The page is named AddContactClassic.aspx, the contents are shown below.

<% @ Page Title ="" Language ="C#" MasterPageFile ="~/Views/Shared/Site.Master" Inherits ="System.Web.Mvc.ViewPage" %>

 

<% @ Import Namespace ="Sedodream.Web.Common.Contact" %>

 

< asp : Content ID ="Content1" ContentPlaceHolderID ="TitleContent" runat ="server">

      Add Contact Classic

</ asp : Content >

 

< asp : Content ID ="Content2" ContentPlaceHolderID ="MainContent" runat ="server">

    < h2 > Add Contact Classic </ h2 >

   

    <% = Html.ValidationSummary( "Errors exist" ) %>

   

    < ol >< li >< span class ="success-message"> <% = ViewData[ "SuccessMessage" ]%> </ span ></ li ></ ol >

    <% using (Html.BeginForm())

       { %>

    < fieldset >

        < legend > Account Information </ legend >

        < ol >

            < li >

                < label for ="FirstName"> First name </ label >

                <% = Html.TextBox( "FirstName" ) %>

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

            </ li >

            < li >

                < label for ="LastName"> Last name </ label >

                <% = Html.TextBox( "LastName" ) %>

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

            </ li >

            < li >

                < label for ="Email"> Email </ label >

                <% = Html.TextBox( "Email" )%>

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

            </ li >

            < li >

                < label for ="Phone"> Phone </ label >

                <% = Html.TextBox( "Phone" )%>

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

            </ li >

            < li >

                < div class ="option-group" id ="Gender">

                    <% = Html.RadioButton( "Gender" , Gender .Male.ToString())%> < span > <% = Gender .Male.ToString() %> </ span >

                    <% = Html.RadioButton( "Gender" , Gender .Female.ToString())%> < span > <% = Gender .Female.ToString() %> </ span >

                </ div >

            </ li >            

            < li >

                < input type ="submit" value ="Add contact" />

            </ li >

        </ ol >

    </ fieldset >

    <% } %>

 

</ asp : Content >

In my ContactController class the following methods are defined.

public ActionResult AddContactClassic()

{

    return View();

}

[ AcceptVerbs ( HttpVerbs .Post)]

public ActionResult AddContactClassic( Contact contact)

{

    if (contact == null ) { throw new ArgumentNullException ( "contact" ); }

 

    InternalAddContact(contact);

 

    return View();

}

When I ran the app and filled in all the values on the AddContactClassic page I was a bit surprised to see an error simply stating “A value is required.” Here is a screen shot.

So I assumed that I must have misspelled one of the names of the fields that were passed to the Html.TextBox method. Obviously this was not the issue, so then I remembered that the Contact class that I defined had another property, Id, which I was not contained in a field on the form. This is the case because this page is supposed to create a new Contact, so its Id will not be set. I changed the AddContactClassic(Contact) method to ignore the Id property when binding was occurring. Here is the new method.

[ AcceptVerbs ( HttpVerbs .Post)]

public ActionResult AddContactClassic( [ Bind (Exclude= "Id" )] Contact contact)

{

    if (contact == null ) { throw new ArgumentNullException ( "contact" ); }

 

    InternalAddContact(contact);

 

    return View();

}

By using the Bind attribute I was able to let the DefaultModelBinder know that I was not interested in getting the value for that field. Once I made this change everything worked fine.

In the Contact class I had incorrectly defined the Id property to be Guid instead of Guid? which is better. If I had correctly declared that then the DefaultModelBinder   would have known that it was not a required field and it would not have complained. But if you are using the Entity Framework , you may still have this issue anyway because it does not always create nullable fields for all nullable columns in my experience. Even after changing the Contact class to use Guid? I have purposefully left the Bind(Exclude=”Id”) on the method in case something changes in the implementation of the Contact class.

Sayed Ibrahim Hashimi

Monday, 18 May 2009 04:25:27 (GMT Daylight Time, UTC+01:00)  #     |