How to Pass JSON Post Data to Web API Method as an Object

How to pass json POST data to Web API method as an object?

EDIT : 31/10/2017

The same code/approach will work for Asp.Net Core 2.0 as well. The major difference is, In asp.net core, both web api controllers and Mvc controllers are merged together to single controller model. So your return type might be IActionResult or one of it's implementation (Ex :OkObjectResult)


Use

contentType:"application/json"

You need to use JSON.stringify method to convert it to JSON string when you send it,

And the model binder will bind the json data to your class object.

The below code will work fine (tested)

$(function () {
var customer = {contact_name :"Scott",company_name:"HP"};
$.ajax({
type: "POST",
data :JSON.stringify(customer),
url: "api/Customer",
contentType: "application/json"
});
});

Result

Sample Image

contentType property tells the server that we are sending the data in JSON format. Since we sent a JSON data structure,model binding will happen properly.

If you inspect the ajax request's headers, you can see that the Content-Type value is set as application/json.

If you do not specify contentType explicitly, It will use the default content type which is application/x-www-form-urlencoded;


Edit on Nov 2015 to address other possible issues raised in comments

Posting a complex object

Let's say you have a complex view model class as your web api action method parameter like this

public class CreateUserViewModel
{
public int Id {set;get;}
public string Name {set;get;}
public List<TagViewModel> Tags {set;get;}
}
public class TagViewModel
{
public int Id {set;get;}
public string Code {set;get;}
}

and your web api end point is like

public class ProductController : Controller
{
[HttpPost]
public CreateUserViewModel Save([FromBody] CreateUserViewModel m)
{
// I am just returning the posted model as it is.
// You may do other stuff and return different response.
// Ex : missileService.LaunchMissile(m);
return m;
}
}

At the time of this writing, ASP.NET MVC 6 is the latest stable version and in MVC6, Both Web api controllers and MVC controllers are inheriting from Microsoft.AspNet.Mvc.Controller base class.

To send data to the method from client side, the below code should work fine

//Build an object which matches the structure of our view model class
var model = {
Name: "Shyju",
Id: 123,
Tags: [{ Id: 12, Code: "C" }, { Id: 33, Code: "Swift" }]
};

$.ajax({
type: "POST",
data: JSON.stringify(model),
url: "../product/save",
contentType: "application/json"
}).done(function(res) {
console.log('res', res);
// Do something with the result :)
});

Model binding works for some properties, but not all ! Why ?

If you do not decorate the web api method parameter with [FromBody] attribute

[HttpPost]
public CreateUserViewModel Save(CreateUserViewModel m)
{
return m;
}

And send the model(raw javascript object, not in JSON format) without specifying the contentType property value

$.ajax({
type: "POST",
data: model,
url: "../product/save"
}).done(function (res) {
console.log('res', res);
});

Model binding will work for the flat properties on the model, not the properties where the type is complex/another type. In our case, Id and Name properties will be properly bound to the parameter m, But the Tags property will be an empty list.

The same problem will occur if you are using the short version, $.post which will use the default Content-Type when sending the request.

$.post("../product/save", model, function (res) {
//res contains the markup returned by the partial view
console.log('res', res);
});

Pass JSON object to WebApi

Will take only one minute, give this a try:

$.post("api/registration",
registrationData,
function (value) {
$('#registrationMessage').append(value);
},
"json"
);

How to pass JSON as parameter to Post method in controller .net api

When you are checking if device if exist you are using a wrong Id, you have to use DeviceId instead

 var exist = deviceContext.Devices.Any(i=> i.Id==deviceData.DeviceId);

if (!exist) return BadRequest(Messages.DeviceNotExist);

and IMHO, replace

 deviceContext.DeviceData.Add(new DeviceData
{
Timestamp = DateTime.Now,
Latitude = deviceData.Latitude,
Longitude = deviceData.Longitude,
Altitude = deviceData.Altitude,
Speed = deviceData.Speed,
DeviceId = deviceData.DeviceId
});

with

 deviceData.Timestamp = DateTime.Now;
