Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I MapHttpRoute a POST to a custom action using the WebApi?

I'm trying to figure out the madness behind the Web API routing.

When I try to post data like this:

curl -v -d "test" http://localhost:8088/services/SendData

I get a 404, and the following error message:

{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:8088/services/SendData'.","MessageDetail":"No action was found on the controller 'Test' that matches the request."}

Here is the code for my test server.

public class TestController : ApiController
{

    [HttpPost]
    public void SendData(string data)
    {
        Console.WriteLine(data);
    }
}

class Program
{
    static void Main(string[] args)
    {

        var config = new HttpSelfHostConfiguration("http://localhost:8088");

        config.Routes.MapHttpRoute(
            name: "API Default",
            routeTemplate:"services/SendData",
            defaults: new { controller = "Test", action = "SendData"},
            constraints: null);

        using (var server = new HttpSelfHostServer(config))
        {
            server.OpenAsync().Wait();  
            Console.WriteLine("Press Enter to quit.");
            Console.ReadLine();
        }

    }
}

More generally, why has the ASP.NET team decided to make the MapHttpRoute method so confusing. Why does it take two anonymous objects....how is anyone supposed to know what properties these objects actually need?

MSDN gives no help: http://msdn.microsoft.com/en-us/library/hh835483(v=vs.108).aspx

All the pain of a dynamically typed language without any of the benefit if you ask me...

like image 601
Darragh Avatar asked Dec 27 '22 06:12

Darragh


2 Answers

Agree with you, it's a hell of a madness, you need to specify that the data parameter should be bound from the POST payload, since the Web API automatically assumes that it should be part of the query string (because it is a simple type):

public void SendData([FromBody] string data)

And to make the madness even worse you need to prepend the POST payload with = (yeah, that's not a typo, it's the equal sign):

curl -v -d "=test" http://localhost:8088/services/SendData

You could read more about the madness in this article.

Or stop the madness and try ServiceStack.

like image 176
Darin Dimitrov Avatar answered Dec 28 '22 19:12

Darin Dimitrov


Use this signature and it will work every time.

public class TestController : ApiController
{
    [HttpPost]
    [ActionName("SendData")]
    public HttpResponseMessage SendData(HttpRequestMessage request)
    {
        var data = request.Content.ReadAsStringAsync().Result;
        Console.WriteLine(data);
    }
}
like image 40
Darrel Miller Avatar answered Dec 28 '22 21:12

Darrel Miller