This weekend I had an issue with the postback of a simple viewmodel object. For some reason the validation of this object failed even though the Id was not required.
public class SkillViewModel
{
public int Id { get; set; }
[Required]
public virtual string Description { get; set; }
[Required]
public virtual string Name { get; set; }
}
[HttpPost]
public ActionResult Create(SkillViewModel skill)
if (ModelState.IsValid)
{
SkillRecord oRecord = new SkillRecord()
{
Name = skill,
Description = skill.Description
};
SkillService.Create(oRecord);
return RedirectToAction("Index");
}
return View(skill);
}
To solve this issue, I started by adding some debugging code to the controller action to find out what was going wrong.
var errors = ModelState.SelectMany(e => e.Value.Errors);
This gave me the following error: "The Id field is required.". This is strange. Of course changing the name of the Id property works, but this is not what I want.
So what is going on. In the create I am underposting, this means I am not posting the Id. This gave me problems in combination with my defined routes.
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Since I am not posting the Id from by razor view, the binding takes tries to get the id from the route, which is not there and cause a validation error.
There are two solutions, either add '[Bind(Exclude = "Id")]' before the parameter in the Create method or add an additional route (before the existing one) without the id in it:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);