How to receive JSON as an MVC 5 action method parameter
Asked Answered
R

4

76

I have been trying the whole afternoon crawling through the web trying to receive a JSON object in the action controller.

What is the correct and or easier way to go about doing it?

I have tried the following: 1:

//Post/ Roles/AddUser
[HttpPost]
public ActionResult AddUser(String model)
{
    if(model != null)
    {
        return Json("Success");
    }else
    {
        return Json("An Error Has occoured");
    }

}

Which gave me a null value on my input.

2:

//Post/ Roles/AddUser
[HttpPost]
public ActionResult AddUser(IDictionary<string, object> model)
{
    if(model != null)
    {
        return Json("Success");
    }else
    {
        return Json("An Error Has occoured");
    }

}

which gives me a 500 error on the jquery side which is trying to post to it? (meaning that it didn't bind correctly).

here is my jQuery code:

<script>
function submitForm() {

    var usersRoles = new Array;
    jQuery("#dualSelectRoles2 option").each(function () {
        usersRoles.push(jQuery(this).val());
    });
    console.log(usersRoles);

    jQuery.ajax({
        type: "POST",
        url: "@Url.Action("AddUser")",
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: JSON.stringify(usersRoles),
        success: function (data) { alert(data); },
        failure: function (errMsg) {
            alert(errMsg);
        }
    });
}

All I want to do is receive my JSON object in my mvc action?

Rolo answered 5/2, 2014 at 13:32 Comment(2)
While this specifies MVC5, the solution is the same, so this is a duplicate of Posting JSON Data to ASP.NET MVCJacobs
Check this: codingfusion.com/Post/…Palaestra
B
89

Unfortunately, Dictionary has problems with Model Binding in MVC. Read the full story here. Instead, create a custom model binder to get the Dictionary as a parameter for the controller action.

To solve your requirement, here is the working solution -

First create your ViewModels in following way. PersonModel can have list of RoleModels.

public class PersonModel
{
    public List<RoleModel> Roles { get; set; }
    public string Name { get; set; }
}

public class RoleModel
{
    public string RoleName { get; set;}
    public string Description { get; set;}
}

Then have a index action which will be serving basic index view -

public ActionResult Index()
{
    return View();
}

Index view will be having following JQuery AJAX POST operation -

<script src="~/Scripts/jquery-1.10.2.min.js"></script>
<script>
    $(function () {
        $('#click1').click(function (e) {

            var jsonObject = {
                "Name" : "Rami",
                "Roles": [{ "RoleName": "Admin", "Description" : "Admin Role"}, { "RoleName": "User", "Description" : "User Role"}]
            };

            $.ajax({
                url: "@Url.Action("AddUser")",
                type: "POST",
                data: JSON.stringify(jsonObject),
                contentType: "application/json; charset=utf-8",
                dataType: "json",
                error: function (response) {
                    alert(response.responseText);
            },
                success: function (response) {
                    alert(response);
                }
            });

        });
    });
</script>

<input type="button" value="click1" id="click1" />

Index action posts to AddUser action -

[HttpPost]
public ActionResult AddUser(PersonModel model)
{
    if (model != null)
    {
        return Json("Success");
    }
    else
    {
        return Json("An Error Has occoured");
    }
}

So now when the post happens you can get all the posted data in the model parameter of action.

Update:

For asp.net core, to get JSON data as your action parameter you should add the [FromBody] attribute before your param name in your controller action. Note: if you're using ASP.NET Core 2.1, you can also use the [ApiController] attribute to automatically infer the [FromBody] binding source for your complex action method parameters. (Doc)

enter image description here

Blandina answered 5/2, 2014 at 13:54 Comment(6)
Ah, so it needs to be a POST? I had the same problem, the argument of the model being null, but when I added POST to my ajax call and to the mvc controller, my model isn't null anymore. Only thing bothering me is that if you assign and empty string to one of the properties in javascript, and pass this object with ajax to the server, in C# the server reads these empty string properties as null. I'd rather like them to be an empty string in C# too.Albania
found the solution to the problem described above: #12734583Albania
I copy/pasted this and I 'hit' the method but the model.Name is null (as are the Roles) I am using .NET Core - is there a setting I have to change?Fraenum
@RuneJeppesen I know, it's late, but for everyone else wondering how to get it work in ASP.NET Core, simply add [FromBody] to your Model parameter: public ActionResult AddUser([FromBody] PersonModel model).Underwrite
can you tell me what change will be required if in your example instead of POST I want to use a GET in the ajax call.Edelman
I was having trouble getting it to bind. Turns out I had forgotten to make my class members public.Stylographic
K
15

There are a couple issues here. First, you need to make sure to bind your JSON object back to the model in the controller. This is done by changing

data: JSON.stringify(usersRoles),

to

data: { model: JSON.stringify(usersRoles) },

Secondly, you aren't binding types correctly with your jquery call. If you remove

contentType: "application/json; charset=utf-8",

it will inherently bind back to a string.

All together, use the first ActionResult method and the following jquery ajax call:

    jQuery.ajax({
        type: "POST",
        url: "@Url.Action("AddUser")",
        dataType: "json",
        data: { model: JSON.stringify(usersRoles) },
        success: function (data) { alert(data); },
        failure: function (errMsg) {
        alert(errMsg);
        }
   });
Knapweed answered 5/2, 2014 at 13:48 Comment(1)
This worked for me, I got rid of the stringify as it put quotes around my string but when I didn't call stringify it came in without the quotes to the controller. This allowed me to get a string into my controller with a post. This gets my upvote.Leroi
I
4

You are sending a array of string

var usersRoles = [];
jQuery("#dualSelectRoles2 option").each(function () {
    usersRoles.push(jQuery(this).val());
});   

So change model type accordingly

 public ActionResult AddUser(List<string> model)
 {
 }
Impatience answered 5/2, 2014 at 13:54 Comment(4)
so you are saying I should not jsonify the data?Rolo
@Zapnologica, data: JSON.stringify(usersRoles) is correct only, you need that. Your ajax code is perfect. But your action method expects a dictionary parameter, but you are sending a array of string :)Impatience
I tried List<String> model and it receives a nullRolo
@Zapnologica, can you look the ajax request with the help of Firebug for firefox or chrome and can you paste your post data to server here?Impatience
J
4

fwiw, this didn't work for me until I had this in the ajax call:

contentType: "application/json; charset=utf-8",

using Asp.Net MVC 4.

Jovitta answered 13/12, 2016 at 22:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.