405方法不允许的Web API

115

这个错误非常普遍,我尝试了所有的解决方案,但都没有起作用。我在控制面板中禁用了WebDAV发布,并将其添加到了我的Web配置文件中:

  <handlers>
  <remove name="WebDAV"/>
  </handlers>
  <modules runAllManagedModulesForAllRequests="true">
  <remove name="WebDAVModule"/>
  </modules>

错误仍然存在。这是控制器:

   static readonly IProductRepository repository = new ProductRepository();

    public Product Put(Product p)
    {
        return repository.Add(p);
    }

方法实现:

 public Product Add(Product item)
    {
        if (item == null)
        {
            throw new ArgumentNullException("item");
        }
        item.Id = _nextId++;
        products.Add(item);
        return item;
    }

这就是异常抛出的地方:

client.BaseAddress = new Uri("http://localhost:5106/");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));      
var response = await client.PostAsJsonAsync("api/products", product);//405 exception

有什么建议吗?

25个回答

84

你正在客户端进行POST请求:

await client.PostAsJsonAsync("api/products", product);

无法进行PUT请求。

您的Web API方法只接受PUT请求。

因此:

await client.PutAsJsonAsync("api/products", product);

当您尝试运行代码时,会抛出错误“HttpClient”不包含“PostAsJsonAsync”的定义。 - agileDev

67

我遇到了同样的异常。我的问题是我使用了:

using System.Web.Mvc; // Wrong namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}

应该是这样的

using System.Web.Http; // Correct namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}

19

我尝试了很多方法来使DELETE方法生效(我一直得到405方法不允许的Web API),最终我在我的控制器中添加了[Route("api/scan/{id}")],然后它正常运作了。希望这篇文章能帮助某些人。

     // DELETE api/Scan/5
    [Route("api/scan/{id}")]
    [ResponseType(typeof(Scan))]
    public IHttpActionResult DeleteScan(int id)
    {
        Scan scan = db.Scans.Find(id);
        if (scan == null)
        {
            return NotFound();
        }

        db.Scans.Remove(scan);
        db.SaveChanges();

        return Ok(scan);
    }

因为某些原因,我的删除操作一直无法正常工作,但创建和更新操作却可以。好吧,我只是加了[HttpPost],就可以正常工作了。不过还是谢谢你让我找对了方向,现在只花了5分钟 :) - Rubenisme
1
你为什么不只是添加[HttpDelete]属性呢? - johnny 5

18

我的问题实际上是WebAPI中的属性路由。我创建了一个自定义路由,但它被视为GET而不是WebAPI发现它是POST。

    [Route("")]
    [HttpPost] //I added this attribute explicitly, and it worked
    public void Post(ProductModel data)
    {
        ...
    }

我知道这一定是某些愚蠢的事情(占据了你整整一天的时间)。


8

当您尝试在服务器使用https的情况下连接http时,也可能会出现此错误。

这有点令人困惑,因为我的get请求没有问题,只有在post请求时才存在问题。


有没有办法在不将URL从http更改为https的情况下修复它? - Lechucico
这就是我遇到的问题。谢谢。 - charlybones

6
我来晚了,但是在大多数情况下,以上方法都不可行或无效。以下是我最终解决问题的方法。
在托管网站/服务的服务器上,需要启用一个功能!HTTP激活!!!
操作如下: 服务器管理器 -> 管理 -> 添加角色和功能 -> 下一步,直到你到达“功能” -> 在.NET(每个版本)下选中HTTP激活。 还要注意,在net->WCF服务下有一个隐藏的选项。
这样就可以立即解决问题了! 这真的让我很头疼。

6

在进行POST请求之前,Chrome经常会尝试执行OPTIONS调用。这是为了确保CORS标头有序。如果您没有在API控制器中处理OPTIONS调用,则可能会出现问题。

public void Options() { }

5

虽然这是一个老问题,但是对我来说所有的答案都没有起到作用。

这篇文章通过在web.config文件中添加以下几行代码解决了我的问题:

<system.webServer>
  <modules runAllManagedModulesForAllRequests="false">
    <remove name="WebDAVModule" />
  </modules>
</system.webServer>

嗯...我做了这个,它从405变成了500...嗯 - bkwdesign
1
与@Danushka所建议的类似,我也不得不将其放在<handlers>中。因此,除了上述内容之外,还需添加:<remove name="WebDAV" />到处理程序中。 - bkwdesign

5
如果你的方法需要一个参数,而你没有传递它,也会出现405错误。
这样是不起作用的(405错误)。
HTML视图/ JavaScript。
$.ajax({
         url: '/api/News',
         //.....

Web Api:

public HttpResponseMessage GetNews(int id)

因此,如果方法签名与上述类似,则必须执行以下操作:
HTML视图/ JavaScript
$.ajax({
         url: '/api/News/5',
         //.....

我似乎因为各种原因遇到了405错误,但它们都归结于尝试调用方法签名时出现的参数问题、命名约定问题或属性问题等。 - Tom Stickel

4
如果您有这样的路由:
[Route("nuclearreactors/{reactorId}")]

您需要在方法中使用完全相同的参数名称,例如:
public ReactorModel GetReactor(reactorId)
{
 ...
}

如果您没有传递完全相同的参数,可能会出现"405方法不允许"的错误,因为路由不会匹配请求,并且WebApi将命中一个不同的控制器方法,其中包含不同的允许HTTP方法。

这也不是一个答案! - Divyang Desai
1
因为路由设置无效,所以在我分享的情况下可能会显示“405方法不允许”的@Div。该方法将无法捕获api-call。然后,api-call可能会命中另一个意外的方法,该方法可能具有不同的HTTP操作允许。是的,我同意这个答案可能不完全符合实际问题,但是Xardas提出的问题标题并不是非常具体,我相信许多人在寻找与标题所述问题的答案时会发现此答案有用。 - roylac

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接