405 方法不允许 Web API
Posted
技术标签:
【中文标题】405 方法不允许 Web API【英文标题】:405 method not allowed Web API 【发布时间】:2013-03-21 01:39:47 【问题描述】:这个错误很常见,我尝试了所有的解决方案,但都没有奏效。我已在控制面板中禁用 WebDAV 发布并将其添加到我的网络配置文件中:
<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
有什么建议吗?
【问题讨论】:
【参考方案1】:您正在从客户端发布:
await client.PostAsJsonAsync("api/products", product);
不放。
您的 Web API 方法只接受 PUT 请求。
所以:
await client.PutAsJsonAsync("api/products", product);
【讨论】:
错误“HttpClient”不包含“PostAsJsonAsync”的定义在尝试您的代码时抛出。【参考方案2】:我也有同样的例外。我的问题是我使用过:
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";
【讨论】:
【参考方案3】:我尝试了很多方法来让 DELETE 方法工作(我得到了 405 method not allowed 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 分钟 :) 为什么不直接添加 [HttpDelete] 属性?【参考方案4】:我的问题原来是 WebAPI 中的属性路由。我创建了一个自定义路由,它把它当作一个 GET 而不是 WebAPI 发现它是一个 POST
[Route("")]
[HttpPost] //I added this attribute explicitly, and it worked
public void Post(ProductModel data)
...
我知道这一定很愚蠢(这会消耗你一整天)
【讨论】:
这拯救了我的一天!【参考方案5】:Chrome 经常尝试在发布帖子之前拨打OPTIONS
电话。它这样做是为了确保 CORS 标头是有序的。如果您没有在 API 控制器中处理 OPTIONS
调用,则可能会出现问题。
public void Options()
【讨论】:
【参考方案6】:当您在服务器处于 https 时尝试连接到 http 时,也会发生此错误。
这有点令人困惑,因为我的 get-requests 没问题,问题只存在于 post-requests 中。
【讨论】:
有没有办法在不将 URL 从 http 更改为 https 的情况下解决这个问题? 这是我遇到的问题。谢谢【参考方案7】:我在 GET 调用中得到 405,问题原来是我在 GET 服务器端方法中将参数命名为Get(int formId)
,我需要更改路由,或者将其重命名为Get(int id)
。
【讨论】:
【参考方案8】:如果您的方法需要一个参数并且您没有传递它,您也可能会收到 405 错误。
这不起作用(405 错误)
HTML 视图/Javascript
$.ajax(
url: '/api/News',
//.....
网络接口:
public HttpResponseMessage GetNews(int id)
因此,如果方法签名像上面那样,那么你必须这样做:
HTML 视图/Javascript
$.ajax(
url: '/api/News/5',
//.....
【讨论】:
由于各种原因,我似乎遇到了 405 错误,它们都归结为它试图命中方法签名和参数问题或约定命名问题或属性问题等...【参考方案9】:我参加这个聚会迟到了,但在大多数情况下,以上任何方法都不可行或有效,这就是我最终解决的方法。
在托管站点/服务的服务器上,需要一项功能! HTTP 激活!!!
服务器管理器 > 管理 > 添加角色和功能 > 下一个下一个直到您到达功能 > 在 .NET(每个版本)下勾选 HTTP 激活。 另请注意,在 >net > WCF Services 下隐藏了一个。
然后立即生效! 那是在融化我的大脑
【讨论】:
【参考方案10】:如果你有这样的路线
[Route("nuclearreactors/reactorId")]
您需要在方法中使用完全相同的参数名称,例如
public ReactorModel GetReactor(reactorId)
...
如果您没有传递完全相同的参数,您可能会收到错误“405 method not allowed”,因为路由与请求不匹配,WebApi 将使用不同的允许 HTTP 方法访问不同的控制器方法。
【讨论】:
这也不是答案! @Div "405 method not allowed" 可以在我分享的情况下显示,因为该方法不会捕获 api-call,因为路由设置无效。然后,api 调用可能会遇到另一个意外的方法,该方法可能允许不同的 HTTP 操作。是的,我同意这个答案可能不是 100% 与实际问题相关,但是 Xardas 的问题标题不是很具体,我相信很多人登陆这里以寻找标题所述问题的答案可能觉得这个答案很有用。【参考方案11】:这并不能回答您的具体问题,但是当我遇到同样的问题时,我来到了这里,我认为更多的人可能会这样做。
我遇到的问题是我无意中将我的 Get 方法声明为 static。我错过了整个上午,它没有引起属性或类似的警告。
不正确:
public class EchoController : ApiController
public static string Get()
return string.Empty;
正确:
public class EchoController : ApiController
public string Get()
return string.Empty;
【讨论】:
【参考方案12】:这是一个解决方案
<handlers accessPolicy="Read, Script">
<remove name="WebDAV" />
</handlers>
docs.microsoft.com solution article
并从模块中删除 WebDAV
<remove name="WebDAVModule" />
【讨论】:
【参考方案13】:[HttpPost] 是不必要的!
[Route("")]
public void Post(ProductModel data)
...
【讨论】:
是的,您这样做的方式是正确的,因为您不需要明确的 [HttpPost] ,但是有些人不遵守约定(哎呀),因此类似于 [Route("MyMethodSaver "] public string MyMethodtoSave(int? id) --> 这需要一个 [HttpPost] 然后才能工作【参考方案14】:我无法解决这个问题。只要 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
,因为飞行前请求通常没有有效载荷,否则您将运行两次发布操作。【参考方案15】:
在我的情况下,我在项目中有一个与 WebAPI 路由(例如沙箱)同名的物理文件夹,并且只有 POST 请求被 IIS 中的静态文件处理程序拦截(显然)。
得到一个误导性的 405 错误,而不是更预期的 404,这是我花了很长时间进行故障排除的原因。
不容易陷入这种情况,但有可能。希望它可以帮助某人。
【讨论】:
【参考方案16】:确保您的控制器继承自 Controller
类。
即使没有它,东西也能在本地工作,这甚至可能更疯狂。
【讨论】:
【参考方案17】:就我而言,我的 POST 处理程序是这种形式:
[HttpPost("routeParam")]
public async Task<ActionResult> PostActuality ([FromRoute] int routeParam, [FromBody] PostData data)
我发现我必须交换参数,也就是说首先是正文数据,然后是路由参数,如下所示:
[HttpPost("routeParam")]
public async Task<ActionResult> PostActuality ([FromBody] PostData data, [FromRoute] int routeParam)
【讨论】:
【参考方案18】:签入您的项目 .csproj 文件并进行更改
<IISUrl>http://localhost:PORT/</IISUrl>
像这样发送到您的网站网址
<IISUrl>http://example.com:applicationName/</IISUrl>
【讨论】:
【参考方案19】:导致相同行为的另一个可能问题是路由中的默认参数。在我的情况下,控制器已正确定位和实例化,但由于指定了默认的 Get
操作,POST 被阻止:
config.Routes.MapHttpRoute(
name: "GetAllRoute",
routeTemplate: "api/controller.ext"/*,
defaults: new action = "Get" */ // this was causing the issue
);
【讨论】:
【参考方案20】:我遇到了完全相同的问题。我找了两个小时没有运气,直到我意识到我的 POST
方法是 private
而不是 public
。
有趣的是,现在看到该错误消息有点笼统。希望对您有所帮助!
【讨论】:
【参考方案21】:我们遇到了类似的问题。我们试图从:
[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: 将路由前缀更改为与虚拟目录不匹配的内容。
【讨论】:
【参考方案22】:老问题,但没有一个答案对我有用。
This article 通过在web.config
中添加以下行解决了我的问题:
<system.webServer>
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule" />
</modules>
</system.webServer>
【讨论】:
好吧...我这样做了,它从 405 变成了 500 对我来说.. 嗯 与@Danushka 的建议类似,我也必须将其放入<handlers>
因此,除了上述内容之外,在处理程序中添加:<remove name="WebDAV" />
【参考方案23】:
函数名称有时会使 c# 变得复杂。更改函数的名称,它将起作用。像 ProductPut 而不是 PutProduct 或 Put。
public Product ProductPut(Product p)
return repository.Add(p);
【讨论】:
【参考方案24】:在我的例子中,405 错误只出现在生产服务器上,而不是我的开发机器上。
我发现问题是由于我只是“手动”将本地发布的文件夹的内容从本地机器传输到在线生产服务器。
所以,我的修复方法是简单地删除产品服务器上的所有在线文件,然后使用 Visual Studio 上的“发布”选项通过 FTP 直接从我的本地计算机发布到产品服务器。
我不知道为什么这会改变一些东西,因为在我看来文件是一样的,但这个东西解决了问题,我希望它也可以帮助其他人。
【讨论】:
以上是关于405 方法不允许 Web API的主要内容,如果未能解决你的问题,请参考以下文章
在 DELETE 上不允许使用 Owin 自托管 Web API 405 方法
“无法在已发布的 Web API 上发布数据” – 405(不允许的方法)