我有一个我无法解释的有趣案例,我需要帮助弄清楚我在IIS7上遇到的问题:
假设:
请参阅以下控制器:
public class ServiceController : Controller
{
public ActionResult Test()
{
return Content("Test");
}
[HttpPost]
public ActionResult Test2()
{
return Content("Test2");
}
}
此外,在Global.asax中有以下代码:
protected void Application_EndRequest()
{
if (Context.Response.StatusCode == 404)
{
ExecuteIndexPage();
}
}
protected void Application_Error(object sender, EventArgs e)
{
var error = Server.GetLastError();
ExceptionLogger.Log(error);
ExecuteIndexPage();
}
因此,每当出现服务器错误时,都会记录下来。在这种情况下,在正常404的情况下,返回起始页面。这工作(几乎)很好。以后更多。
此设置在IIS7(Windows Server 2008,生产环境)和IIS7.5(Win7 Pro,开发环境和Windows Server 2008 R2,以及生产环境)上提供了截然不同的行为。
在IIS(两个版本)中给出以下配置:
在 IIS 7.5 中,行为是:
在 IIS 7 中,行为改为:
因此,IIS 7和IIS 7.5在使用GET请求时效果很好,除非没有路由。 当没有路由时,IIS 7.5执行状态代码为404的Global.asax结束请求并传递索引页。 IIS 7执行 NOT 执行Global.asax结束请求。为什么? 我可以(并且目前正在)通过注册{* catchall}路由解决此问题,以便存在匹配的路由。
当我尝试使用HTTP POST时,IIS 7的工作效果甚至低于我的预期。
在发布请求时,IIS 7不会在我的应用程序中执行任何代码,并直接返回IIS 404页面。
所以我的问题是:为什么IIS 7在我的MVC 4应用程序中拒绝如此难以处理POST请求,我该怎么办才能让它处理post请求呢?
答案 0 :(得分:1)
我们终于明白了。
默认配置在web.config中插入:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
<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>
问题是“*”。路径,它将覆盖/test.aspx,但不是简单/测试。
如果将其更改为“*”,则所有请求都将由ExtensionlessUrlHandler处理,包括那些将不再提供的静态文件。
所以解决方案是: 从处理程序条目中删除POST动词,并为ExtensionlessUrlHandler添加新条目,路径设置为“*”,仅用于POST请求:
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,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,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,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit_post" path="*" verb="POST" 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_post" path="*" verb="POST" 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_post" path="*" verb="POST" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
理想情况下,删除不需要的(经典与集成管道中的x86和x64)。
答案 1 :(得分:0)
这可能与IIS 7上未安装(或未正确)的某些功能有关,这些功能会阻止无扩展URL正常工作。
请检查以下项目:
在Windows控制面板“程序和功能”应用程序的“打开或关闭Windows功能”对话框中:
答案 2 :(得分:0)
对于将POST交给没有可以接受帖子表单数据的参数的操作,7和7.5路由可能不同。
如果您的代码永远不会被命中,则表明路由没有找到匹配签名,参数和内置约束,它在切换到代码之前检查。
下一步可能是尝试将参数添加到POST以接受模型,即使您没有传递该模型。结果显然模型将为null。