问题
I have different kinds of elements - textboxes, selects, checkboxes and radio buttons on my view. When I present this strongly typed view with the model there are some elements that get populated with corresponding model values but there are certain kinds and ones that don't. Radio buttons, checkboxes are blank. When it comes to select elements, if they are created with @Html.DropDownListFor
helper method then they get correct values, but if they are just plain Html selects with their names corresponding to model properties then the default- first item is selected. I've created both checkboxes and radiobuttons with @Html helper methods:
@Html.RadioButtonFor(x => x.PreferredReplyMethod, PreferredReplyMethod.Written.GetHashCode(), new { id = "rbReplyWritten" })
<label for="rbReplyWritten">Written</label>
@Html.RadioButtonFor(x => x.PreferredReplyMethod, PreferredReplyMethod.Verbal.GetHashCode(), new { id = "rbReplyVerbal" })
<label for="rbReplyVerbal">Verbal</label>
@Html.CheckBoxFor(x => x.IsUnderControl, new { id = "chkUnderControl" })
@Html.LabelFor(x => x.IsUnderControl, new { @for = "chkUnderControl" })
The thing is, if I post these values to back to the server, all the saved values are correct. What should I do?
回答1:
I finally found the cause of the problem. So grab your coffee (of course those who are new to ASP.NET MVC model binding like me) to sip as you read. As I said I had a problem with the checkboxes, radiobuttons and select elements (that were not generated with the help of DropDownListFor<> helper method) not having correct values. When posting back the form I was able to save all the data (except for checkboxes) I'd entered to the database correctly. But when reading back, the form was not being filled with correct values - selects had their first options selected, radio buttons and checkboxes where clear. The common cause of the problem was the value attribute not having correct value. So I'll touch each of them one by one.
- On the view some of the select elements were created with DropDownListFor<> helper method, whereas some were just marked up as plain html matching their name to that of the corresponding model property, just like this:
<select class="select-normal" name="ApplicationType"> <option value="0">--Choose--</option> <option value="1">Complaint</option> <option value="2">Proposal</option> <option value="3">Query</option> </select>
ApplicationType is of custom Enum type.
public Enum ApplicationType{
Complaint=1
Proposal=2,
Query=3
}
When in edit/insert mode the selected option is easily bound to the appropriate property because there's an implicit cast from numeric value to enum. But when reading, the model property value is the name of the enum member, not its underlying value. So i.e., if the ApplicationType is ApplicationType.Proposal MVC engine will look for the element that has the same name and will find our select. Then it will try to find the option that has the value of "Proposal",not 2, and it won't find any. So we have to set the values to the names of the enum options, like this:
<select class="select-normal" name="ApplicationType"> <option value="0">--Choose--</option> <option value="Complaint">Complaint</option> <option value="Proposal">Proposal</option> <option value="Query">Query</option> </select>
But even this alone is not enough to get the correct option selected. The problem is, for an option to be selected it needs selected
attribute to be set, as such selected="selected"
. Unfortunately I couldn't figure out how to accomplish this, so I searched the web and found out that there's a new Html extension method in MVC 5.1 caled EnumDropDownListFor<>, which you can add to your project from here. This method generates an html select element from an enum. You have to keep two things in mind before using it:
a) You need to decorate your enum options with Disaplay(Name="Enum1 display text") if you want your select to display user friendly names b) By default the method will set the value of the option element to be the underlying value of the enum. Just change this
string value = Convert.ChangeType(field.GetValue(null), baseEnumType).ToString();
to this
string value=field.Name;
After adding this code to your project, the only thing yo have to do is just add this one line of code
@Html.EnumDropDownListFor(x => x.ApplicationType, new { @class = "select-normal" })
But of course, if you manage to control the "selectedness" of options somehow, you can still go the old way .That's all, you're good to go.
For radiobuttons my mistake was to set the value to Enum.GetHashCode(). So changing this
@Html.RadioButtonFor(x => x.PreferredReplyMethod, PreferredReplyMethod.Verbal.GetHashCode())
to this will solve the problem
@Html.RadioButtonFor(x => x.PreferredReplyMethod, PreferredReplyMethod.Verbal
.GetHashCode())
With checkboxes though, the situation is a bit different. If I pass the Model to the Html.BeginForm method explicitly like this
@using(Html.Beginform("SaveDocument","DocumentController",Model))
and debug the action method I can see that the model properties corresponding to checkboxes (they're all of type int
) have value of "0". So when they're read back this causes the checkboxes to be unchecked. I haven't been able to figure out why, because if I let the MVC engine pass the model implicitly, this problem evaporates.
@using(Html.Beginform("SaveDocument","DocumentController"))
来源:https://stackoverflow.com/questions/24466610/radiobutton-checkbox-and-select-elements-dont-get-populated-accordingly