Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebApi2 Requested resource does not support post

I've read a ton of similar posts that describe the same error message but they don't seem to match what i'm experiencing.

I have recently started using Web API and ripped all my MVC methods out where I was returning JSON etc, so MVC will just render the html and I will call down the models via ajax from my webapi controllers.

Here's the strange thing, I can GET and POST from my Home apiController (so I can login/signup etc) but I can only GET from an API Controller in an area I have created. I get a 405 (Method Not Allowed) even though its decorated and called the same way as other controller. I guess the routing is okay otherwise it wouldn't return my initial get?

Routing

 public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultAreaApi",
            routeTemplate: "api/{area}/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

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

Controller

 // Returns Model
 [HttpGet]
 public HttpResponseMessage SelectAgent()

 // The requested resource does not support http method 'POST'. 
 [HttpPost]
 public HttpResponseMessage SelectAgent(Guid id)

JQuery

 // Works fine
    $.ajax({
            type: 'POST',
            url: '/api/Home/Login',
            headers: options.headers,
            contentType: "application/json; charset=utf-8",
            dataType: 'JSON',
            data: ko.toJSON(self.serverModel),
            success: function (response) {

   // Works fine
   $.getJSON("/api/Account/Users/SelectAgent", function (model) { ....

   // 405 
    $.ajax({
        type: 'POST',
        url: '/api/Account/Users/SelectAgent',
        headers: options.headers,
        contentType: "application/json; charset=utf-8",
        dataType: 'JSON',
        data: "{'id':'" + selectModel.agentId() + "'}",
        success: function (response) {....

data being passed seems fine (or at least it was for the MVC controller that it used to work with).

I haven't modified the Home API Controller at all, I don't understand how I can post to that and not my other controller. Argh.

Any pointers in the right direction would be awesome.

like image 610
Peter Lea Avatar asked Feb 20 '14 10:02

Peter Lea


3 Answers

Web API is only looking at your querystring parameters for basic data types. Thus your post is just looking at the url of /api/Account/Users/SelectAgent when you are making your post. The data being submitted is not being considered when matching against the function, since you are not marking the Guid with a [FromBody] attribute. So the "Method Not Allowed" error is being returned because it is sending your POST request to your GET method (no params).

You can read more about this on asp.net:

If the parameter is a “simple” type, Web API tries to get the value from the URI. Simple types include the .NET primitive types (int, bool, double, and so forth), plus TimeSpan, DateTime, Guid, decimal, and string, plus any type with a type converter that can convert from a string. (More about type converters later.)

To fix this, try doing one of the following:

  1. Change the url that you are submitting to include the id in the querystring of the email

    url: '/api/Account/Users/SelectAgent?id=' + selectModel.agentId()

  2. Change the Action signature to read the Id FromBody:

    public HttpResponseMessage SelectAgent([FromBody]Guid id)

like image 83
Yaakov Ellis Avatar answered Oct 28 '22 08:10

Yaakov Ellis


I know this is an old question, but this answer might help someone. Changing the Action signature to read the Id FromBody: did not work for me and I wonder how easy it will be passing the parameters to the querystring when you have a complex type with many fields/members.

This problem is as a result of the fact that both traditional and verb-based routing cannot be used in the same ApiController. See this link. You can resolved this problem by adding an empty [Route] attribute to the POST action method. That is:-

 [HttpPost]
 [Route]
 public HttpResponseMessage SelectAgent(Guid id)
like image 33
Sola Oderinde Avatar answered Oct 28 '22 07:10

Sola Oderinde


When you have same Name for your post and get function, It routes to the Get function. Thats why you get this answer. Easiest way today is

 [HttpPost]
 [Route("api/postagent", Name ="postagent")]
 public HttpResponseMessage SelectAgent(Guid id)

just define a route for your post function and on the client side post it with host + /api/postagent for example. you find more detailed information over this link.

This is especially helpful if you create an api controller by generatin new controller. Predefined functions will have such structure as get and post method will have same route. you need to redefine one of them or both of them separate them.

https://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2#route-names

like image 34
Emil Avatar answered Oct 28 '22 08:10

Emil