Web Api Parameter always null

Why is the parameter always null when I call the below Post method with the below ajax?

public IEnumerable<string> Post([FromBody]string value)
{
    return new string[] { "value1", "value2", value };
}

Here is the call to the Web API method via ajax:

  function SearchText() {
        $("#txtSearch").autocomplete({
            source: function (request, response) {
                $.ajax({
                    type: "POST",
                    contentType: "application/json; charset=utf-8",
                    url: "api/search/",
                    data: "test",
                    dataType: "text",
                    success: function (data) {
                        response(data.d);
                    },
                    error: function (result) {
                        alert("Error");
                    }
                });
            }
        });
    }

$.ajax({
    url: '/api/search',
    type: 'POST',
    contentType: 'application/x-www-form-urlencoded; charset=utf-8',
    data: '=' + encodeURIComponent(request.term),
    success: function (data) {
        response(data.d);
    },
    error: function (result) {
        alert('Error');
    }
});

Basically you can have only one parameter of scalar type which is decorated with the [FromBody] attribute and your request needs to use application/x-www-form-urlencoded and the POST payload should look like this:

=somevalue

Notice that contrary to standard protocols the parameter name is missing. You are sending only the value.

You can read more about how model binding in the Web Api works in this article.

But of course this hacking around is a sick thing. You should use a view model:

public class MyViewModel
{
    public string Value { get; set; }
}

and then get rid of the [FromBody] attribute:

public IEnumerable<string> Post(MyViewModel model)
{
    return new string[] { "value1", "value2", model.Value };
}

and then use a JSON request:

$.ajax({
    url: '/api/search',
    type: 'POST',
    contentType: 'application/json; charset=utf-8',
    data: JSON.stringify({ value: request.term }),
    success: function (data) {
        response(data.d);
    },
    error: function (result) {
        alert('Error');
    }
});

You cannot use a simple type for the [FromBody] attribute with the JSON content type. Although the default in Visual Studio has a string from body this is for the application/x-www-form-urlencoded content type.

Put the string value as a property on a basic model class and the deserialiser will work.

public class SimpleModel()
{
    public string Value {get;set;}
}

public IEnumerable<string> Post([FromBody]SimpleModel model)
{
    return new string[] { "value1", "value2", model.Value };
}

Change the JSON you are sending to:

{"Value":"test"}

whenever we are calling web api action and which take [frombody] parameter then input parameter prefix with = for example

public string GetActiveEvents([FromBody] string XMLRequestString) {
}

to call above web api action

  1. URI

  2. 2.

User-Agent: Fiddler

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

Host: localhost:54702

Content-Length: 936

  1. request body is =data

I hope this will give clear idea.


I've just had a beast of a time with this and .NET Core Web API. So hopefully to save time for someone: The actual problem for me was simple - I wasn't converting to the correct type (Notice @Darins answer uses a VM rather than a string).

The default type in the template is string. I thought because we're sending stringified JSON, we would see a JSON string, but this was not the case. I had to make it the correct type.

E.g. This failed

[EnableCors("AllowAll")]
[HttpPost]
public HttpResponseMessage Post([FromBody]string value)
{
    // Do something with the blog here....

    var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
    return msg;

}

But this worked.

[EnableCors("AllowAll")]
[HttpPost]
public HttpResponseMessage Post([FromBody]Blog value)
{
    // Do something with the blog here....

   var msg = new HttpResponseMessage(System.Net.HttpStatusCode.OK);
  return msg;

}

Ajax Call

function HandleClick() {

    // Warning - ID's should be hidden in a real application 
    //         - or have covering GUIDs.
    var entityData = {
        "blogId": 2,
        "url": "http://myblog.com/blog1",
        "posts": [
        {
            "postId": 3,
            "title": "Post 1-1",
            "content": "This is post 1 for blog 1",
            "blogId": 2
        },
        {
            "postId": 4,
            "title": "Post 1-2",
            "content": "This is post 2 for blog 1",
            "blogId": 2
        }
        ]
    };


    $.ajax({
        type: "POST",
        url: "http://localhost:64633/api/blogs",
        async: true,
        cache: false,
        crossDomain: true,
        data: JSON.stringify(entityData),
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        success: function (responseData, textStatus, jqXHR) {
            var value = responseData;
        },
        error: function (responseData, textStatus, errorThrown) {
            alert('POST failed.');
        }
    });

}