Question

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?

Was it helpful?

Solution

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

OTHER TIPS

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);
        }
   });

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)
 {
 }

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top