maybe it was a simple question but 2 day I worked on it. it was work for me in another view, but now not work for me I want show second dropdownlist by change of first but not work how can I resolve that
I use chrome inspect to show and use debug mode and breakpoints , the debugger didn't go to control
@section Scripts {
@Scripts.Render("~/bundles/jqueryval")
<script>
$(document).ready(function() {
$(document).on("change","#ProvinceId",function() {
var pid = this.value;
$.ajax({
type: "POST",
url:'@Url.Action("ReturnCity", "Account")',
dataType:"json",
data:{provinceId:pid},
contentType:'application/json; charset=utf-8',
success: function(data) {
$('#CityId').empty();
$.each(data,
function (index, item) {
$('#CityId').append($('<option></option>').text(item.Name).val(item.Id));
});
}, error: function (data)
{ alert(data) }
});
});
});
</script>
}
and my control is
public ActionResult Register()
{
//return PartialView("_Login");
ViewBag.ProvinceId = new SelectList(_db.Provinces, "Id", "Name");
ViewBag.CityId = new SelectList(_db.Cities, "Id", "Name",_db.Cities.Where(x => x.ProvinceId == 1));
return View("");
}
//
// POST: /Account/Register
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Register(RegisterViewModel model)
{
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email,CountryId = 55,ProvinceId = model.ProvinceId,CityId = model.CityId};
var result = await UserManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
MigrateShoppingCart(model.Email);
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
// For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
string code = await UserManager.GenerateEmailConfirmationTokenAsync(user.Id);
var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: Request.Url.Scheme);
await UserManager.SendEmailAsync(user.Id, "" + callbackUrl + "\">link</a>");
// Uncomment to debug locally
// TempData["ViewBagLink"] = callbackUrl;
ViewBag.Message = "";
return View("Info");
//return RedirectToAction("Index", "Home");
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
for return city this is code in control
[HttpPost]
public JsonResult ReturnCity(int provinceId)
{
_db.Configuration.ProxyCreationEnabled = false;
var data = _db.Cities.Where(x => x.ProvinceId == provinceId);
return Json(data.ToList(), JsonRequestBehavior.AllowGet);
}
in view i use this for show two related dropdownlist
<div class="form-group">
@Html.LabelFor(model => model.ProvinceId, "استان", htmlAttributes: new { @class = "control-label col-md-4" })
<div class="col-md-8">
@*@Html.DropDownListFor(model=>model.ProvinceId, (SelectList)ViewBag.ProvinceId, "Select", new { htmlAttributes = new { @class = "form-control" }})*@
@Html.DropDownList("ProvinceId", "Select")
@Html.ValidationMessageFor(model => model.ProvinceId, "", new { @class = "text-danger" })
</div>
</div>
<div class="form-group">
@Html.LabelFor(model => model.CityId,"City", htmlAttributes: new { @class = "control-label col-md-4" })
<div class="col-md-8">
@*@Html.DropDownListFor(model => model.CityId, (SelectList)ViewBag.CityId, "Select", new { htmlAttributes = new { @class = "form-control" } })*@
@Html.DropDownList("CityId", "Select")
@Html.ValidationMessageFor(model => model.CityId, "", new { @class = "text-danger" })
</div>
</div>
I see few issues with your code. First, in your ajax call, you specify the contentType contentType:'application/json; charset=utf-8',
. But you are trying to send a javascript object in the data property. So jQuery will send Content-Type:application/json; charset=UTF-8
in the request header and provinceId=1
as the request payload in the request body. The server code uses the contentType header to determine how to deserialize and model bind the posted form data/request body to the parameter of your action method. Usually you specify the content type as json when you send a stringified json version of a javascript object. The Model binder will be able to map this to your method param (a view model object matching with the structure of your js object)
Since your method parameter is a simple int, you do not need to specify the contenttype as application/json. Simply remove that line and it will hit the action method in server . You can also remove the datatype param as well.
This should work as long as you do not have any other script error in the page(check browser console).
$(document).ready(function() {
$(document).on("change","#ProvinceId",function() {
var pid = this.value;
$.ajax({
type: "POST",
url:'@Url.Action("ReturnCity", "Account")',
data:{provinceId:pid},
success: function(data) {
$('#CityId').empty();
$.each(data,
function (index, item) {
$('#CityId').append($('<option></option>')
.text(item.Name).val(item.Id));
});
}, error: function (data)
{ alert(data) }
});
});
});
Also since you want user to select the city based on selected province, there is no need to load all cities. You can simply render a select element using vanilla html with Id
and Name
set to CityId
See this post for some sample cascading dropdown code.
Change your code as following.
Script
@section Scripts {
<script>
$(document).on("change","#ProvinceId",function() {
var pid = this.value;
$.ajax({
url: '/Account/ReturnCity',
type: "POST",
dataType: "JSON",
data: { provinceId: pid },
success: function (data) {
$("#CityId").html(""); // clear before appending new list
$.each(cities, function (i, city) {
$("#CityId").append(
$('<option></option>').val(city.CityId).html(city.CityName));
});
}
});
)}
</script>
}
Controller
public ActionResult ReturnCity(int provinceId)
{
_db.Configuration.ProxyCreationEnabled = false;
var data = _db.Cities.Where(x => x.ProvinceId == provinceId);
return Json(data , JsonRequestBehavior.AllowGet);
}