"The Id field is required" validation message on Create; Id not set to [Required]

This is happening when I try to create the entity using a Create style action in Asp.Net MVC 2.

The POCO has the following properties:

public int Id {get;set;}

[Required]
public string Message {get; set}

On the creation of the entity, the Id is set automatically, so there is no need for it on the Create action.

The ModelState says that "The Id field is required", but I haven't set that to be so. Is there something automatic going on here?

EDIT - Reason Revealed

The reason for the issue is answered by Brad Wilson via Paul Speranza in one of the comments below where he says (cheers Paul):

You're providing a value for ID, you just didn't know you were. It's in the route data of the default route ("{controller}/{action}/{id}"), and its default value is the empty string, which isn't valid for an int. Use the [Bind] attribute on your action parameter to exclude ID. My default route was: new { controller = "Customer", action = "Edit", id = " " } // Parameter defaults

EDIT - Update Model technique

I actually changed the way I did this again by using TryUpdateModel and the exclude parameter array asscoiated with that.

    [HttpPost]
    public ActionResult Add(Venue collection)
    {
        Venue venue = new Venue();
        if (TryUpdateModel(venue, null, null, new[] { "Id" }))
        {
            _service.Add(venue);
            return RedirectToAction("Index", "Manage");
        }
        return View(collection);
    }

You can add the attribute:

 [Bind(Exclude = "Id")] 

on the parameter in method rather than the class, that way on create you can exclude it and on edit it will still be mandatory:

public ActionResult Create([Bind(Exclude = "Id")] User u)
{
    // will exclude for create
}

public ActionResult Edit(User u)
{
    // will require for edit
}

I ran into this issue with a form in which I was adding "objects" to a list dynamically. Therefore, our users were able to add, remove or update. It all worked well except for the cases when new items were created. For this reason, in my case, excluding the Id property was not an option. The solution was to make the ID Nullable:

public int? Id { get; set; }

This way existing items will have a value and new ones will have null instead. Good stuff.

Great question and answers, saved my ... behind. I need to add something, though:

Instead of

[Bind(Exclude = "Id")]

I think it's better to use

[Bind(Include = "Prop1, Prop2, Prop3, etc")]

.. where Prop1, Prop2 and Prop3 are THE ONLY properties that you want to be bound at the action level.

Since this is white-listing as opposed to black-listing. White-listing is better, safer. This way you also solve the risk of over posting and under posting too. See Brad Wilson's post.

[Bind(Exclude = "Id")]
public class Hebe
{
      public int Id {get;set;}

      [Required]
      public string Message {get; set}
}

By the way above it doesnt bind the Id Property for your model on create

The Id should be sent from the client as 0. The model does not have a problem with Id=0, this is the default of int. The problem is that he does not see the value coming from the client or it's coming with space or null. I have an input hidden that represents the Id (or in complex object NestedPropertyId/NestedProperty.Id) so I make sure it starts with a value of zero.

<input type="hidden" id="id" value="0" />
<input type="hidden" id="eventId" value="0"/>
<input type="hidden" id="contactId" value="0"/>

Also when Ireset the form to Add New entity in the client side, I make sure to initialize the hidden with zero.

Hope this helps somone.

Efy

Comments
  • You might find this blog post interesting: bradwilson.typepad.com/blog/2010/01/…
  • I did find it interesting. Doesn't solve this problem, but helps me think of some others I was going to have
  • How can I make "Id" type safe? Something like ()=>id ?
  • Nice. I think this will do the trick. I had seen it somewhere but couldn't find it again. Where did you find it?
  • @burnt_hand - Its in a book I have (Professional MVC 1.0 off the top of my head). But also you can google "asp.net mvc bind exclude" and there are some example usages.
  • HOW TO DEAL WITH FRONT END VALIDATION? JAVASCRIPT IS ASKING FOR 'REQUIRED' VALUES...
  • That doesn't work for me. I added that to action, and I'm still getting the error.
  • @Rosstified I have used Ajax.BeginForm() to post data. How do I handle two different action method while save/update using single button?
  • Best solution in my case. Thank you.
  • Excellent!! really helped me!
  • Agreed. You can easily get haX0rd if you aren't using View Models.
  • Yep. For example I have a CreateUser action on my Account controller. One of the properties of the User model is UserType which is an enum containing User, ..., Admin. If he'd be posting a hidden field called UserType and it's value "Admin" and I wouldn't use this form of Bind attribute I'd have WAY TOO MANY Admins on my site =))