Gašper Sladič
Gašper Sladič

Reputation: 897

ASP.NET mvc 4 controller parameter always null when sending json to controller, why?

There are some similar posts already here, and tried every solution suggested, and still does not work... I can not get value inside controller, it is always null. Below is the code. Am I missing something?

Client side javascript

   function getChart() {
       JSONString3 = { HAxis : [{ Name : "monday" }] };
       jQuery.ajaxSettings.traditional = true;
        $.ajax({
            url: "@Url.Action("getChart","SBM")",
            type: 'POST',
            contentType: 'json',
            dataType: 'html',
            data: JSONString3,
            success: function (data) {
                var imagestring = btoa(data);
                $('#ChartImage').attr('src', "data:image/png;base64," + imagestring + "?" + new       Date().getTime());
            }
        })
        jQuery.ajaxSettings.traditional = false;
    }

MVC Controller

    [Authorize]
    [HttpPost]
    public ActionResult getChart(YAxis HAxis)
    {
        YAxis XAxisvalue = HAxis;
        Charts chart = new Charts();
        MemoryStream ms = new MemoryStream();
        chart.Chart.SaveImage(ms);
        string image = Convert.ToBase64String(ms.GetBuffer());
        return File(ms.GetBuffer(), "image/png", "Chart.png");
    }

Model

public class YAxis
{
    public string Name { get; set; }
}

Upvotes: 15

Views: 25962

Answers (5)

live-love
live-love

Reputation: 52534

I had same problem (parameter always null), but my solution was different.

Make sure that your ActionResult method parameter doesn't have the same name as the JSON object property.

In this example I renamed myParam to myNewParam to differentiate from MyParam property.

Example: This won't work:

    var myObj = {
        ID: '0',
        MyParam: $('#mycontrol').val(),
    }; 

    $.ajax({
        type: "POST",
        url: '@Url.Action("MyAction", "MyModel")',
        cache: false,
        data: JSON.stringify(myObj),
        datatype: 'json',
        contentType: "application/json; charset=utf-8",
        success: function (result) {
        }
    })

[HttpPost]
        public ActionResult MyAction(Class1 myParam)

This will work:

    var myObj = {
        ID: '0',
        MyParam: $('#mycontrol').val(),
    }; 

    $.ajax({
        type: "POST",
        url: '@Url.Action("MyAction", "MyModel")',
        cache: false,
        data: JSON.stringify(myObj),
        datatype: 'json',
        contentType: "application/json; charset=utf-8",
        success: function (result) {
        }
    })

[HttpPost]
        public ActionResult MyAction(Class1 myNewParam) -->renamed

Upvotes: 3

user3307830
user3307830

Reputation: 1

Adding a datatype attribute to the controller method solved it for me.

[JsonFilter(Param="yourParamName", JsonDataType=typeof(YourParamType))]
[HttpPost]
public ActionResult yourFunction(YourParamType YourParamName)
{
    //do some stuff
}

Upvotes: -1

Gašper Sladič
Gašper Sladič

Reputation: 897

Thank you guys for the directions and solutions. The solution is a combination of all of your suggestions, so I decided to round it up in one post.

Solution to the problem is as follows:

  1. contentType should be application/json (as Ant P suggested above)
  2. json data should be in form of JSONString3 = {"Name" : "monday" } (as Ant P suggested above)
  3. before sending to controller, json should be stringifyed as follows: JSONString3 = JSON.stringify(JSONString3) (as Quan suggested)

Client side javascript

function getChart() {
               JSONString3 = { "Name" : "monday" };
               jQuery.ajaxSettings.traditional = true;
                $.ajax({
                    url: "@Url.Action("getChart","SBM")",
                    type: 'POST',
                    contentType: 'application/json',
                    dataType: 'html',
                    data: JSON.stringify(JSONString3),
                    success: function (data) {
                        var imagestring = btoa(data);
                        $('#ChartImage').attr('src', "data:image/png;base64," + imagestring + "?" + new       Date().getTime());
                    }
                })
                jQuery.ajaxSettings.traditional = false;
    }

