I am having problems when the back button is used and a form is resubmitted, the value on the model that is bound to the drop down list is not retained on the second submission.
In real life, this code is a report generator - the form collects parameters from the user and then posts it to a results view where the data is displayed. Obviously this is a fairly complex bit of code to post, but below I have some simple code exhibiting the same bug:
I have a model like so:
public class HomeModel
{
public string SomeText { get; set; }
public long SelectedItemId { get; set; }
public IEnumerable<SelectListItem> AvailableItems { get; set; }
}
A form that submits an instance of the model like so:
@using(Html.BeginForm("Result", "Home", FormMethod.Get))
{
@Html.EditorFor(model => model.SomeText)
<br />
@Html.DropDownListFor(model => model.SelectedItemId, Model.AvailableItems)
<input type="submit" value="submit" />
}
And a view that shows the details, like so
You Typed: @Html.DisplayFor(model => model.SomeText) <br />
You Selected: @Html.DisplayFor(model => model.SelectedItemId)
And a controller to manage it all:
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
HomeModel model = new HomeModel();
List<SelectListItem> items = new List<SelectListItem>();
for (int i = 0; i < 10; i++)
items.Add(new SelectListItem() { Value = i.ToString(), Text = i.ToString() });
model.AvailableItems = items;
return View(model);
}
public ActionResult Result(HomeModel model)
{
return View(model);
}
}
I fill in the form, press submit. I am redirected to the Results view and all is well.
Then I press back in the browser, and I am shown the Index view again.
Then I submit the form again and things turn sour. The model is not being repopulated with the selected value from my list, despite the list appearing to show the previously selected value in the browser.
The string property is being updated correctly, and this is true in the real world code that I have displaying this behaviour.
This only happens in IE, I am using version 9.
Well I found the solution.
Short answer: don't suffix your model properties with 'Id'
When I first load the index view in the example, this is what gets rendered:
<SELECT id=SelectedItemId name=SelectedItemId data-val-required="The field is required"...>
When I submit, press back and then check the source, this is what I get:
<select name="SelectedItem" id="SelectedItem">
Notice that the name of the element has been changed, severely disrupting MVC's deserializers.
This can be seen in the URLs that are being posted, when I first post the form, this is the url that is shown in the browser:
http://localhost:57175/Home/Result?SomeText=999&SelectedItemId=1
Then, when I press back and post again, this is what is shown:
http://localhost:57175/Home/Result?SomeText=999&SelectedItem=1
I can live with changing the property name, but the trouble is that it also strips all of the validation attributes that are needed for using unobtrusive validation. Can anyone enlighten me on how to retain those?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With