1

Simple ApiController method:

public class TestController : ApiController
{
    public void TakeIt(MyObject o){
        Console.Write(o.ToString());
    }
}

Simple data type:

public class MyObject{
    public string V1{ get; set; }
    public string V2{ get; set; }
}

Simple post:

POST http://localhost:11026/api/test/takeit HTTP/1.1
Accept: application/json
Content-Type: application/json
Host: localhost:11026

{"V1":"Something","V2": "Something else"}

For some reason the MyObject o will not automatically bind from the JSON form post body (even with [FromBody] inserted before the parameter on the method.

Am I doing something wrong?

SOLUTION (DUH!)

To debug my incoming requests, I had put this in my global.asax (because I was failing to get the requests to flow through Fiddler) so I could inspect them first

    protected void Application_BeginRequest()
    {
        using (Stream receiveStream = Request.InputStream)
        {
            using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
            {
                var content = readStream.ReadToEnd();
                Console.WriteLine(content);
            }
        }
    }

This was stopping anything down the line from reading the posted data. Soon as I removed that, the automatic model binding worked fine.

2 Answers 2

1

I think you either need to decorate your method with [HttpPost] or rename it to PostTakeIt. Web API defaults to GET I believe.

Sign up to request clarification or add additional context in comments.

Comments

1

Two things

public class TestController : ApiController
{
    [HttpPost]
    public void TakeIt([FromBody]MyObject o){
        Console.Write(o.ToString());
    }
}

Tag the action with HttpPost as is it not actually conforming to convention-based routing, and next tag the parameter with [FromBody] so the model binder know where to look for the model.

Also, given the URI api/test/takeit the assumption here is that the route template is api/{controller}/{action}.

The default template is usually api/{controller}/

// Convention-based routing.
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

which does not cater for the action name.

You would either have to add another route

// Convention-based routing.    
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

config.Routes.MapHttpRoute(
    name: "DefaultActionApi",
    routeTemplate: "api/{controller}/{action}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

or use Attribute routing

// Attribute routing.
config.MapHttpAttributeRoutes();

// Convention-based routing.
config.Routes.MapHttpRoute(
    name: "DefaultApi",
    routeTemplate: "api/{controller}/{id}",
    defaults: new { id = RouteParameter.Optional }
);

With updated controller

[RoutePrefix("api/test")]
public class TestController : ApiController
{
    [HttpPost]
    [Route("takeit")] //Matches POST api/test/takeit
    public IHttpActionResult TakeIt([FromBody]MyObject o){
        Console.Write(o.ToString());
        return Ok();
    }
}

3 Comments

I should have explicitly stated that I changed the API route mapper to "api/{controller}/{action}/{id}". Unfortunately neither adding [FromBody] to the parameter nor [HttpPost] to the method makes any difference to the binding on my controller. I have a feeling its a config setting somewhere that is missing.
@Jimbo I would have to agree. There is not enough info in the OP for use to tell though. provide a minimal reproducible example that can be used to reproduce your problem and help find a solution.
Dammit, knew it was something simple... I have put more info in my OP explaining why this wasnt working. Thanks for your efforts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.