我使用 ASP.NET Web API 编写了 REST 服务。我正在尝试发送 HttpDelete 请求,但是我收到以下错误:
405 - 不允许用于访问此页面的 HTTP 动词
我想我已经接近解决方案了,我发现我应该启用 IIS 远程管理,转到 Handler Mappings 部分并将 DELETE 动词添加到适当的位置......但问题是有很多不同的位置列表...(像这里的东西:http://www.somacon.com/p126.php)。
我应该编辑哪一个?其中很少有没有扩展名,例如“ExtensionUrlHandler-Integrated-4.0”,我在其中添加了 DELETE 动词,但它仍然不起作用......
修改那个只是在黑暗中拍摄,所以我应该修改不同的位置吗?如果有,是哪一个?或者也许还有什么我应该做的?
相同的 Web 服务在我的本地服务上工作得非常好,所以我猜问题出在远程 IIS 上……
问候
您不需要卸载 WebDAV,只需将这些行添加到 web.config:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>
此错误的常见原因是 WebDAV。确保卸载它。
如下更改您的 Web.Config 文件
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV"/>
<remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
<remove name="OPTIONSVerbHandler"/>
<remove name="TRACEVerbHandler"/>
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
如下更改您的 Web.Config 文件。它会像魅力一样。
在节点 <system.webServer>
中添加以下代码部分
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
</modules>
添加后,您的 Web.Config 将如下所示
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
</modules>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
我遇到了这个问题,我解决了以下问题:
打开 IIS 在功能视图中选择后端站点:打开处理程序映射
https://i.stack.imgur.com/lYWzE.jpg
在处理程序映射窗口中,查找 WebDAV
https://i.stack.imgur.com/OzoOt.jpg
在编辑模块映射中,打开请求限制
https://i.stack.imgur.com/li989.jpg
检查您的 web.confiq
文件”
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
如果上述解决方案都没有像我一样解决您的问题(仍然卡在我的 RestClient 模块面对 405 ),请尝试使用 Postman 或 Fiddler 之类的工具请求您的 Api。我的意思是问题可能出在其他地方,例如格式错误的请求。
我发现我的 RestClient 模块正在询问一个 Id 参数格式不正确的“Put”:
http://myserver/api/someresource?id=75fd954d-d984-4a31-82fc-8132e1644f78
代替
http://myserver/api/someresource/75fd954d-d984-4a31-82fc-8132e1644f78
奇怪的是,格式错误的请求返回 405 - Method Not Allowed (IIS 7.5)
不常见,但可能会有所帮助。
确保您使用 System.Web.Http 中的 [HttpPut]
我们在 HttpPut 修饰方法上收到“不允许的方法”405。
我们的问题似乎并不常见,因为我们不小心使用了 System.Web.Mvc 中的 [HttpPut] 属性而不是 System.Web.Http
原因是,resharper 建议使用 .Mvc 版本,当您直接从 ApiController 派生时,通常已经引用了 System.Web.Http,我们使用的是扩展 ApiController 的类。
当我调用的 web api post 方法具有参数的原始类型而不是从主体访问的复杂类型时,我已经发生了这种情况(不允许使用 405 方法)。像这样:
这有效:
[Route("update"), Authorize, HttpPost]
public int Update([FromBody] updateObject update)
这没有:
[Route("update"), Authorize, HttpPost]
public int Update(string whatever, int whatever, string whatever)
此错误来自静态文件处理程序——默认情况下不过滤任何动词,但可能只能处理 HEAD 和 GET。
这是因为没有其他处理程序站出来说他们可以处理删除。
由于您使用的是 WEBAPI,因为路由没有文件,因此没有扩展名,因此需要将以下添加添加到您的 web.config 文件中:
<system.webserver>
<httpProtocol>
<handlers>
...
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="C:\windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="C:\windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
显然需要什么取决于经典模式与集成模式,而经典模式取决于位数。此外,还为 CORS 处理添加了 OPTIONS 标头,但如果您不执行 CORS,则不需要它。
仅供参考,您的 web.config 是应用程序(或应用程序目录)版本的本地,其顶级是 applicationHost.config。
如果是 IIS 8.0,请检查是否启用了 HTTP 激活。服务器管理器 -> IIS -> 管理(见右上方) -> 添加角色和功能 -> ... -> 进入 WCF 配置,然后选择 HTTP 激活。
以上都对我不起作用,我在使用支持页面时遇到了问题(https://support.microsoft.com/en-us/help/942051/error-message-when-a-user-visits-a-website-that-is-hosted-on-a-server)then 我将应用程序主机文件与一个工作副本进行了比较,似乎我缺少一堆处理程序,当我将它们添加回应用程序时主机开始工作。我错过了所有这些,
<add name="xamlx-ISAPI-4.0_64bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="xamlx-ISAPI-4.0_32bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
<add name="xamlx-Integrated-4.0" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" type="System.Xaml.Hosting.XamlHttpHandlerFactory, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="rules-ISAPI-4.0_64bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="rules-ISAPI-4.0_32bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
<add name="rules-Integrated-4.0" path="*.rules" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="xoml-ISAPI-4.0_64bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="xoml-ISAPI-4.0_32bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
<add name="xoml-Integrated-4.0" path="*.xoml" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="svc-ISAPI-4.0_64bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="svc-ISAPI-4.0_32bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
<add name="svc-Integrated-4.0" path="*.svc" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="rules-64-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
<add name="rules-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
<add name="rules-Integrated" path="*.rules" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
<add name="xoml-64-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
<add name="xoml-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
<add name="xoml-Integrated" path="*.xoml" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
<add name="svc-ISAPI-2.0-64" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
<add name="svc-ISAPI-2.0" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
<add name="svc-Integrated" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
.NET Framework 4.x Features
的 WCF Services
中添加 HTTP Activation
(Windows 程序和功能,或 Windows Server 的角色和功能)我遇到了确切的问题(405 Method not allowed over a .NET SOAP Web服务),这需要 HTTP 激活功能。
在我们的案例中,问题在于 .Net 站点和 ADFS 之间的联合登录。重定向到 ADFS 端点时,wctx
参数需要 WSFederationAuthenticationModule.CreateSignInRequest
方法的所有三个参数:rm
、id
和 ru
感谢 Guillaume Raymond 提供的检查 URL 参数的提示!
除了上述所有解决方案外,请检查您是否有“id
”或 DELETE
方法中的任何自定义参数与路由配置匹配。
public void Delete(int id)
{
//some code here
}
如果您遇到重复的 405 错误,最好将方法签名重置为默认值,然后尝试。
默认情况下,路由配置将在 URL 中查找 id
。因此,参数名称 id
在这里很重要,除非您更改 App_Start
文件夹下的路由配置。
不过,您可以更改 id
的数据类型。
例如,下面的方法应该可以正常工作:
public void Delete(string id)
{
//some code here
}
注意:还要确保通过 url 传递数据,而不是通过将负载作为正文内容携带的数据方法。
DELETE http://{url}/{action}/{id}
例子:
DELETE http://localhost/item/1
希望能帮助到你。
我将为那些在尝试运行 PHP
(可能是 Laravel
)或使用 405 error
的其他独特 IIS
托管情况时遇到困难的人添加,您需要为此更改处理程序中的 verbs
对于这种特定情况...所以由于我使用的是 PHP
,因此我转到 PHP
处理程序,然后在 Request Restrictions
和 Verbs
选项卡中添加您需要的 verbs
。这就是我需要添加到 web.config
以在 Laravel
中启用 CORS
的全部内容。
<handlers>
<remove name="php-5.6.40" />
<add name="php-5.6.40" path="*.php" verb="GET,HEAD,POST,PUT,DELETE,OPTIONS" modules="FastCgiModule" scriptProcessor="C:\Program Files (x86)\PHP\v5.6\php-cgi.exe" resourceType="Either" requireAccess="Script" />
</handlers>
这可能不适用于纯“Web API”,也可能不适用于流行的面向公众的网站,但如果您在使用 IIS 10 的网站上遇到此错误 405 - Method Not Allowed 问题,应用程序使用 AspNetCore 2.2、MVC 2 构建(或 3)和 Angular 9,这是我的经验。错误消息告诉我,我可以访问 MVC 控制器,但不允许(或找到或列出)“PUT”作为我的 MVC 控制器上的 Http 动词选项之一。
我可以使用 POST 登录(因为“Login()”是我用 [HttpPost(route)] 装饰的 MVC 控制器方法的名称)并且我可以成功使用 GET 动词。我使用 Routes 进行导航。
但我无法使用 POST 创建新条目,无法使用 PUT 编辑它们或使用 DELETE 删除它们。我收到“405”错误。
就我而言,从 web.config 中删除 WebDAV 引用只会将我收到的错误从“405”更改为“400 - Bad Request”。
但是,这个信息也很有帮助,所以我回到了开发模式,更改了我的 MVC 控制器方法名称以匹配 HTTP 动词名称,例如“PUT”现在匹配控制器方法“Put()”——即使使用 [FromBody] . “DELETE”动词现在匹配“Delete()”方法名称,POST 匹配“Post()”。我没有从新方法名称中删除或更改任何必要的参数,例如“id”等。
我再次开始测试并在 dotnet server compile 中收到错误,显示 MVC 控制器路径中的跨站点防伪问题存在问题。
我还在 StartUp.cs 中使用防伪标头/cookies,它在登录 POST 中工作,所以我没有在 StartUp.cs 中更改任何内容。
但是我的 MVC 控制器类用 [AutoValidateAntiforgeryToken] 属性装饰(不完全理解我为什么使用它,只是按照我的例子),我的 MVC 控制器方法用 [HttpPut] 等装饰。
因此,由于 dotnet 编译错误,我删除了类级别属性 [AutoValidateAntiforgeryToken],但将 [HttpPut] 等属性保留在每个 MVC 控制器的方法级别。
这是我的解决方案,编辑 web.config 以删除 WebDAV,使控制器方法名称匹配 http 动词并从 MVC 控制器类中删除 [AutoValidateAntiforgeryToken] 属性 - 因为我的网站是私有的,而不是面向公众的。
我的 StartUp.cs 中仍然有登录标头 x-xsrf-token / cookies / antiforgery 的东西,它仍然可以在登录时使用。然而,仍在研究如何让它在 MVC 控制器类级别上工作。
但是,就目前而言,我可以毫无错误地进行 POST、PUT 和 DELETE。
更新 - 通过阅读其他一些关于 **400 - Bad Request”问题的帖子,我发现 this link 到“ASP.NET Core Web Api Antiforgery”。这非常有帮助。在完成之后文章建议的更新包括添加 MVC AntiForgeryController 和 Angular Injectable 服务,我可以在为我的控制器打开 CRSF 的情况下进行 PUT、POST 和 DELETE,在大多数控制器上使用“ValidateAntiForgeryToken”,但“忽略”一些方法() ,就像文章建议的那样。
除了文章中的更改之外,我还在我的 StartUp.cs 中的 Configure() 方法中注册了这个应用程序 - 除了“登录”之外,我没有面向公众的路由:
app.Use(nextDelegate => context =>
{
string path = context.Request.Path.Value;
string[] directUrls = { "/<first restricted url route>", "/<second restricted url route>", "/<third>" };
if (path.StartsWith("/api") || string.Equals("/", path) ||
directUrls.Any(url => path.StartsWith(url)))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-REQUEST-TOKEN", tokens.RequestToken,
new CookieOptions()
{
HttpOnly = false,
Secure = false,
IsEssential = true
});
}
return nextDelegate(context);
});