1

My controller Action method looks like the below:

    [HttpGet]
    [Route("ShowModal")]
    public Task<IActionResult> GetDetails(int id, string name, IEnumerable<Employee> employees)
    {
    //create a model
    //Some business logic codes

    return PartialView("_Partial.cshtml", model);
    }

I need to call the above Action Method from jQuery's $.get() method on a button click, capture the partial view returned as HTML, and show it in a Bootstrap popup.

I am not able to pass the IEnumerable<Employee> from the jQuery method, it is always null, whatever I try.

Below is the JS code:

<a class="btn btn-primary" onclick="ShowModal();" data-keyboard="true" data-toggle="modal">ShowModal</a>

<div class="modal fade" id="divShowModalDialog" role="dialog" tabindex="-1">
    <div class="modal-body" id="divShowModalBody">
    </div>
</div>

function ShowModal()
    {
        var list = [{ Id: 101, Gender: 'MALE' }, { Id: 102, Gender: 'FEMALE' }];
        list = JSON.stringify(list);

        var data = { 'id': 999, 'name': 'JAMES', 'employees': list };

        $.get('/Area1/Controller1/ShowModal', data)
        .done(function (response) {
            if (response != undefined) {
                $('#divShowModalBody').html(response);
                $('#divShowModalDialog').modal(
                    {
                        backdrop: 'static',
                        keyboard: true,
                    });                
            }
        })
        .fail(function (xhr) {
            console.log(xhr);
        })           
    }

I get the id and name parameter in the Action method, but the list is always empty. I have tried after removing JSON.stringify() as well, but it doesn't work. I know I'm missing a trivial thing, please help.

Anurag
  • 552
  • 9
  • 31

3 Answers3

0

First, you should be using [HttpPost] on your controller action and not [HttpGet], and of course you'll need to use post from jQuery which is using $.post() and that is because 'POST' is the correct - but not the only - HTTP verb to actually post data to the server side.

Second, you shouldn't stringify your employees list before you put it in your data javascript object that you are sending. so, list = JSON.stringify(list); and just straight away go

var data = { 'id': 999, 'name': 'JAMES', 'employees': list };

You also might need to provide the dataType using $.post(url,data,onsucess,dataType) check documentation in the link above.

Last, on your action method remove IEnumerable<T> and replace it with a concrete collection type like List<T> because the JSON serializer will need to know which type of collection to instantiate at binding time.

sm_
  • 2,572
  • 2
  • 17
  • 34
  • You are right. I just did the same thing, changed GET to POST in the action method and $.get() to $.post() in the jQuery method. Works fine. I don't think I need to change IEnumerable to List, coz List inherits from IEnumerable. Thanks – Anurag Aug 26 '16 at 04:58
  • Even though List "implements" IEnumerable, that is not the issue, the issue is how would the json converter figure out which type of collection to create that implements IEnumerable. – sm_ Aug 26 '16 at 05:17
  • I need not change IEnumerable to List. The JSON binder recognizes it. – Anurag Aug 26 '16 at 06:58
0

Actually you can achieve it without changing it to POST by using $.ajax()

Use a dictionary object instead of IEnumerable in action method

public ActionResult GetDetails(int id, string name, Dictionary<int,string> employees)
    {

And then in the script

var list = [{ Id: 101, Gender: 'MALE' }, { Id: 102, Gender: 'FEMALE' }];


    var data = { id: 999, name: 'JAMES', employees: list };
    debugger;
    $.ajax({
        url: '/Home/GetDetails',
        type: "GET",
        data :data,
        contentType: "application/json",
        dataType: "json"
    });
Amal Dev
  • 1,938
  • 1
  • 14
  • 26
  • Thanks for the suggestion. I will try it. But i have to use $.get() or $.post() not $.ajax(). They all are more or less same, but I need not use $.ajax(). – Anurag Aug 26 '16 at 06:56
-1

I was replying to your comment but decided it would be easier to demonstrate my point as an answer.

To answer your question, no I am not sure. But thats why I asked you to try it first, it seems logical as you are passing a list and not IEnumerable to your function.

Also, depending on what your Employee class looks like, you should try this: (you need a constructor in your Employee class for this)

List<Employee> list = new List<Employee>();
list.Add(new Employee(101, 'MALE'));
list.Add(new Employee(102, 'FEMALE'));

var data = { 'id': 999, 'name': 'JAMES', 'employees': list };
...

Update

I realize why I'm wrong, I kept thinking in C# terms. Json.stringify() returns a json style string (which C# just sees as a string), so your public Task GetDetails(int id, string name, IEnumerable employees) should be public Task GetDetails(int id, string name, string employees) and then in C#, you need to parse the JSON string. A helpful link: How can I parse JSON with C#?

Community
  • 1
  • 1
Keyur PATEL
  • 2,299
  • 1
  • 15
  • 41
  • How can you create a List as you have created above in JS? I don't think so. And List inherits IEnumerable, so those are okay. – Anurag Aug 26 '16 at 04:22
  • @ Keyur: I can't just change the signature of the function mate. Thanks for your help. I will try to find out the solution. – Anurag Aug 26 '16 at 04:47