Reputation: 169
I am trying to create cascading dropdownlist using @Html.DropDownListFor helper and jQuery AJAX. The first load is always perfect. all dropdownlist data was displayed correctly. However, after postback, it always hit ModelState.IsValid = False and the dropdownlist become empty. Below is my code:
Model
Public Property Province As New List(Of SelectListItem)
Public Property City As New List(Of SelectListItem)
Public Property SelectedProvince As String
Public Property SelectedCity As String
Controller
Public Function SetEmployeeProfile() As ActionResult
Dim loc As New clsLocation
Dim provinces As List(Of Province)
Dim model As New SetEmployeeProfileViewModel
provinces = loc.GetProvinceList
Dim sel As SelectListItem
For Each p As Province In provinces
sel = New SelectListItem
sel.Text = p.ProvinceName
sel.Value = p.ProvinceName
model.Province.Add(sel)
Next
Return View(model)
End Function
View
@ModelType SetEmployeeProfileViewModel
<div class="form-group">
@Html.LabelFor(Function(m) m.Province, New With {.class = "col-md-2 control-label"})
<div class="col-md-10">
@Html.DropDownListFor(Function(m) m.Province, New SelectList(Model.Province, "Value", "Text", Model.SelectedProvince), New With {.class = "form-control"})
@Html.ValidationMessageFor(Function(m) m.Province, "", New With {.class = "text-danger"})
</div>
</div>
<div class="form-group">
@Html.LabelFor(Function(m) m.City, New With {.class = "col-md-2 control-label"})
<div class="col-md-10">
@Html.DropDownListFor(Function(m) m.City, New SelectList(Model.City, "Value", "Text", Model.SelectedCity), New With {.class = "form-control"})
@Html.ValidationMessageFor(Function(m) m.City, "", New With {.class = "text-danger"})
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
LoadCities();
});
$("#Province").change(function () {
LoadCities();
});
function LoadCities() {
var selectedItem = $("#Province").val();
var ddlCities = $("#City");
var statesProgress = $("#city-loading-progress");
statesProgress.show();
$.ajax({
cache: false,
type: "POST",
url: "@(Url.Action("GetCities"))",
data: { "provinceName": selectedItem },
success: function (data) {
ddlCities.html('');
$.each(data, function (id, option) {
ddlCities.append($('<option></option>').val(option.CityName).html(option.CityName));
});
statesProgress.hide();
},
error: function (xhr, ajaxOptions, thrownError) {
alert('Failed to retrieve cities.');
statesProgress.hide();
}
});
}
NOTE: I tried adding selectedProvince property in the model and implemented according to this post but the problem still persist. Both Province and City field also produces the following validation error:
The value 'Bali' is invalid. (Province)
The value 'Kuta' is invalid. (City)
Is it normal that it put query string: Province=System.Collections.Generic.List ?
Upvotes: 0
Views: 1270
Reputation: 14614
Your mistake is here
@Html.DropDownListFor(Function(m) m.Province, New SelectList(Model.Province, "Value", "Text", Model.SelectedProvince), New With {.class = "form-control"})
and here
@Html.DropDownListFor(Function(m) m.City, New SelectList(Model.City, "Value", "Text", Model.SelectedCity), New With {.class = "form-control"})
The first parameter of @Html.DropDownListFor()
for the first dropdownlist should be Function(m) m.SelectedProvince
instead of Function(m) m.Province
, and for the second dropdownlist should be Function(m) m.SelectedCity
instead of Function(m) m.City
.
Below is the changed portion of code:
<div class="form-group">
@Html.LabelFor(Function(m) m.Province, New With {.class = "col-md-2 control-label"})
<div class="col-md-10">
@Html.DropDownListFor(Function(m) m.SelectedProvince, New SelectList(Model.Province, "Value", "Text", Model.SelectedProvince), New With {.class = "form-control"})
@Html.ValidationMessageFor(Function(m) m.Province, "", New With {.class = "text-danger"})
</div>
</div>
<div class="form-group">
@Html.LabelFor(Function(m) m.City, New With {.class = "col-md-2 control-label"})
<div class="col-md-10">
@Html.DropDownListFor(Function(m) m.SelectedCity, New SelectList(Model.City, "Value", "Text", Model.SelectedCity), New With {.class = "form-control"})
@Html.ValidationMessageFor(Function(m) m.City, "", New With {.class = "text-danger"})
</div>
</div>
Upvotes: 1