6

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

5
  • How is generated html look like for the hidden field? Also can you post your UserProfile model? Commented Jan 22, 2013 at 13:07
  • <input data-val="true" data-val-number="The field UserId must be a number." data-val-required="The UserId field is required." id="UserId" name="UserId" type="hidden" value="4" /> Commented Jan 22, 2013 at 13:09
  • 1
    The generated HTML looks fine. So can you update your post with the definition of your UserProfile class? Commented Jan 22, 2013 at 13:10
  • Do you have a parameter named UserId in your routes? Commented Jan 22, 2013 at 13:11
  • no I haven't touched the routes file, userprofile class added Commented Jan 22, 2013 at 13:12

2 Answers 2

7

The DefaultModelBinder only able to bind public properties.

Change your property setter to public and it should work fine:

[Key]
[DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
public int UserId { get; set; }

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 UserProfile directly. Create a UserProfileViewModel where your UserId is public and use that in your View and Controller action. In this case you need to map between your UserProfile and the UserProfileViewModel but there are good tools exists for that task like AutoMapper.

Sign up to request clarification or add additional context in comments.

1 Comment

This is the answer. Can't use private set in this context.
1

As @nemesev said, the accessor properties on your Model properties need to be public.

To save you from having to hack away at your database class in order to make model binding work, you should really create a Model for that class, then you don't need to use the DTO in the view (which isn't ideal).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.