Web API - 405 - The requested resource does not support http method 'PUT'

Solution 1:

Are you using attribute routing?

This mystic error was a route attributes issue. This is enabled in your WebAPIConfig as:

 config.MapHttpAttributeRoutes(); 

It turns out Web Api Controllers "cannot host a mixture of verb-based action methods and traditional action name routing. "; https://aspnetwebstack.codeplex.com/workitem/184

in a nutshell: I needed to mark all of my actions in my API Controller with the [Route] attribute, otherwise the action is "hidden" (405'd) when trying to locate it through traditional routing.

API Controller:

[RoutePrefix("api/quotes")]
public class QuotesController : ApiController
{
    ...

    // POST api/Quote
    [ResponseType(typeof(Quote))]
    [Route]
    public IHttpActionResult PostQuote(Quote quote)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.Quotes.Add(quote);
        db.SaveChanges();

        return CreatedAtRoute("", new { id = quote.QuoteId }, quote);
    }

note: my Route is unnamed so the CreatedAtRoute() name is just an empty string.

WebApiConfig.cs:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

        // Web API routes
        config.MapHttpAttributeRoutes();

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

    }
}

hope this helps

Solution 2:

I had the exact same problem as you, and I tried all the things you tried but sometimes the solution is so trivial and under your nose, that you just don't expect it and keep looking for more complicated reasons. Make sure that in the url you're calling to test your web methods, the param names match the names in your controller method declaration. My 405 problem was solved by simply doing this (I was using query params):

My clientsController:

...

[HttpPut]
public string PutClient(string username = "", string phone= ""){...}

On my WebApiConfig:

// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
     name: "DefaultApi",
     routeTemplate: "api/{controller}"
);

And the path used to test the method must be like so: (use Postman or similar, to apply the correct web method)

http://localhost:49216/api/clients?username=Kurt&phone=443332211

Otherwise, you'll get a 405 for that http method in that controller. I didn't need to change the web.config at all (no need to remove webdav, etc..). Check this for source in the documentation:

For example, consider the following action:

public void Get(int id)

The id parameter binds to the URI. Therefore, this action can only match a URI that contains a value for "id", either in the route dictionary or in the query string.

Optional parameters are an exception, because they are optional. For an optional parameter, it's OK if the binding can't get the value from the URI.

Solution 3:

This happened to me when I changed the first parameter name of the PUT method

public void Put(int code, [FromBody]Lead lead)

It should be:

public void Put(int id, [FromBody]Lead lead)

And this is how it gets called:

$.ajax({
    type: "PUT",
    data: json,
    url: "../api/leadsapi/123",
    contentType: "application/json; charset=utf-8"
});