4

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...

3 Answers 3

8

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.

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

7 Comments

Yes, that might be also an issue if you are using url form encoding, not for json.
The madness is only because everybody is desperately trying to pretend that we are not using HTTP. Unless you understand what media type is being passed, and how Web API deals with passed media types, why is anyone surprised when it doesn't magically work.
@DarrelMiller At some point when behavior doesn't work as expected, it stops being the programmer's and starts being the tools fault. If a tools design can't accommodate the metaphor it's trying to abstract, it's not a programmer mindset issue, it's a poor design choice.
@mythz Web API was supposed to be an abstraction of HTTP. Not object serialization. If someone wants to do object serialization they should use ServiceStack.
@DarrelMiller Agreed, sounds like great advice :)
|
2

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);
    }
}

2 Comments

This works...and the ActionName attribute doesn't actually seem to be needed.
@Darragh The action name would be needed if you have more than one method with the HttpPost attribute.
0

Try with the following change,

public class TestController : ApiController
{
    [HttpPost]
    [ActionName("SendData")]
    public void SendData(string data)
    {
        Console.WriteLine(data);
    }
}

The ActionName attribute might fix the issue. Otherwise, you can also the name convention "Post"

public void Post(string data)
{
   Console.WriteLine(data);
}

And send an Http Post directly to "services" without SendData.

Comments

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.