Posting JSON Data to ASP.NET MVC

Posting JSON Data to ASP.NET MVC

Take a look at Phil Haack's post on model binding JSON data. The problem is that the default model binder doesn't serialize JSON properly. You need some sort of ValueProvider OR you could write a custom model binder:

using System.IO;
using System.Web.Script.Serialization;

public class JsonModelBinder : DefaultModelBinder {
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) {
if(!IsJSONRequest(controllerContext)) {
return base.BindModel(controllerContext, bindingContext);
}

// Get the JSON data that's been posted
var request = controllerContext.HttpContext.Request;
//in some setups there is something that already reads the input stream if content type = 'application/json', so seek to the begining
request.InputStream.Seek(0, SeekOrigin.Begin);
var jsonStringData = new StreamReader(request.InputStream).ReadToEnd();

// Use the built-in serializer to do the work for us
return new JavaScriptSerializer()
.Deserialize(jsonStringData, bindingContext.ModelMetadata.ModelType);

// -- REQUIRES .NET4
// If you want to use the .NET4 version of this, change the target framework and uncomment the line below
// and comment out the above return statement
//return new JavaScriptSerializer().Deserialize(jsonStringData, bindingContext.ModelMetadata.ModelType);
}

private static bool IsJSONRequest(ControllerContext controllerContext) {
var contentType = controllerContext.HttpContext.Request.ContentType;
return contentType.Contains("application/json");
}
}

public static class JavaScriptSerializerExt {
public static object Deserialize(this JavaScriptSerializer serializer, string input, Type objType) {
var deserializerMethod = serializer.GetType().GetMethod("Deserialize", BindingFlags.NonPublic | BindingFlags.Static);

// internal static method to do the work for us
//Deserialize(this, input, null, this.RecursionLimit);

return deserializerMethod.Invoke(serializer,
new object[] { serializer, input, objType, serializer.RecursionLimit });
}
}

And tell MVC to use it in your Global.asax file:

ModelBinders.Binders.DefaultBinder = new JsonModelBinder();

Also, this code makes use of the content type = 'application/json' so make sure you set that in jquery like so:

$.ajax({
dataType: "json",
contentType: "application/json",
type: 'POST',
url: '/Controller/Action',
data: { 'items': JSON.stringify(lineItems), 'id': documentId }
});

Posting JSON to controller MVC 5

You cannot possibly expect to map this complex JSON structure to a list of strings (List<String>) that your controller action currently takes as parameter:

[{"Raw Material Name":"Asphalt","Short Code":"AS02","Price":"20"}]

So you may start by defining the appropriate view models that will reflect this structure (or almost, see the massaging technique required below):

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

public string ShortCode { get; set; }

public decimal Price { get; set; }
}

which your controller action will take as parameter:

public ActionResult insertRawMaterial(IList<MaterialViewModel> data)
{
...
}

and finally massage your data on the client to match the correct property names (name, shortCode and price of course):

// we need to massage the raw data as it is crap with property names
// containing spaces and galaxies and stuff
var massagedRawMaterials = [];

for (var i = 0; i < rawMaterials.length; i++) {
var material = rawMaterials[i];
massagedRawMaterials.push({
name: material['Raw Material Name'],
shortCode: material['Short Code'],
price: material['Price']
});
}

$.ajax({
url: "/Supplies/insertRawMaterial",
type: "POST",
data: JSON.stringify(massagedRawMaterials),
contentType: "application/json; charset=utf-8",
...

This being said, if the client side library you are currently using produces such undeterministic property names, you might consider replacing it with something more appropriate.

How do you post a JSON file to an ASP.NET MVC Action?

You need to set the HTTP Header, accept, to 'application/json' so that MVC know that you as passing JSON and does the work to interpret it.

accept: application/json

see more info here: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

UPDATE: Working sample code using MVC3 and jQuery

Controller Code

namespace MvcApplication1.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}

[HttpPost]
public JsonResult PostUser(UserModel data)
{
// test here!
Debug.Assert(data != null);
return Json(data);
}
}

public class UserModel
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}
}

View Code

@{ ViewBag.Title = "Index"; }
<script src="../../Scripts/jquery-1.9.1.min.js"></script>
<script type="text/javascript">
var sample = {};
sample.postData = function () {
$.ajax({
type: "POST", url: "@Url.Action("PostUser")",
success: function (data) { alert('data: ' + data); },
data: JSON.stringify({ "firstName": "Some Name", "lastName": "Some Last Name", "age": "30" }),
accept: 'application/json'
});
};
$(document).ready(function () {
sample.postData();
});
</script>

<h2>Index</h2>

** Update **
I added JSON.stringify to the JS object before I pass it to the data element in the AJAX Request. This just makes the payload more readable, however the Controller will interpret both formats of the data similarly.

How to post JSON data from ASP.Net MVC controller?

After sending JSON with PostMan I was able to create classes for the JSON request as well as the response. All I had to do next, is add a class which I called Service. In this class, which has an integer and the url of the JSON server as attributes, I add all my functions to call the API. The integer represents the ID of the request and the url will be used in every function.

