Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Web API POST parameter is null

(To clarify, I have read other questions and their answers and tried all solutions, but none of them solved the issue)

I'm debugging locally a code that I'll deploy to Windows Azure Cloud Services. It's an ASP.NET Web API application that was working just a few days ago, but not anymore.

I have a controller with both GET and POST handlers. The GET handler works fine and returns the desired result, however the POST handler is not able to get the parameters from the POST body request. This handler was working just fine a few builds ago (~2 days ago), however it's not working now. Here are the details:

First, both GET and POST handlers:

public class PlayerController : ApiController
{
    [HttpGet]
    public HttpResponseMessage Information(string userID)
    {
        // Works fine!
    }

    [HttpPost]
    public HttpResponseMessage Insert(PlayerEntry entry)
    {
        // All values from entry are null or 0!
    }
}

This is the PlayerEntry model:

public class PlayerEntry
{
    public string userID;
    public string userName;
    public int userProgress;
}

This is the POST request being made (taken from Fiddler):

POST http://127.0.0.1/api/player/insert HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Content-Length: 80
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache

userID=20&userName=Test&userProgress=9

And this is the Debug Output in the server:

iisexpress.exe Information: 0 : Request, Method=POST, Url=http://127.0.0.1:81/api/player/insert, Message='http://127.0.0.1:81/api/player/insert'
iisexpress.exe Information: 0 : Message='Player', Operation=DefaultHttpControllerSelector.SelectController
iisexpress.exe Information: 0 : Message='MvcWebRole1.Controllers.PlayerController', Operation=DefaultHttpControllerActivator.Create
iisexpress.exe Information: 0 : Message='MvcWebRole1.Controllers.PlayerController', Operation=HttpControllerDescriptor.CreateController
iisexpress.exe Information: 0 : Message='Selected action 'Insert(PlayerEntry entry)'', Operation=ApiControllerActionSelector.SelectAction
iisexpress.exe Information: 0 : Message='Value read='MvcWebRole1.Models.PlayerEntry'', Operation=JQueryMvcFormUrlEncodedFormatter.ReadFromStreamAsync
iisexpress.exe Information: 0 : Message='Parameter 'entry' bound to the value 'MvcWebRole1.Models.PlayerEntry'', Operation=FormatterParameterBinding.ExecuteBindingAsync
iisexpress.exe Information: 0 : Message='Model state is valid. Values: entry=MvcWebRole1.Models.PlayerEntry', Operation=HttpActionBinding.ExecuteBindingAsync
iisexpress.exe Information: 0 : Message='Action returned 'StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.StringContent, Headers:
{
  Content-Type: text/plain; charset=utf-8
}'', Operation=ReflectedHttpActionDescriptor.ExecuteAsync
iisexpress.exe Information: 0 : Operation=ApiControllerActionInvoker.InvokeActionAsync, Status=200 (OK)
iisexpress.exe Information: 0 : Operation=PlayerController.ExecuteAsync, Status=200 (OK)
iisexpress.exe Information: 0 : Response, Status=200 (OK), Method=POST, Url=http://127.0.0.1:81/api/player/insert, Message='Content-type='text/plain; charset=utf-8', content-length=0'
iisexpress.exe Information: 0 : Operation=PlayerController.Dispose

So far, these are the things I've tried that didn't change anything:

  • Add a "=" in the beginning of the POST body (just to be sure it wouldn't work)
  • Add a [FromBody] before PlayerEntry entry in the Insert() function
  • Try testing any other POST handler I have in other controllers (none of them work!)

However, when I simply remove the PlayerEntry model and get the POST parameters from the URL (and send the parameters through the URL. I did that only as a test), I can get all the parameters without problems.

What could be causing the issue here? I did not change any code in the handlers as far as I remember (only code that runs internally and connects to an SQL Server and returns results), and all of a sudden I got this problem.

like image 938
Bernardo Avatar asked Jan 10 '14 03:01

Bernardo


Video Answer


2 Answers

I believe the default model binder does not bind to fields, only properties with a public setter. Try changing your fields to properties:

public class PlayerEntry
{
    public string userID { get; set; }
    public string userName { get; set; }
    public int userProgress { get; set; }
}
like image 197
lc. Avatar answered Oct 19 '22 23:10

lc.


For what it's worth, I got sick of trying to get it to serialize correctly and did it myself.

My data is a javascript array of strings which posts like "value=thing1,thing2,thing3" and I was able to serialize it using the following:

    $('<form>', {
        "id": "dynamicForm",
        "html": '<input type="hidden" id="val" name="val" value="' + $scope.items + '" />',
        "action": '/api/Example/',
        "method": "post"
    }).appendTo(document.body).submit();

Then on the server side:

[HttpPost]
[Route("")]
public HttpResponseMessage Post()
{
    var values = HttpContext.Current.Server.UrlDecode(Request.Content.ReadAsStringAsync().Result).Replace("val=","").Split(',');
...
}
like image 32
Scott R. Frost Avatar answered Oct 20 '22 01:10

Scott R. Frost