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