This question already has an answer here:
Having issues with the view state on a series of page views -- On the initial view of a page in Razor I am using Html.HiddenFor
as follows:
@Html.HiddenFor(x => Model.err)
@Html.HiddenFor(x => Model.errField)
@Html.HiddenFor(x => Model.errMessage)
@Html.HiddenFor(x => Model.IsMove)
which seems to work fine. My hidden input tags contain the correct values. However when I submit the form [HTTPPost]
and update the model in my controller action with..
model.err = transHelper.err;
model.errField = transHelper.errField;
model.errMessage = transHelper.errMessage;
return View(model);
The hidden fields do not seem to update, they contain the original values from the initial view. However When I use these fields in another context within the same razor view like this...
@*
this seems to not update correctly...
@Html.HiddenFor(x => Model.err)
@Html.HiddenFor(x => Model.errField)
@Html.HiddenFor(x => Model.errMessage)
@Html.HiddenFor(x => Model.IsMove)
*@
<input type="hidden" id="err" value="@Model.err" />
<input type="hidden" id="errField" value="@Model.errField" />
<input type="hidden" id="errMessage" value="@Model.errMessage" />
<input type="hidden" id="IsMove" value="@Model.IsMove" />
</div>
Then the input fields update correctly. I even created a View Helper to help debug, and in all cases, the Model seems to have correct data in HtmlHelper<TModel>
-- I even returned the Model as return Json(model);
and the data was fine.
At this point I am running with the work around, but does anybody know why @Html.HiddenFor
is dirty.
Update: here is my controller actions
[HttpPost]
public ActionResult Index(HomePageModel model)
{
// process transaction
Transactionr transr = new Transactionr();
transr.Process(model);
model.err = transr.err;
model.errField = transr.errField;
model.errMessage = transr.errMessage;
return View(model);
}
Here is my view:
@model App.Models.HomePageModel
@{
ViewBag.Title = "Product Categorizer";
}
<form id="formData" method="post" action="/Home/Index">
@Html.AntiForgeryToken()
<fieldset>
<div>
@Html.HiddenFor(model => model.err)
@Html.HiddenFor(model => model.errField)
@Html.HiddenFor(model => model.errMessage)
@Html.HiddenFor(model => model.IsMove)
<input type="hidden" id="myerr" value="@Model.err" />
<input type="hidden" id="myerrField" value="@Model.errField" />
</div>
<div class="section group">
<div class="col span_2_of_2">
<div class="message" id ="message">
@if (Model.err < 0)
{
<span style="color: purple;">@Model.errMessage (@Model.err) - (@Model.errField)</span>
}
else if (Model.err > 0)
{
<span style="color:red;">@Model.errMessage (@Model.err) (@Model.errField)</span>
} else {
<span>@Model.errMessage (@Model.err) (@Model.errField)</span>
}
</div>
</div>
</div>
<div class="section group" id="workspace">
@Html.Partial("_WorkspacePartial", Model)
</div>
<div class="section group" id="details">
@Html.Partial("_DetailPartial", Model)
</div>
</fieldset>
</form>
Here is my model:
public class HomePageModel
{
public int FromStore { get; set; }
// the "To" part of the copy/move transaction
public int ToStore { get; set; }
// a list of the copy/move transaction
public List<int> Details { get; set; }
// true is move false is copy
public bool IsMove { get; set; }
// current message
public int err { get; set; }
public int errField { get; set; }
public string errMessage { get; set; }
I had a similar issue and solved it like this.
You can try
As mentioned by joedotnot this is intended behaviour. Another 'quick fix' for this is to code the html for the hidden field and update only the value from the model eg:
Use the same
id
andname
as your model property and the updated value will be rendered after postback.You need a key in your view model. If you don't have any property named as Id in your view model, set one of them (expected to be uniqe identifiyer) as key with [Key].
The default HtmlHelpers behavior (@Html.HiddenFor, etc) is to behave exactly as you have described.
i.e. any changes you make to the ViewModel on a post are actioned, any changes you return from the Post are received by the view, but on re-rendering WITH HTMLHELPERS, the previous Post-values take precedence over the changed ViewModel values.
Want to "fix" this behavior in a quick + dirty way, clear the ModelState.Clear() prior to returning from the HttpPost ActionMethod !
I've faced similar problem recently and ended up with writing new simple helper method + 2 overloads. I'm sharing it here in case anybody is still looking for some workaround cause this "feature" is sometimes annoying.
Then you just use it as usual from within you view:
It worth to mention it works with collections too.