2

I would like to know why the function called by AJAX keeps fail in this scenario? The FillObj() is supposed to be called when a dropdownlist selection changes.

    <div class="form-group">
        @Html.LabelFor(model => model.Module, htmlAttributes: new { @class = "control-label col-md-2" })
        <div class="col-md-10">
            @Html.DropDownListFor(model => model.Module, new SelectList(Model.ModuleList, "Value", "Text"),
     "- Please select a Module -", new { @onchange = "FillObj()", @class = "form-control" })
        </div>
    </div> 

As you can see I already have the @onchange set to FillObj() in the Dropdownlist code. However, when the selection changes, it keep goes to alert('A error') instead of success. The following is the AJAX function:

function FillObj() {
    var moduleID = $('#Module').val();
    $.ajax({
        url: '/Questions/FillObjectives',
        type: "GET",
        dataType: "JSON",
        data: { module: moduleID },
        success: function (objectives) {
            $("#objective").html(""); // clear before appending new list
            $.each(objectives, function (i, Obj) {
                $("#objective").append(
                    $('<option></option>').val(Obj.ObjectiveId).html(Obj.objective));
            });
        },
        error: function () {
            alert('A error');
        }

    });
}

Controller:

public ActionResult FillObjectives(int module)
{
    var objectives = db.Objectives.Where(o => o.ModuleId == module);
    return Json(objectives, JsonRequestBehavior.AllowGet);
}

EDIT 1:

Ok, I did some debugging and found out that this error message occured whenever the function is called:

enter image description here

Anyways to fix this?

Pow4Pow5
  • 501
  • 2
  • 8
  • 22
  • 1
    does the controller action gets called, check using breakpoint using debugger? – Ehsan Sajjad Dec 18 '16 at 19:51
  • and use `Url.Action` for urls like: `url: '@Url.Action("FillObjectives","Questions")'` – Ehsan Sajjad Dec 18 '16 at 19:52
  • The controller parameter expects an integer. Try changing it to string: FillObjectives(string module) –  Dec 18 '16 at 19:52
  • @FernandaInesDuran that should not be a problem i think – Ehsan Sajjad Dec 18 '16 at 19:53
  • @Ehsan Sajjad In the ajax function the datatype has been defined as a json, so the type of data that you're expecting back from the server is a string. Is not correct? –  Dec 18 '16 at 20:12
  • 1
    What errors are you getting in the browser. The code you have shown works fine. Best guess is that the code in your controller throws an exception - debug it! –  Dec 18 '16 at 21:59
  • And not related, but why in the world are you generating an identical `IEnumerable` using `new SelectList(Model.ModuleList ...)` when `ModuleList` appears to be already `IEnumerable` –  Dec 18 '16 at 22:04
  • I found out the error is due to DataReader command executing a query while iterating over the results from another query..I'm not really sure about fixing this though.. – Pow4Pow5 Dec 19 '16 at 07:55
  • Start by trying `var objectives = db.Objectives.Where(o => o.ModuleId == module).Select(o => new { ObjectiveId = o.ObjectiveId, objective = 0.objective });` which will also improve greately performance. If that does not solve it, show your model for `Objective` –  Dec 19 '16 at 23:35

1 Answers1

1

Please see edit below in EDIT 1

If you are calling your action using GET, then you cannot send data in the body. You cannot do this:

data: { module: moduleID },

You can append it to the end of the url as a querystring.

url: '/Questions/FillObjectives?module=' + moduleID,

Or you can change the call to POST but make sure your action does not have HttpGet attribute applied to it.

EDIT 1

Thanks to the comments by Stephen Muecke, above I said that for a GET operation data { module: moduleID } should not be done. That is half true. And since this answer was upvoted a few times, I am sharing this so other people, who are under the same impression, will know that is is not true. It will not work if whatever being posted is already a string. If it is not a string, jQuery will convert it to a string and append it to the URL. This is from jQuery docs:

Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests.

In the question posted, it is not already a string so jQuery will convert the data to a string and append it to the url.

Therefore, in conclusion, the code posted in this question will work but the reason it is going to error is because the code in the controller is erroring out. If you do this in the controller, it will go to success on the client side:

public ActionResult FillObjectives(int module)
{
     var data = new[]{ new { ObjectiveId = 1, objective = "Option 1" }, new { ObjectiveId = 2, objective = "Option 2" } };
     return Json(data, JsonRequestBehavior.AllowGet);
}

So the issue most likely is with this line of code:

var objectives = db.Objectives.Where(o => o.ModuleId == module);
CodingYoshi
  • 25,467
  • 4
  • 62
  • 64
  • Of course `data: { module: moduleID },` works for a GET –  Dec 18 '16 at 21:57
  • I don't think so. See [here](http://stackoverflow.com/questions/978061/http-get-with-request-body) and [here](http://stackoverflow.com/questions/10298899/how-to-send-data-in-request-body-with-a-get-when-using-jquery-ajax). Why do you say it works-i would like to know. – CodingYoshi Dec 19 '16 at 00:28
  • Your should try it first :) And refer this [DotNetFiddle](https://dotnetfiddle.net/Lk6qQe) to prove it –  Dec 19 '16 at 00:41
  • Also form the [docs](http://api.jquery.com/jquery.ajax/) _Data to be sent to the server. It is converted to a query string, if not already a string. It's appended to the url for GET-requests ....._ –  Dec 19 '16 at 00:42
  • Hey @StephenMuecke, Thank you very much for that. I honestly was not aware of this little detail that jQuery will append it to the url. Anyways, I really appreciate you pointing this out. I edited my answer instead of simply deleting it since there are other people who are under the same impression and can hopefully benefit from it. – CodingYoshi Dec 19 '16 at 05:21
  • Actually your suggestion will also fail - OP has specified `dataType: 'json'` do in order for the test to work it would need to be `return Json(data, JsonRequestBehavior.AllowGet);` and so it would generate the ` –  Dec 19 '16 at 05:28