MVC Controller

[Authorize]
[HttpPost]
public ActionResult getChart(YAxis HAxis)
{
    YAxis XAxisvalue = HAxis;
    Charts chart = new Charts();
    MemoryStream ms = new MemoryStream();
    chart.Chart.SaveImage(ms);
    string image = Convert.ToBase64String(ms.GetBuffer());
    return File(ms.GetBuffer(), "image/png", "Chart.png");
}

Model

public class YAxis
{
    public string Name { get; set; }
}

Instead of this:

JSONString3 = { "Name" : "monday" };

we can do this:

var JSONString3 = {};
JSONString.Name = "monday";

But we still need to stringify object before posting to controller!!!

To pass multiple objects to controller, below is the example

Client side javascript

   function getChart() {

        //first json object
        //note: each object Property name must be the same as it is in the Models classes on    server side
        Category = {};
        Category.Name = "Category1";
        Category.Values = [];
        Category.Values[0] = "CategoryValue1";
        Category.Values[1] = "CategoryValue2";

        //second json object
        XAxis = {};
        XAxis.Name = "XAxis1";
        XAxis.Values = [];
        XAxis.Values[0] = "XAxisValue1";
        XAxis.Values[1] = "XAxisValue2";

        //third json object
        YAxis = {};
        YAxis.Name = "YAxis1";

        //convert all three objects to string
        //note: each object name should be the same as the controller parameter is!!
        var StringToPost = JSON.stringify({CategoryObject : Category, XAxisObject : XAxis, YAxisObject : YAxis});

        $.ajax({
            url: "@Url.Action("getChart","SBM")",
            type: 'POST',
            contentType: "application/json",
            dataType: 'html',
            data: StringToPost,
            success: function (data) {
                var imagestring = btoa(data);
                $('#ChartImage').html(data);
            }
        })
    }

MVC Controller

[HttpPost]
public ActionResult getChart(Category CategoryObject, XAxis XAxisObject, YAxis YAxisObject)
{
    //do some stuff with objects here and return something to client
    return PartialView("_Chart");
}

Category model

public class Category
{
    public string Name { get; set; }
    public List<string> Values { get; set; }
}

XAxis model

public class XAxis
{
    public string Name { get; set; }
    public List<string> Values { get; set; }
}

YAxis model

public class YAxis
{
    public string Name { get; set; }
}

Hope it will help someone to clarify the whole picture!

Upvotes: 23

Quan Truong
Quan Truong

Reputation: 154

JSONString3 = { "Name": "monday" };

You should post it to controller as a string, so use JSON.stringify to convert, i dont know how to use your ajax type, i just know to use $.post... T_T

 $.post('@Url.Action("getChart","SBM")', {yourJson : data:JSON.stringify(JSONString3)} , function(data) {
            if (data.success) {
var imagestring = btoa(data.name);
                $('#ChartImage').attr('src', "data:image/png;base64," + imagestring + "?" + new       Date().getTime());
   }
});

In controller,

    public ActionResult getChart(string yourJson)
        {
         YAxis  yAxis= JsonConvert.DeserializeObject<YAxis>(yourValue);
          //  ....... your code here
          return Json(new{success=true,name=yAxis.Name},JsonRequestBehavior.AllowGet);
        }

** Note : JsonConvert is method of using Newtonsoft.Json; , please add Newtonsoft reference.

Upvotes: 1

Ant P
Ant P

Reputation: 25231

Looks to me like you're trying to pass an array of objects:

JSONString3 = { HAxis : [{ Name : "monday" }] };

When your action only wants one:

public ActionResult getChart(YAxis HAxis)

Maybe you only meant to pass one?

JSONString3 = { "Name": "monday" };

Upvotes: 1

Related Questions