身份验证过程中表单数据丢失——但仅限于集成管道模式
我维护一个 ASP.NET MVC 应用程序(版本 1),当前以经典模式在 IIS 7 上运行。我们希望开始以集成管道模式运行应用程序。然而,我遇到了一个奇怪的问题,它阻止我们切换到集成模式——当我们尝试时,应用程序停止接收表单数据。 (即通过 POST 方法发送数据。)
通过向 Global.aspx 文件添加大量日志记录,我能够缩小表单数据丢失的位置。这似乎是正在发生的事情。
收到请求后,将触发
Application_BeginRequest
事件。此时,表单数据已存在,并且可以通过检查请求对象的Forms
或Params
属性来查看。此时,请求的Url
属性不在其中的任何位置具有“.mvc”扩展名。 (更多内容见下文。)接下来,将触发
Application_AuthenticateRequest
事件。同样,表单数据存在,并且 URL 没有“.mvc”扩展名。此时,我期望发生的情况是触发
Application_PostAuthenticateRequest
事件。但实际发生的是再次调用Application_BeginRequest
。这次,表单数据消失了——它不在Forms
、Params
或其他任何地方。此外,URL 已更改,因此 URL 的控制器名称部分附加了“.mvc”扩展名。例如,如果步骤 1 和 2 中的 URL 是“/Education/Manage”,那么在步骤 3 中它将显示为“/Education.mvc/Manage”。Application_AuthenticateRequest
事件再次触发。同样,表单数据丢失,并且 URL 中嵌入了“.mvc”扩展名。这一次,
Application_PostAuthenticateRequest
被触发,页面生命周期的其余部分正常进行。在此事件和所有后续事件中,没有表单数据,并且“.mvc”扩展名仍然存在。
仅当我切换到集成管道模式时才会出现该问题。它在经典模式下运行良好。我已经搜索了好几天了,不幸的是我无法找到任何类似问题的参考。我还尝试以几种不同的方式编辑 Web.config 文件,希望能够解决问题,但没有任何运气。我希望这里有人可以阐明这个问题。
以下是一些相关的代码片段。如果我应该包含任何其他代码,请告诉我。
从 Web.config:
<system.web>
<authentication mode="Forms">
<forms name=".appLive" timeout="60" enableCrossAppRedirects="true" path="/" />
</authentication>
[...]
</system.web>
[....]
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="ScriptModule" />
<remove name="UrlRoutingModule" />
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<remove name="FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
<handlers>
<remove name="AboMapperCustom-17403419" />
<remove name="WebServiceHandlerFactory-Integrated" />
<remove name="ScriptHandlerFactory" />
<remove name="ScriptHandlerFactoryAppServices" />
<remove name="ScriptResource" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<add name="AboMapperCustom-17403419" path="*.mvc" verb="GET,POST,HEAD,DEBUG" modules="IsapiModule" scriptProcessor="C:\Windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,bitness32,runtimeVersionv2.0" responseBufferLimit="0" />
</handlers>
</system.webServer>
从 Global.aspx:
public void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = source as HttpApplication;
if (source != null)
{
if (application.Request.AppRelativeCurrentExecutionFilePath.Contains(".mvc"))
{
application.Context.RewritePath(application.Request.Url.PathAndQuery.Replace(".mvc", string.Empty));
}
}
}
I maintain an ASP.NET MVC application (version 1) that currently runs on IIS 7 in classic mode. We'd like to start running the app in integrated pipeline mode instead. However, I am running into a bizarre problem that is preventing us from switching to integrated mode-- when we try, the application stops receiving forms data. (I.e. data send via the POST method.)
By adding a ton of logging to the Global.aspx file, I was able to narrow down the location where the forms data is getting lost. Here's what seems to be happening.
Upon receiving the request, the
Application_BeginRequest
event is fired. At this point, the forms data is present and can be seen by examining the request object'sForms
orParams
property. The request'sUrl
property at this point does not have an ".mvc" extension anywhere in it. (More on this below.)Next, the
Application_AuthenticateRequest
event is fired. Again, the forms data is present, and the URL has no ".mvc" extension.At this point, what I would expect to happen is for the
Application_PostAuthenticateRequest
event to fire. But what acutally happens is thatApplication_BeginRequest
is called again. This time, the forms data is gone-- it's not inForms
,Params
, or anywhere else. In addition, the URL has changed so that the controller name part of the Url has an ".mvc" extension tacked onto it. For instance, if the URL in steps 1 and 2 is "/Education/Manage", then in step 3 it shows up as "/Education.mvc/Manage".The
Application_AuthenticateRequest
event is fired again. Again, the forms data is missing, and the URL has an ".mvc" extension embedded in it.This time,
Application_PostAuthenticateRequest
is fired, and the rest of the page's life cycle proceeds normally. In this and all subsequent events, there's no forms data, and the ".mvc" extension remains present.
The problem only occurs when I switch to the integrated pipeline mode. It works fine in classic mode. I've been googling for days, and unfortunately I've been unable to find any reference to a similar problem. I've also tried editing the Web.config file in several different ways hoping to solve the problem, without any luck. I'm hoping somebody here can shed some light on the issue.
Here are a few relevant code snippets. If there's any other code I should include, please let me know.
From Web.config:
<system.web>
<authentication mode="Forms">
<forms name=".appLive" timeout="60" enableCrossAppRedirects="true" path="/" />
</authentication>
[...]
</system.web>
[....]
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="ScriptModule" />
<remove name="UrlRoutingModule" />
<add name="ScriptModule" preCondition="managedHandler" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, System.Web.Routing, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<remove name="FormsAuthenticationModule" />
<remove name="UrlAuthorization" />
<remove name="DefaultAuthentication" />
<add name="DefaultAuthentication" type="System.Web.Security.DefaultAuthenticationModule" />
</modules>
<handlers>
<remove name="AboMapperCustom-17403419" />
<remove name="WebServiceHandlerFactory-Integrated" />
<remove name="ScriptHandlerFactory" />
<remove name="ScriptHandlerFactoryAppServices" />
<remove name="ScriptResource" />
<add name="ScriptHandlerFactory" verb="*" path="*.asmx" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptHandlerFactoryAppServices" verb="*" path="*_AppService.axd" preCondition="integratedMode" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="ScriptResource" preCondition="integratedMode" verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="MvcHttpHandler" preCondition="integratedMode" verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<add name="AboMapperCustom-17403419" path="*.mvc" verb="GET,POST,HEAD,DEBUG" modules="IsapiModule" scriptProcessor="C:\Windows\microsoft.net\framework\v2.0.50727\aspnet_isapi.dll" resourceType="Unspecified" requireAccess="Script" preCondition="classicMode,bitness32,runtimeVersionv2.0" responseBufferLimit="0" />
</handlers>
</system.webServer>
From Global.aspx:
public void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = source as HttpApplication;
if (source != null)
{
if (application.Request.AppRelativeCurrentExecutionFilePath.Contains(".mvc"))
{
application.Context.RewritePath(application.Request.Url.PathAndQuery.Replace(".mvc", string.Empty));
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您是否有机会使用 URL 重写器或通配符映射来支持经典模式?对于集成模式,您不需要此功能,应该将其关闭。
Are you by any chance using a URL rewriter or wildcard mapping to support classic mode? You don't need this for integrated mode and should turn it off.