问题
I have a view to create a user as follows.
<% using (Html.BeginForm("SaveUser", "Security")) {%>
<p>
<label for="UserName">UserName:</label>
<%= Html.TextBox("UserName") %>
<%= Html.ValidationMessage("UserName", "*") %>
</p>
<p>
<label for="Password">Password:</label>
<%= Html.TextBox("Password") %>
<%= Html.ValidationMessage("Password", "*") %>
</p>
<p>
<input type="submit" value="Create" />
</p>
<}%>
When the "Create" button is clicked, the HTML form is posted to an action called "SaveUser" that accepts the "POST" verb only as follows.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveUser( UserViewModel user)
{
//user.Id is zero before save
//Save the user. Code omitted...
//user.Id is now greater than zero
//redirect to edit user view
return View("EditUser", user );
}
After the user is saved, the page is redirected to the "EditUser" view with
<p>
<label for="Id">Id:</label>
<%= Html.Hidden("Id", Model.Id)%>
</p>
Here is the problem: the value for the hidden field kept showing up as zero though. Model.Id
is greater than zero. It seemed that something else is overriding the model view value. ViewDataDictonary
was a suspect. So a line is added before returning the view in the action as follows.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SaveUser( UserViewModel user)
{
//user.Id is zero before save
//Save the user. Code omitted...
//user.Id is now greater than zero
//clear the view data
ViewData = new ViewDataDictionary();
//redirect to edit user view
return View( "EditUser", user);
}
Sure enough, this worked. The hidden field now has a value of the correct user ID.
We found a way to treat the symptom, but where is the source of the problem?
I don't like the idea of clearing view data dictionary every time before a returning another view.
回答1:
After successful operation you should use
return RedirectToAction("EditUser", new { id = user.Id });
or similar code. The current ModelState is used to generate view and model binder didn't bind Id.
[Bind(Exclude = "Id")]
could also work, but the redirection creates new page (not using current ModelState) and is a better solution.
Edit:
If you don't want to bind whole object, you should use [Bind (Exclude)]
or you should just define SaveUser
as SaveUser(string userName, string password)
and build the UserViewModel
object yourself. This will save you from errors generated by model binder and Model values, that you don't know where come from.
来源:https://stackoverflow.com/questions/1560579/view-data-dictionary-overriding-model-data-in-asp-net-mvc