ASP.NET MVC2 Reading JSON Data with a Controller

I am having problems getting json values โ€‹โ€‹from my javascript / jQuery request for my controller.

MyClass is as follows:

function MyClass() { this.MyString = null; this.MyInt = null; this.Subs = null; } 

My request is as follows:

 var testData1 = new MyClass(); testData1.MyInt = 1234; testData1.MyString = "abcDEF"; testData1.Subs = new Array(); var testData2 = new MyClass(); testData2.MyInt = 5678; testData2.MyString = "GHIjkl"; testData1.Subs.push(testData2); var jsonData = JSON.stringify(testData1); var self = this; $.ajax({ url: '/Home/Request', type: 'POST', dataType: 'json', data: jsonData, contentType: 'application/json; charset=utf-8', success: function (x) { self.ParseResult(x); } }); 

Now I have a controller:

 public JsonResult Request(MyClass myObj) { var answer = ... return Json(answer, JsonRequestBehavior.DenyGet); } 

With the following class:

 public class MyClass { public string MyString { get; set; } public int MyInt { get; set; } public List<MyClass> Subs { get; set; } } 

All names in jsonData are exactly the same as in my "MyClass" class. But there are no values โ€‹โ€‹in myObj.

Where is the problem. Is there anything I can do to correctly display this display?

Thank you very much,

Chris

UPDATE:

Thank you for your cues. I used the JavascriptSerializer. But I have a problem that myString is null:

 public JsonResult Data(string myString) { JavaScriptSerializer serializer = new JavaScriptSerializer(); var data = serializer.Deserialize<MyClass>(myString); var answer = ... return Json(answer, JsonRequestBehavior.DenyGet); } 

Where is the meaning? Should I accept the value from the request data?

@Dave Ward

The second solution works. But I have a problem with submarines.

 var testData1 = new MyClass(); testData1.MyInt = 1234; testData1.MyString = "abcDEF"; testData1.Subs = new Array(); for (var i = 0; i < 10; i++) { var testData2 = new MyClass(); testData2.MyInt = i; testData2.MyString = "abcDEF"; testData1.Subs.push(testData2); } 

I get 10 Subs in my controller, but they are all empty. What can I do?

@Dave Ward, @ALL

Using traditional settings, my 10 Subs bot is empty, they are not there. Counting count is 0 (not NULL). I tried changing the type of Subs from a list to IEnumerable, but that didn't help. Do you know anything else I can do to get Subs populated by my controller?

Ok, thanks Dave Ward, I will use the JSON method.

For someone else having the same problem, this controller code can be obtained with:

 MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(myString)); var serializer = new DataContractJsonSerializer(typeof(MyClass)); MyClass se = serializer.ReadObject(ms) as MyClass; ms.Close(); 
+4
source share
4 answers

Right now you are sending a JSON string as the whole body of your POST. MVC is not able to connect the dots and realize that you want it to contain the entire string as a parameter named myString.

To do this, change the client-side data settings as follows:

 $.ajax({ url: '/Home/Request', type: 'POST', dataType: 'json', data: { myString: jsonData }, contentType: 'application/json; charset=utf-8', success: function (x) { // If ParseResult is some sort of JSON deserializing, don't do that. // When the dataType is set to 'json', jQuery handles this for you // automatically before the success handler is called. self.ParseResult(x); } }); 

When you provide a jQuery object as its data parameter, it automatically URLEncodes, which before sending, then something like this will be sent to the server:

 myString={json:data, here:etc} 

MVC will select this as the myString parameter as desired, and you can continue to deserialize it using the JavaScriptSerializer.

Also, if you are not doing something more complex on the client side than you are showing, a JavaScript class is not needed. Something like this will work:

 var testData2 = { MyInt: 5678, MyString: "GHIjkl", } var testData1 = { MyInt: 1234, MyString: "abcDEF", Subs: [ testData2 ] } 

All that said, why are you using JSON for the request? If you accept a custom type parameter in your action, binding the MVC model pretty well dampens this type with standard URLEncoded input:

 public JsonResult Data(MyClass request) { // request.MyInt, request.MyString, etc should exist here. var answer = ... // It okay to accept URLEncoded input parameters, but still return JSON. return Json(answer, JsonRequestBehavior.DenyGet); } 

Then, to call it, client-side JSON serialization is not required:

 var testData2 = { MyInt: 5678, MyString: "GHIjkl", } var testData1 = { MyInt: 1234, MyString: "abcDEF", Subs: [ testData2 ] } $.ajax({ url: '/Home/Request', type: 'POST', traditional: true, dataType: 'json', data: testData1 success: function (x) { self.ParseResult(x); } }); 

This is a bit simpler and faster since you removed the serialization layer on the client side and deserialized on the server side.

+3
source

In my experience, I have to pass json as a string and then deserialize it. I use Newtonsoft for this.

 public ActionResult DoAjax(string jsonRequest) { JsonSerializer serializer = new JsonSerializer(); StringReader sr = new StringReader(jsonRequest); Newtonsoft.Json.JsonTextReader reader = new JsonTextReader(sr); MyClass obj = (MyClass)serializer.Deserialize(reader, typeof(MyClass)); //...do other stuff } 
+1
source

at a similar level for josh's, you can use json actionfilter a la:

 // requires newtonsoft.json.dll public class JsonFilter : ActionFilterAttribute { public string Param { get; set; } public Type JsonDataType { get; set; } public override void OnActionExecuting(ActionExecutingContext filterContext) { if (filterContext.HttpContext .Request.ContentType.Contains("application/json")) { string inputContent; using (var sr = new StreamReader(filterContext.HttpContext .Request.InputStream)) { inputContent = sr.ReadToEnd(); } var result = JsonConvert.DeserializeObject(inputContent, JsonDataType); filterContext.ActionParameters[Param] = result; } else try { // we should do a loop looking for json here ONLY if there a callback // ie we're calling jsonP if (filterContext.HttpContext.Request.QueryString["callback"] != null) { string inputContent = Enumerable.Where(filterContext.HttpContext .Request.QueryString.Keys.Cast<string>() .Select(qs => filterContext.HttpContext .Request.QueryString[qs]), query => !string.IsNullOrEmpty(query)) .FirstOrDefault(query => query.IndexOf("{") == 0); var result = JsonConvert.DeserializeObject(inputContent, JsonDataType); filterContext.ActionParameters[Param] = result; } } catch (Exception e) { // do nothing filterContext.ActionParameters[Param] = null; } } } 

(in this case typeof (IList)), but can be ANY class, i.e. typeof (myClass):

 [JsonFilter(Param = "jsonData", JsonDataType = typeof(IList<FundPropertyWeekSplit>))] public virtual ActionResult AddFundPropertyWeekSplit(IList<FundPropertyWeekSplit> jsonData) { // code to deal with the newly created strongly typed object } 

I use this (pretty much !!) throughout the store ...

+1
source

You can take a look at an article by Omar Al-Zabir about processing json, xml requests and the answers that he provided a really good solution to solve these common situations.

Create a REST API using ASP.NET MVC that speaks both Json and plain Xml

0
source

Source: https://habr.com/ru/post/1332149/


All Articles