Now Here is what really matters.
The following code is for making a Login using credentials from the remote device and sending user input in JSON data:

public Response Login(String usr, String pwd)
{
this.MyId++;
Request model = new Request(id, usr, pwd);
var http = (HttpWebRequest)WebRequest.Create(uri);
http.Accept = "application/json";
http.ContentType = "application/json";
http.Method = "POST";
String json = Newtonsoft.Json.JsonConvert.SerializeObject(model);
UTF8Encoding encoding = new UTF8Encoding();
Byte[] bytes = encoding.GetBytes(json);

Stream newStream = http.GetRequestStream();
newStream.Write(bytes, 0, bytes.Length);
newStream.Close();

var response = http.GetResponse();

var stream = response.GetResponseStream();
var sr = new StreamReader(stream);
var content = sr.ReadToEnd();
Response res= Newtonsoft.Json.JsonConvert.DeserializeObject<Response>(content.ToString());
return res;

}

As you notice here, we create an instance of a c# class called Request. This class is then serialized into JSON string. The JSON string is then put into the stream and sent with UTF-8 Encoding. Then we get the response and deserialize it into a c# class which with it we can know if the user was authenticated or not. Based on the result, we can redirect the client to his home page or prompt him to input a correct login and password.

PS This procedure is totally CORS free. And this way I send and receive data in my server and assess it then send HTML views accordingly. This keeps my requests and the remote device totally hidden.

Posting json string to c# mvc method

A better approach would be to take advantage of the model binding instead of trying to post and parse the JSON yourself.

Create a model of the items to be sent

public class ItemModel {
//...include the desired properties

public string Description { get; set; }
public string Name { get; set; }
public decimal TotalPrice { get; set; }

//...
}

next update the action to expect the items

[HttpPost]
public IActionResult PersistSelections([FromBody] ItemModel[] items) {
//access posted items
}

and lastly update the client to post the json data

$.ajax({
url: "/Home/PersistSelections",
type: 'post',
contentType: "application/json; charset=utf-8",
dataType: 'json',
data: JSON.stringify(selectedItems)
})

The framework's built in model binder should parse and bind the posted JSON and populate the objects in the controller

How to: (a) send JSON data from the browser to the controller; and (b) send the transformed data to SQL Server within ASP.NET MVC?

Although there are plenty of questions related to this, the answers to those typically refer to binding to a model instead of just the json string. But those will also help you.

It looks like there are two things:

  1. I would change the controller to receive a string instead of an object.
  2. You'll need to update the json data you're passing to the controller to match the parameter name of the controller. So in this case, the controller would receive a parameter named jsonFile. So in the $.ajax method you'll want update the data to something like:
data: { jsonFile: JSON.stringify(myJson) }

UPDATE:


  1. remove the Content-Type of application/json

MVC Controller handle POSTed JSON as a string

ASP.Net Core:

You can declare your controller action argument as object and then call ToString() on it, like this:

[HttpPost]
public IActionResult Foo([FromBody] object arg)
{
var str = arg?.ToString();
...
}

In this example str variable will contain JSON string from a request body.

ASP.Net MVC:

Since the previous option does not work in old ASP.Net MVC, as an option you can read data directly from Request property in your controller's action. The following extension method will help you with it:

public static string GetBody(this HttpRequestBase request)
{
var requestStream = request?.InputStream;
requestStream.Seek(0, System.IO.SeekOrigin.Begin);
using (var reader = new StreamReader(requestStream))
{
return reader.ReadToEnd();
}
}

And your action will look like that:

[HttpPost]
[Route("test")]
public ActionResult Foo()
{
string json = Request.GetBody();
...
}

Passing JSON to ASP.Net MVC Action

Please check follwing code with error line identified.

var data = [];
var questID = 100;
data.push({ QuestionTypeId: '2', QuestionId: questID, Answer: 'asdff' });
data.push({ QuestionTypeId: '2', QuestionId: questID, Answer: 'asdff' });
data.push({ QuestionTypeId: '2', QuestionId: questID, Answer: 'asdff' });
data.push({ QuestionTypeId: '2', QuestionId: questID, Answer: 'asdff' });

//var items = JSON.stringify(data);
//alert(items);

var items = JSON.stringify(data); // HERE IS THE ERROR

alert(items);

$.ajax({
url: '/Dashboard/CreateAssessment',
data: items,
type: 'POST',
contentType: "application/json; charset=utf-8",
dataType: 'json',
traditional: true,
success: function (response) {
if (response.success) {
swal('Password Changed', response.Message, 'success');
window.location.href = "/Account/Management";
} else {
$("update-password").removeAttr("disabled");
swal('Error', response.Message, 'error');
}
},
error: function (response) {
$("update-password").removeAttr("disabled");
}
});

Please recheck your AssessmentAnswerModel with case sensitive consideration

Please mark as answer if found helpful.

Posting JSON data via jQuery to ASP .NET MVC 4 controller action

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]}


Related Topics



Leave a reply



Submit