Search code examples
asp.netasp.net-mvcjsonactionmethod

How to receive JSON as an MVC 5 action method parameter


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?


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