开发者

View data dictionary overriding model data in ASP.NET MVC

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 Vie开发者_JAVA技巧w( "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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