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

ASP.NET MVC4 Web API application defines post method to save customer. Customer is passed in json format in POST request body. Customer parameter in post method contains null values for properties.

How to fix this so that posted data will passed as customer object ?

If possible Content-Type: application/x-www-form-urlencoded should used since I dont know how to change it in javascript method which posts form.

Controller:

public class CustomersController : ApiController {

  public object Post([FromBody] Customer customer)
        {
            return Request.CreateResponse(HttpStatusCode.OK,
            new
            {
                customer = customer
            });
        }
    }
}

public class Customer
    {
        public string company_name { get; set; }
        public string contact_name { get; set; }
     }

Request:

POST http://localhost:52216/api/customers HTTP/1.1
Accept: application/json, text/javascript, */*; q=0.01
X-Requested-With: XMLHttpRequest
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

{"contact_name":"sdfsd","company_name":"ssssd"}

The answer is


Make sure that your WebAPI service is expecting a strongly typed object with a structure that matches the JSON that you are passing. And make sure that you stringify the JSON that you are POSTing.

Here is my JavaScript (using AngluarJS):

$scope.updateUserActivity = function (_objuserActivity) {
        $http
        ({
            method: 'post',
            url: 'your url here',
            headers: { 'Content-Type': 'application/json'},
            data: JSON.stringify(_objuserActivity)
        })
        .then(function (response)
        {
            alert("success");
        })
        .catch(function (response)
        {
            alert("failure");
        })
        .finally(function ()
        {
        });

And here is my WebAPI Controller:

[HttpPost]
[AcceptVerbs("POST")]
public string POSTMe([FromBody]Models.UserActivity _activity)
{
    return "hello";
}

I've just been playing with this and discovered a rather odd result. Say you have public properties on your class in C# like this:

public class Customer
{
    public string contact_name;
    public string company_name;
}

then you must do the JSON.stringify trick as suggested by Shyju and call it like this:

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

However, if you define getters and setters on your class like this:

public class Customer
{
    public string contact_name { get; set; }
    public string company_name { get; set; }
}

then you can call it much more simply:

$.ajax({
    type: "POST",
    data :customer,
    url: "api/Customer"
});

This uses the HTTP header:

Content-Type:application/x-www-form-urlencoded

I'm not quite sure what's happening here but it looks like a bug (feature?) in the framework. Presumably the different binding methods are calling different "adapters", and while the adapter for application/json one works with public properties, the one for form encoded data doesn't.

I have no idea which would be considered best practice though.


Use the JSON.stringify() to get the string in JSON format, ensure that while making the AJAX call you pass below mentioned attributes:

  • contentType: 'application/json'

Below is the give jquery code to make ajax post call to asp.net web api:

_x000D_
_x000D_
var product =_x000D_
    JSON.stringify({_x000D_
        productGroup: "Fablet",_x000D_
        productId: 1,_x000D_
        productName: "Lumia 1525 64 GB",_x000D_
        sellingPrice: 700_x000D_
    });_x000D_
_x000D_
$.ajax({_x000D_
    URL: 'http://localhost/api/Products',_x000D_
    type: 'POST',_x000D_
    contentType: 'application/json',_x000D_
    data: product,_x000D_
    success: function (data, status, xhr) {_x000D_
        alert('Success!');_x000D_
    },_x000D_
    error: function (xhr, status, error) {_x000D_
        alert('Update Error occurred - ' + error);_x000D_
    }_x000D_
});
_x000D_
_x000D_
_x000D_


Working with POST in webapi can be tricky! Would like to add to the already correct answer..

Will focus specifically on POST as dealing with GET is trivial. I don't think many would be searching around for resolving an issue with GET with webapis. Anyways..

If your question is - In MVC Web Api, how to- - Use custom action method names other than the generic HTTP verbs? - Perform multiple posts? - Post multiple simple types? - Post complex types via jQuery?

Then the following solutions may help:

First, to use Custom Action Methods in Web API, add a web api route as:

public static void Register(HttpConfiguration config)
{
    config.Routes.MapHttpRoute(
        name: "ActionApi",
        routeTemplate: "api/{controller}/{action}");
}

And then you may create action methods like:

[HttpPost]
public string TestMethod([FromBody]string value)
{
    return "Hello from http post web api controller: " + value;
}

Now, fire the following jQuery from your browser console

$.ajax({
    type: 'POST',
    url: 'http://localhost:33649/api/TestApi/TestMethod',
    data: {'':'hello'},
    contentType: 'application/x-www-form-urlencoded',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

Second, to perform multiple posts, It is simple, create multiple action methods and decorate with the [HttpPost] attrib. Use the [ActionName("MyAction")] to assign custom names, etc. Will come to jQuery in the fourth point below

Third, First of all, posting multiple SIMPLE types in a single action is not possible. Moreover, there is a special format to post even a single simple type (apart from passing the parameter in the query string or REST style). This was the point that had me banging my head with Rest Clients (like Fiddler and Chrome's Advanced REST client extension) and hunting around the web for almost 5 hours when eventually, the following URL proved to be of help. Will quote the relevant content for the link might turn dead!

Content-Type: application/x-www-form-urlencoded
in the request header and add a = before the JSON statement:
={"Name":"Turbo Tina","Email":"[email protected]"}

PS: Noticed the peculiar syntax?

http://forums.asp.net/t/1883467.aspx?The+received+value+is+null+when+I+try+to+Post+to+my+Web+Api

Anyways, let us get over that story. Moving on:

Fourth, posting complex types via jQuery, ofcourse, $.ajax() is going to promptly come in the role:

Let us say the action method accepts a Person object which has an id and a name. So, from javascript:

var person = { PersonId:1, Name:"James" }
$.ajax({
    type: 'POST',
    url: 'http://mydomain/api/TestApi/TestMethod',
    data: JSON.stringify(person),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function(data){ console.log(data) }
});

And the action will look like:

[HttpPost]
public string TestMethod(Person person)
{
    return "Hello from http post web api controller: " + person.Name;
}

All of the above, worked for me!! Cheers!


Microsoft gave a good example of doing this:

https://docs.microsoft.com/en-us/aspnet/web-api/overview/advanced/sending-html-form-data-part-1

First validate the request

if (ModelState.IsValid)

and than use the serialized data.

Content = new StringContent(update.Status)

Here 'Status' is a field in the complex type. Serializing is done by .NET, no need to worry about that.


@model MVCClient.Models.ProductDetails

@{
    ViewBag.Title = "ProductDetails";
}
<script src="~/Scripts/jquery-1.8.2.min.js"></script>
<script type="text/javascript">

    $(document).ready(function () {
        $("#Save").click(function () {
            var ProductDetails = new Object();
            ProductDetails.ProductName =  $("#txt_productName").val();
            ProductDetails.ProductDetail = $("#txt_desc").val();
            ProductDetails.Price= $("#txt_price").val();
            $.ajax({
                url: "http://localhost:24481/api/Product/addProduct",
                type: "Post",
                dataType:'JSON',
                data:ProductDetails, 

                success: function (data) {
                    alert('Updated Successfully');
                    //window.location.href = "../Index";
                },
                error: function (msg) { alert(msg); }
            });
        });
    });
    </script>
<h2>ProductDetails</h2>

<form id="form1" method="post">
    <fieldset>
        <legend>ProductDetails</legend>


        <div class="editor-label">
            @Html.LabelFor(model => model.ProductName)
        </div>
        <div class="editor-field">

            <input id="txt_productName" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.ProductName)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.ProductDetail)
        </div>
        <div class="editor-field">

            <input id="txt_desc" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.ProductDetail)
        </div>

        <div class="editor-label">
            @Html.LabelFor(model => model.Price)
        </div>
        <div class="editor-field">

            <input id="txt_price" type="text" name="fname">
            @Html.ValidationMessageFor(model => model.Price)
        </div>



        <p>
            <input id="Save" type="button" value="Create" />
        </p>
    </fieldset>

</form>
    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>

</form>



@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
}

Following code to return data in the json format ,instead of the xml -Web API 2 :-

Put following line in the Global.asax file

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
        GlobalConfiguration.Configuration.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);

1)In your client side you can send you http.post request in string like below

var IndexInfo = JSON.stringify(this.scope.IndexTree);
this.$http.post('../../../api/EvaluationProcess/InsertEvaluationProcessInputType', "'" + IndexInfo + "'" ).then((response: any) => {}

2)Then in your web api controller you can deserialize it

public ApiResponce InsertEvaluationProcessInputType([FromBody]string IndexInfo)
    {
var des = (ApiReceivedListOfObjects<TempDistributedIndex>)Newtonsoft.Json.JsonConvert.DeserializeObject(DecryptedProcessInfo, typeof(ApiReceivedListOfObjects<TempDistributedIndex>));}

3)Your ApiReceivedListOfObjects class should be like below

public class ApiReceivedListOfObjects<T>
    {
        public List<T> element { get; set; }

    }

4)make sure that your serialized string (IndexInfo here) becomes like below structure before JsonConvert.DeserializeObject command in step 2

var resp = @"
    {
        ""element"": [
        {
            ""A"": ""A Jones"",
            ""B"": ""500015763""
        },
        {
            ""A"": ""B Smith"",
            ""B"": ""504986213""
        },
        {
            ""A"": ""C Brown"",
            ""B"": ""509034361""
        }
        ]
    }";

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to asp.net-mvc

Using Lato fonts in my css (@font-face) Better solution without exluding fields from Binding Vue.js get selected option on @change You must add a reference to assembly 'netstandard, Version=2.0.0.0 How to send json data in POST request using C# VS 2017 Metadata file '.dll could not be found The default XML namespace of the project must be the MSBuild XML namespace How to create roles in ASP.NET Core and assign them to users? The model item passed into the dictionary is of type .. but this dictionary requires a model item of type How to use npm with ASP.NET Core

Examples related to json

Use NSInteger as array index Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) HTTP POST with Json on Body - Flutter/Dart Importing json file in TypeScript json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 190) Angular 5 Service to read local .json file How to import JSON File into a TypeScript file? Use Async/Await with Axios in React.js Uncaught SyntaxError: Unexpected token u in JSON at position 0 how to remove json object key and value.?

Examples related to asp.net-mvc-4

Better solution without exluding fields from Binding How to remove error about glyphicons-halflings-regular.woff2 not found When should I use Async Controllers in ASP.NET MVC? How to call controller from the button click in asp.net MVC 4 How to get DropDownList SelectedValue in Controller in MVC Return HTML from ASP.NET Web API There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key country Return JsonResult from web api without its properties how to set radio button checked in edit mode in MVC razor view How to call MVC Action using Jquery AJAX and then submit form in MVC?

Examples related to asp.net-web-api

Entity Framework Core: A second operation started on this context before a previous operation completed FromBody string parameter is giving null How to read request body in an asp.net core webapi controller? JWT authentication for ASP.NET Web API Token based authentication in Web API without any user interface Web API optional parameters How do I get the raw request body from the Request.Content object using .net 4 api endpoint How to use a client certificate to authenticate and authorize in a Web API HTTP 415 unsupported media type error when calling Web API 2 endpoint The CodeDom provider type "Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider" could not be located