-1

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>
sunny
  • 2,670
  • 5
  • 24
  • 39
  • Please update your question with any errors you're receiving in your javascript console. – Soviut Sep 10 '17 at 20:28
  • when I changed first dropdownlist i didn't any change in dropdownlist two, without any error in inspector – sunny Sep 10 '17 at 20:29
  • to start with, you have an extra `}` at the end of your script – Shyju Sep 10 '17 at 20:30
  • I update it again please check again – sunny Sep 10 '17 at 20:34
  • Are you getting any errors in your console ? – Shyju Sep 10 '17 at 20:36
  • no nothing and debugger did n't got to ReturnCity when i check with debugger – sunny Sep 10 '17 at 20:37
  • Remove the `contentType` option (your not stringifying your data so it need to be the default `'application/x-www-form-urlencoded; charset=UTF-8'`. But there are numerous other issues with your code including the name of the property you binding to and the `SelectList` cannot be the same (refer [this answer](http://stackoverflow.com/questions/37161202)) and the fact that this all fails if your need to return the view and you code will not work for editing existing items - refer [this answer](https://codereview.stackexchange.com/questions/174079/) –  Sep 10 '17 at 22:05

2 Answers2

1

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.

Shyju
  • 214,206
  • 104
  • 411
  • 497
  • before copy and past this code: when change province dropdownliad dont change City List , and in dropdownliast city there are all city, but after copy and past this code: when change province dropdownliast ,city dropdownliast change and go to be empty, – sunny Sep 11 '17 at 14:50
  • is it making the ajax call ? What is the response you are getting for that xhr call ? Is it a 200 OK with the expected response ? If it is 500 response ,you might have a code problem in your action method which needs to be fixed. – Shyju Sep 11 '17 at 15:40
  • in inspector I don't have any Error, data return null , and when check with breakpoints , debugger don't go to ReturnCity action in Account controller – sunny Sep 11 '17 at 16:00
  • 1
    to which endpoint it is making the call ? check the network tab in your dev tools – Shyju Sep 11 '17 at 16:01
0

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);
}
Alsamil Mehboob
  • 384
  • 2
  • 6
  • 24