I have a simple edit form for a user model but when I post back, none of the hidden input values are being applied to model and I’m not sure why this is happening.
My Razor:
@model CMS.Core.Models.UserProfile
@using (Html.BeginForm())
{
@Html.ValidationSummary(true)
<fieldset class="normalForm">
<legend>User Profile</legend>
@Html.HiddenFor(model => model.UserId)
<div class="formRow">
<div class="editor-label">
@Html.LabelFor(model => model.EmailAddress)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.EmailAddress, new { @class = "textbox" })
@Html.ValidationMessageFor(model => model.EmailAddress)
</div>
</div>
<div class="formRow">
<div class="editor-label">
@Html.LabelFor(model => model.FirstName)
</div>
<div class="editor-field">
@Html.TextBoxFor(model => model.FirstName, new { @class = "textbox" })
@Html.ValidationMessageFor(model => model.FirstName)
</div>
</div>
<div class="buttonRow"><input type="submit" value="Save" class="button" /></div>
</fieldset>
}
My Controller:
[HttpPost]
public ActionResult Edit(UserProfile user)
{
if (ModelState.IsValid)
{
user.Save();
return RedirectToAction("Index");
}
return View(user);
}
UserProfile class:
[Table("UserProfile")]
public class UserProfile
{
[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; private set; }
[Required(ErrorMessage = "Please enter an email address")]
[StringLength(350)]
[DataType(DataType.EmailAddress)]
[Display(Name = "Email Address")]
public string EmailAddress { get; set; }
[StringLength(100)]
[DataType(DataType.Text)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
}
If I try user.UserId it returns zero (as it is an int) but if I try Request["UserId"] it returns the correct value so the value is being posted correctly – just not added into the UserProfile model. Does anyone know why this is happening or what I can do to solve it
Thanks
The
DefaultModelBinderonly able to bind public properties.Change your property setter to public and it should work fine:
If you can’t do that you will need create a custom model binder which deals with private setters.
However as a better approach instead of using your
UserProfiledirectly. Create aUserProfileViewModelwhere yourUserIdis public and use that in your View and Controller action. In this case you need to map between yourUserProfileand theUserProfileViewModelbut there are good tools exists for that task like AutoMapper.