Something pretty weird is happening with my app:
I have the following property in my ViewModel:
public int? StakeholderId { get; set; }
It gets rendered in a partial view as follows:
<%= Html.Hidden("StakeholderId", Model.StakeholderId) %>
The form is submitted, and the relevant controller action generates an id and updates the model, before returning the same view with the updated model
The problem I'm experiencing is that the hidden field does not have anything in its "value" attribute rendered the second time even though StakeholderId now has a value.
If I just output the value on its own, it shows up on the page, so I've got it to render the value by doing this:
<input type="hidden" id="StakeholderId" name="stakeholderId" value="<%: Model.StakeholderId %>" />
But it's pretty strange that the helper doesn't pick up the updated value?
(I'm using jQuery to submit forms and render the action results into divs, but I've checked and the html I get back is already wrong before jQuery does anything with it, so I don't think that has much to do with anything)
UPDATE
I've since discovered that I 开发者_StackOverflow社区can also clear the relevant ModelState key before my controller action returns the partial view.
The helper will first look for POSTed values and use them. As you are posting the form it will pick up the old value of the ID. Your workaround is correct.
ADDENDUM: Multiple HTML Forms, eg, in a Grid
As an addendeum to this issue, one thing to be VERY careful of is with multiple forms on the same page, eg, in a grid, say one generated using Ajax.BeginForm.
You might be tempted to write something along the lines of:
@foreach (var username in Model.TutorUserNames)
{
<tr>
<td>
@Html.ActionLink(username, MVC.Admin.TutorEditor.Details(username))
</td>
<td>
@using (Ajax.BeginForm("DeleteTutor", "Members",
new AjaxOptions
{
UpdateTargetId = "AdminBlock",
OnBegin = "isValidPleaseWait",
LoadingElementId = "PleaseWait"
},
new { name = "DeleteTutorForm", id = "DeleteTutorForm" }))
{
<input type="submit" value="Delete" />
@Html.Hidden("TutorName", username)
}
</td>
</tr>
}
The lethal line in here is:
@Html.Hidden("TutorName", username)
... and intend to use TutorName as your action's parameter. EG:
public virtual ActionResult DeleteTutor(string TutorName){...}
If you do this, the nasty surprise you are in for is that Html.Hidden("TutorName", username) will, as Darin Dimitrov explains, render the last POSTed value. Ie, regardless of your loop, ALL the items will be rendered with the TutorName of the last deleted Tutor!
The word around, in Razor syntax is to replace the @Html.Hidden call with an explicit input tag:
<input type="hidden" id="TutorName" name="TutorName" value='@username' />
This works as expected.
Ie:
NEVER, EVER USE Html.Hidden TO PASS A PARAMETER BACK TO YOUR ACTIONS WHEN YOU ARE USING MULTIPLE FORMS IN A GRID!!!
Final Caveat:
When constructing your hidden input tag, you need to include both name and id, set to the same value, otherwise, at the time of writing (Feb 2011) it won't work properly. Certainly not in Google Chrome. All you get is a null parameter returned if you only have an id and no name attribute.
精彩评论