deviceContext.DeviceData.Add(deviceData);

Passing JSON Object to GET Method - ASP.Net ApiController

Change [HttpGet] to [HttpPost]. GET's can't have a [FromBody] parameter:

[Route("file")]
[HttpPost]
public async Task<IHttpActionResult> DownloadFile([FromBody] UriWeb uri){...}

If you have to use GET, then you need to pass it as a Query String. So you would change it to:

[Route("file")]
[HttpGet]
public async Task<IHttpActionResult> DownloadFile([FromQuery] Uri uri){...}

And then call it as so (query string has been encoded):

http://example.com/api/file?uri=http%3A%2F%2Fexample.com%2Ffile.zip

Post JSON data to web API using object in C#

Thanks to Mason! I wrote the code to POST the data to the web API using HttpWebRequest.

Main

static void Main(string[] args) 
{
string patientServiceResponse = PostRequest( string.Format("https://url.com/api/{0}/{1}/taskOrders", 3345, "1V34858493"));

Debug.Write(patientServiceResponse);
}

POST

private static string PostRequest(string url)
{
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url);
httpWebRequest.ContentType = "application/json; charset=utf-8";
httpWebRequest.Method = "POST";

using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
{
string json = "[ { \"ReferenceId\": \"a123\" } ]";
Debug.Write(json);
streamWriter.Write(json);
streamWriter.Flush();
streamWriter.Close();
}
try
{
using (var response = httpWebRequest.GetResponse() as HttpWebResponse)
{
if (httpWebRequest.HaveResponse && response != null)
{
using (var reader = new StreamReader(response.GetResponseStream()))
{
result = reader.ReadToEnd();
}
}
}
}
catch (WebException e)
{
if (e.Response != null)
{
using (var errorResponse = (HttpWebResponse)e.Response)
{
using (var reader = new StreamReader(errorResponse.GetResponseStream()))
{
string error = reader.ReadToEnd();
result = error;
}
}

}
}

return result;

}

Post json data in body to web api

WebAPI is working as expected because you're telling it that you're sending this json object:

{ "username":"admin", "password":"admin" }

Then you're asking it to deserialize it as a string which is impossible since it's not a valid JSON string.

Solution 1:

If you want to receive the actual JSON as in the value of value will be:

value = "{ \"username\":\"admin\", \"password\":\"admin\" }"

then the string you need to set the body of the request in postman to is:

"{ \"username\":\"admin\", \"password\":\"admin\" }"

Solution 2 (I'm assuming this is what you want):

Create a C# object that matches the JSON so that WebAPI can deserialize it properly.

First create a class that matches your JSON:

public class Credentials
{
[JsonProperty("username")]
public string Username { get; set; }

[JsonProperty("password")]
public string Password { get; set; }
}

Then in your method use this:

[Route("api/account/GetToken/")]
[System.Web.Http.HttpPost]
public HttpResponseBody GetToken([FromBody] Credentials credentials)
{
string username = credentials.Username;
string password = credentials.Password;
}

Posting JSON object via AJAX to ASP.NET Core Web API

I opened the Network tab and I got this: I got a 404 (kind of
expected that) , the name of the method 'save' , a type of 'xhr' and a
size of 45B.

The 404 error obviously means the url/routing is wrong. Here to solve it ,you have two ways to achieve.

First way:

You can change url to "api/shopping" in ajax as follow:

        $.ajax({
type: "POST",
data: JSON.stringify(shoppingCart),
url: "api/shopping",
contentType: "application/json charset=utf-8",
}).done(function (res) {
alert(res);
})

Second way:

You can change the path name
of Save action by Attribute routing with Http verb attributes as follow:

            [Route("api/Shopping")]
[ApiController]
public class ShoppingCartController : ControllerBase
{
[HttpPost("Save")]
public ShoppingCart Save([FromBody] ShoppingCart s)
{

return s;
}
}

Update

According to your comment, in addition to the above updates, you also need to modify the routing settings as follows:

 app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});

Debug result:

Sample Image



Related Topics



Leave a reply



Submit