405方法不允许Web API


88

此错误非常常见,我尝试了所有解决方案,但没有一个起作用。我已在控制面板中禁用了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

有什么建议么?

Answers:


61

您正在从客户端发布:

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

不放。

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

所以:

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

尝试您的代码时,错误“ HttpClient”不包含引发“ PostAsJsonAsync”的定义。
agileDev

61

我有同样的例外。我的问题是我曾经使用过:

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

18

我尝试了很多事情来使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 16'7

1
为什么不只添加[HttpDelete]属性?
约翰尼

14

我的问题原来是WebAPI中的属性路由。我创建了一个自定义路由,并将其视为GET而不是WebAPI,将其视为POST

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

我知道那一定是愚蠢的(消耗了您一整天)


这挽救了我的一天!
Phate01

6

Chrome通常会OPTIONS在发布信息之前尝试拨打电话。这样做是为了确保CORS标头是正确的。如果未OPTIONS在API控制器中处理调用,则可能会出现问题。

public void Options() { }

6

当服务器在https上时尝试连接到http时,也会发生此错误。

这有点令人困惑,因为我的get请求还可以,问题只存在于post-requests上。


4

我在GET调用中获取405,结果发现我在GET服务器端方法中命名了该参数Get(int formId),并且需要更改路由或重命名它Get(int id)


4

如果说您的方法需要一个参数并且没有传递该参数,那么您还会收到405错误。

这不起作用(405错误)

HTML视图/ JavaScript

$.ajax({
         url: '/api/News',
         //.....

网络Api:

public HttpResponseMessage GetNews(int id)

因此,如果方法签名与上述类似,则必须执行以下操作:

HTML视图/ JavaScript

$.ajax({
         url: '/api/News/5',
         //.....

我似乎由于各种原因遇到了405个错误,它们全都归结为它试图命中方法签名和参数问题,约定命名问题或属性问题等
事实

4

我参加这个聚会很晚,但是由于以上情况在大多数情况下都不可行或无法解决,因此这终于为我解决了。

在托管站点/服务的服务器上,需要一项功能!HTTP激活!!!

服务器管理器>管理>添加角色和功能>下一步下一步,直到进入功能>在.NET(每个版本)下,勾选HTTP激活。另请注意,在> net> WCF服务下隐藏了一个。

然后,此操作立即生效!那使我的大脑融化


4

如果您有类似的路线

[Route("nuclearreactors/{reactorId}")]

您需要在方法中使用完全相同的参数名称,例如

public ReactorModel GetReactor(reactorId)
{
 ...
}

如果未传递完全相同的参数,则可能会收到错误“ 405方法不允许”,因为路由与请求不匹配,WebApi将使用允许的HTTP方法使用不同的控制器方法。


这也不是答案!
Divyang Desai

在我共享的情况下,可能会显示@Div“不允许使用405方法”,因为该方法将无法捕获api调用,因为路由设置无效。然后,api调用可能会遇到另一个意外的方法,该方法可能具有允许的不同HTTP操作。是的,我同意这个答案可能与实际问题并非100%相关,但是Xardas提出的问题的标题不是很明确,我相信许多落在此处的人可能会按照标题中的说明寻找问题的答案觉得这个答案有用。
roylac'4


3

这不能回答您的特定问题,但是当我遇到相同的问题时,我到了这里,我发现更多的人可能会这样做。

我遇到的问题是,我故意将Get方法声明为static。我错过了整个整个上午,并没有引起来自属性或类似内容的警告。

不正确:

public class EchoController : ApiController
{
    public static string Get()
    {
        return string.Empty;
    }
}

正确:

public class EchoController : ApiController
{
    public string Get()
    {
        return string.Empty;
    }
}

2

[HttpPost]是不必要的!

[Route("")]
public void Post(ProductModel data)
{
    ...
}

1
是的,您这样做的方式是正确的,因为您不需要显式的[HttpPost],但是有些人没有遵循约定(喜欢),因此,有些东西像[Route(“ MyMethodSaver”]公共字符串MyMethodtoSave(int? id)->需要一个[HttpPost],然后它将起作用
Tom Stickel 2015年

2

我无法解决这个问题。只要POST返回void(ASP.NET 4.0-WEBAPI 1),我就启用了CORS并且可以正常工作。当我尝试返回HttpResponseMessage时,我开始获取HTTP 405响应。

根据上面Llad的回答,我看了自己的参考资料。

我在POST方法上方列出了属性[System.Web.Mvc.HttpPost]。

我将其更改为使用:

[System.Web.Http.HttpPostAttribute]
[HttpOptions]
public HttpResponseMessage Post(object json)        
{
    ...
    return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}

这解决了我的麻烦。我希望这可以帮助其他人。

为了完整起见,我在web.config中添加了以下内容:

<httpProtocol>
    <customHeaders>
        <clear />
        <add name="Access-Control-Expose-Headers " value="WWW-Authenticate"/>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, PATCH, DELETE" />
        <add name="Access-Control-Allow-Headers" value="accept, authorization, Content-Type" />
        <remove name="X-Powered-By" />
    </customHeaders>
</httpProtocol>

这将具有在OPTIONS飞行前请求(以及POST)上调用的方法的时间,这时json很可能是null因为飞行前请求通常没有有效负载,否则您将运行两次Post操作。
glennsl

1

我们有一个类似的问题。我们试图从中获取:

[RoutePrefix("api/car")]
public class CarController: ApiController{

    [HTTPGet]
    [Route("")]
    public virtual async Task<ActionResult> GetAll(){

    }

}

因此,我们将会.GET("/api/car")并且这将引发一个错误405 error


解决方法:

CarController.cs文件位于目录中,/api/car因此当我们请求此api端点时,IIS会发回一个错误,因为它看起来像我们在尝试访问不允许访问的虚拟目录。

选项1:更改/重命名控制器所在的目录。
选项2:将路由前缀更改为与虚拟目录不匹配的名称。


1

就我而言,我在项目中有一个物理文件夹,名称与WebAPI路由相同(例如,沙箱),并且IIS中的静态文件处理程序仅拦截了POST请求(显然)。

得到误导性的405错误而不是预期的404错误,是我花很长时间进行故障排除的原因。

不容易陷入这种情况,但有可能。希望它能帮助某人。


1

就我而言,我的POST处理程序具有以下形式:

[HttpPost("{routeParam}")]
public async Task<ActionResult> PostActuality ([FromRoute] int routeParam, [FromBody] PostData data)

我发现我必须交换参数,也就是说首先要交换主体数据,然后交换route参数,如下所示:

[HttpPost("{routeParam}")]
public async Task<ActionResult> PostActuality ([FromBody] PostData data, [FromRoute] int routeParam)

0

签入您的项目.csproj文件并进行更改

<IISUrl>http://localhost:PORT/</IISUrl>

这样访问您的网站网址

<IISUrl>http://example.com:applicationName/</IISUrl>

0

导致相同行为的另一个可能的问题是路由中的默认参数。在我的情况下,控制器已正确定位并实例化,但由于Get指定了默认操作,POST被阻止了:

config.Routes.MapHttpRoute(
    name: "GetAllRoute",
    routeTemplate: "api/{controller}.{ext}"/*,
    defaults: new { action = "Get" }*/ // this was causing the issue
);

0

我遇到了完全相同的问题。我看了两个小时,运气不好,直到我意识到我的POST方法private代替了public

现在很有趣,看到该错误消息有点泛泛。希望能帮助到你!


0

确保您的控制器从Controller类继承。

甚至没有这些东西在本地工作甚至更疯狂。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.