Reputation: 1133
I'm having trouble trying to pass a complex JSON object to an MVC 4 controller action. As the JSON content is variable, I don't want MVC to map individual properties/elements of the JSON to parameters in the action method's parameter list. I just want to get the data as a single JSON string parameter in the controller action.
Here's the signature of my action method:
[HttpPost]
[ValidateInput(false)]
public string ConvertLogInfoToXml(string jsonOfLog)
And here's my attempt to post some JSON data, from my browser:
data = {prop: 1, myArray: [1, "two", 3]};
//'data' is much more complicated in my real application
json = {jsonOfLog: data};
$.ajax({
type: 'POST',
url: "Home/ConvertLogInfoToXml",
data: JSON.stringify(json),
success: function (returnPayload) {
console && console.log ("request succeeded");
},
error: function (xhr, ajaxOptions, thrownError) {
console && console.log ("request failed");
},
dataType: "xml",
contentType: "application/json",
processData: false,
async: false
});
When I hit my breakpoint at the beginning of the ConvertLogInfoToXML method, jsonOfLog is null.
If I change what 'json' variable is set to in the JavaScript to have the jsonOfLog property be a simple string, e.g. :
json = { jsonOfLog: "simple string" };
then when my breakpoint at the beginning of the ConvertLogInfoToXML method is hit, jsonOfLog is the value of the string (e.g. "simple string").
I tried changing the type of the jsonOfLog parameter in the action method to be of type object:
[HttpPost]
[ValidateInput(false)]
public string ConvertLogInfoToXml(object jsonOfLog)
Now, with the original JavaScript code (where I'm passing a more complex 'data' object), jsonOfLog gets the value of {object}. But the debugger doesn't show any more details in a watch window, and I don't know what methods I can use to operate on this variable.
How do I pass JSON data to a MVC controller, where the data passed is a stringified complex object?
Thanks, Notre
Upvotes: 28
Views: 117605
Reputation: 5544
//simple json object in asp.net mvc
var model = {"Id": "xx", "Name":"Ravi"};
$.ajax({ url: 'test/[ControllerName]',
type: "POST",
data: model,
success: function (res) {
if (res != null) {
alert("done.");
}
},
error: function (res) {
}
});
//model in c#
public class MyModel
{
public string Id {get; set;}
public string Name {get; set;}
}
//controller in asp.net mvc
public ActionResult test(MyModel model)
{
//now data in your model
}
Upvotes: 1
Reputation: 4150
Okay, so I have just spent several hours looking for a viable method for posting multiple parameters to an MVC 4 WEB API, but most of what I found was either for a 'GET' action or just flat out did not work. However, I finally got this working and I thought I'd share my solution.
Use NuGet packages to download JSON-js json2
and Json.NET
. Steps to install NuGet packages:
(1) In Visual Studio, go to Website > Manage NuGet Packages...
(2) Type json (or something to that effect) into the search bar and find JSON-js json2
and Json.NET
. Double-clicking them will install the packages into the current project.
(3) NuGet will automatically place the json file in ~/Scripts/json2.min.js
in your project directory. Find the json2.min.js file and drag/drop it into the head of your website. Note: for instructions on installing .js (javascript) files, read this solution.
Create a class object containing the desired parameters. You will use this to access the parameters in the API controller. Example code:
Public Class PostMessageObj
Private _body As String
Public Property body As String
Get
Return _body
End Get
Set(value As String)
_body = value
End Set
End Property
Private _id As String
Public Property id As String
Get
Return _id
End Get
Set(value As String)
_id = value
End Set
End Property
End Class
Then we setup the actual MVC 4 Web API controller that we will be using for the POST action. In it, we will use Json.NET to deserialize the string object when it is posted. Remember to use the appropriate namespaces. Continuing with the previous example, here is my code:
Public Sub PostMessage(<FromBody()> ByVal newmessage As String)
Dim t As PostMessageObj = Newtonsoft.Json.JsonConvert.DeserializeObject(Of PostMessageObj)(newmessage)
Dim body As String = t.body
Dim i As String = t.id
End Sub
Now that we have our API controller set up to receive our stringified JSON object, we can call the POST action freely from the client-side using $.ajax; Continuing with the previous example, here is my code (replace localhost+rootpath appropriately):
var url = 'http://<localhost+rootpath>/api/Offers/PostMessage';
var dataType = 'json'
var data = 'nothn'
var tempdata = { body: 'this is a new message...Ip sum lorem.',
id: '1234'
}
var jsondata = JSON.stringify(tempdata)
$.ajax({
type: "POST",
url: url,
data: { '': jsondata},
success: success(data),
dataType: 'text'
});
As you can see we are basically building the JSON object, converting it into a string, passing it as a single parameter, and then rebuilding it via the JSON.NET framework. I did not include a return value in our API controller so I just placed an arbitrary string value in the success()
function.
This was done in Visual Studio 2010 using ASP.NET 4.0, WebForms, VB.NET, and MVC 4 Web API Controller. For anyone having trouble integrating MVC 4 Web API with VS2010, you can download the patch to make it possible. You can download it from Microsoft's Download Center.
Here are some additional references which helped (mostly in C#):
Upvotes: 2
Reputation: 5637
Well my client side (a cshtml file) was using DataTables to display a grid (now using Infragistics control which are great). And once the user clicked on the row, I captured the row event and the date associated with that record in order to go back to the server and make additional server-side requests for trades, etc. And no - I DID NOT stringify it...
The DataTables def started as this (leaving lots of stuff out), and the click event is seen below where I PUSH onto my Json object :
oTablePf = $('#pftable').dataTable({ // INIT CODE
"aaData": PfJsonData,
'aoColumnDefs': [
{ "sTitle": "Pf Id", "aTargets": [0] },
{ "sClass": "**td_nodedate**", "aTargets": [3] }
]
});
$("#pftable").delegate("tbody tr", "click", function (event) { // ROW CLICK EVT!!
var rownum = $(this).index();
var thisPfId = $(this).find('.td_pfid').text(); // Find Port Id and Node Date
var thisDate = $(this).find('.td_nodedate').text();
//INIT JSON DATA
var nodeDatesJson = {
"nodedatelist":[]
};
// omitting some code here...
var dateArry = thisDate.split("/");
var nodeDate = dateArry[2] + "-" + dateArry[0] + "-" + dateArry[1];
nodeDatesJson.nodedatelist.push({ nodedate: nodeDate });
getTradeContribs(thisPfId, nodeDatesJson); // GET TRADE CONTRIBUTIONS
});
Upvotes: 0
Reputation: 10515
The problem is your dataType
and the format of your data
parameter. I just tested this in a sandbox and the following works:
C#
[HttpPost]
public string ConvertLogInfoToXml(string jsonOfLog)
{
return Convert.ToString(jsonOfLog);
}
javascript
<input type="button" onclick="test()"/>
<script type="text/javascript">
function test() {
data = { prop: 1, myArray: [1, "two", 3] };
//'data' is much more complicated in my real application
var jsonOfLog = JSON.stringify(data);
$.ajax({
type: 'POST',
dataType: 'text',
url: "Home/ConvertLogInfoToXml",
data: "jsonOfLog=" + jsonOfLog,
success: function (returnPayload) {
console && console.log("request succeeded");
},
error: function (xhr, ajaxOptions, thrownError) {
console && console.log("request failed");
},
processData: false,
async: false
});
}
</script>
Pay special attention to data
, when sending text, you need to send a variable that matches the name of your parameter. It's not pretty, but it will get you your coveted unformatted string.
When running this, jsonOfLog looks like this in the server function:
jsonOfLog "{\"prop\":1,\"myArray\":[1,\"two\",3]}" string
The HTTP POST header:
Key Value
Request POST /Home/ConvertLogInfoToXml HTTP/1.1
Accept text/plain, */*; q=0.01
Content-Type application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With XMLHttpRequest
Referer http://localhost:50189/
Accept-Language en-US
Accept-Encoding gzip, deflate
User-Agent Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)
Host localhost:50189
Content-Length 42
DNT 1
Connection Keep-Alive
Cache-Control no-cache
Cookie EnableSSOUser=admin
The HTTP POST body:
jsonOfLog={"prop":1,"myArray":[1,"two",3]}
The response header:
Key Value
Cache-Control private
Content-Type text/html; charset=utf-8
Date Fri, 28 Jun 2013 18:49:24 GMT
Response HTTP/1.1 200 OK
Server Microsoft-IIS/8.0
X-AspNet-Version 4.0.30319
X-AspNetMvc-Version 4.0
X-Powered-By ASP.NET
X-SourceFiles =?UTF-8?B?XFxwc2ZcaG9tZVxkb2N1bWVudHNcdmlzdWFsIHN0dWRpbyAyMDEyXFByb2plY3RzXE12YzRQbGF5Z3JvdW5kXE12YzRQbGF5Z3JvdW5kXEhvbWVcQ29udmVydExvZ0luZm9Ub1htbA==?=
The response body:
{"prop":1,"myArray":[1,"two",3]}
Upvotes: 24
Reputation: 867
I think you'll find your answer if you refer to this post: Deserialize JSON into C# dynamic object?
There are various ways of achieving what you want here. The System.Web.Helpers.Json approach (a few answers down) seems to be the simplest.
Upvotes: 2
Reputation: 5637
Some months ago I ran into an odd situation where I also needed to send some Json-formatted date back to my controller. Here's what I came up with after pulling my hair out:
My class looks like this :
public class NodeDate
{
public string nodedate { get; set; }
}
public class NodeList1
{
public List<NodeDate> nodedatelist { get; set; }
}
and my c# code as follows :
public string getTradeContribs(string Id, string nodedates)
{
//nodedates = @"{""nodedatelist"":[{""nodedate"":""01/21/2012""},{""nodedate"":""01/22/2012""}]}"; // sample Json format
System.Web.Script.Serialization.JavaScriptSerializer ser = new System.Web.Script.Serialization.JavaScriptSerializer();
NodeList1 nodes = (NodeList1)ser.Deserialize(nodedates, typeof(NodeList1));
string thisDate = "";
foreach (var date in nodes.nodedatelist)
{ // iterate through if needed...
thisDate = date.nodedate;
}
}
and so I was able to Deserialize my nodedates Json object parameter in the "nodes" object; naturally of course using the class "NodeList1" to make it work.
I hope this helps.... Bob
Upvotes: 0