asp.net – 两次调用HttpModule EndRequest处理程序

我正在尝试为在WCF中实现并托管在Azure上的REST服务实现身份验证.我正在使用HttpModule来处理AuthenticationRequest,PostAuthenticationRequest和EndRequest事件.如果Authorization标头丢失或其中包含的标记无效,则在EndRequest期间我将响应的StatusCode设置为401.但是,我已确定EndRequest被调用两次,而在第二次调用时响应已经有标题set,导致设置StatusCode的代码抛出异常.

我向Init()添加了锁,以确保处理程序没有被注册两次;还是跑了两次. Init()也运行了两次,表明正在创建两个HttpModule实例.但是,在VS调试器中使用Set Object ID似乎表明请求实际上是不同的请求.我在fiddler中验证过,浏览器只向我的服务发出了一个请求.

如果我切换到使用global.asax路由而不是依赖于WCF服务主机配置,处理程序只调用一次,一切正常.

如果我将配置添加到system.web配置部分以及Web.config中的system.webServer配置部分,则只调用一次处理程序,一切正常.

所以我有缓解,但我真的不喜欢我不理解的行为.为什么处理程序被调用两次?

这是问题的最小重复:

Web.config文件

<system.web>
    <compilation debug="true" targetFramework="4.0" />
    <!--<httpModules>
      <add name="AuthModule" type="TestWCFRole.AuthModule,TestWCFRole"/>
    </httpModules>-->
  </system.web>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="WebBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior>
          <!-- To avoid disclosing Metadata information,set the value below to false and remove the Metadata endpoint above before deployment -->
          <serviceMetadata httpGetEnabled="true" />
          <!-- To receive exception details in faults for debugging purposes,set the value below to true.  Set to false before deployment to avoid disclosing exception information -->
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" />
    <services>
      <service name="TestWCFRole.Service1">
        <endpoint binding="webHttpBinding" name="RestEndpoint" contract="TestWCFRole.IService1" bindingConfiguration="HttpSecurityBinding" behaviorConfiguration="WebBehavior"/>
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost/" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
      </webHttpEndpoint>
    </standardEndpoints>
    <bindings>
      <webHttpBinding>
        <binding name="HttpSecurityBinding" >
          <security mode="None" />
        </binding>
      </webHttpBinding>
    </bindings>
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="AuthModule" type="TestWCFRole.AuthModule,TestWCFRole"/>
    </modules>
    <directorybrowse enabled="true"/>
  </system.webServer>

Http模块:

using System;
using System.Web;

namespace TestWCFRole
{
    public class AuthModule : IHttpModule
    {
        /// <summary>
        /// You will need to configure this module in the web.config file of your
        /// web and register it with IIS before being able to use it. For more information
        /// see the following link: http://go.microsoft.com/?linkid=8101007
        /// </summary>
        #region IHttpModule Members

        public void dispose()
        {
            //clean-up code here.
        }

        public void Init(HttpApplication context)
        {
            // Below is an example of how you can handle LogRequest event and provide 
            // custom logging implementation for it
            context.EndRequest += new EventHandler(OnEndRequest);
        }

        #endregion

        public void OnEndRequest(Object source,EventArgs e)
        {
            HttpContext.Current.Response.StatusCode = 401;
        }
    }
}

解决方法

对不起,为什么它可以被调用两次没有任何线索,但是EndRequest最终可能因多种原因被调用.请求完成,请求被中止,发生了一些错误.因此,我不相信假设如果你到达那里,你实际上有401,这可能是出于其他原因.

我只是将我的逻辑保留在AuthenticateRequest管道中:

public class AuthenticationModule : IHttpModule
    {
        public void dispose() { }

        public void Init(HttpApplication context)
        {
            context.AuthenticateRequest += Authenticate;
        }

        public static void Authenticate(object sender,EventArgs e)
        {
            // authentication logic here            
            //.............

            if (authenticated) {
                HttpContext.Current.User = new System.Security.Principal.GenericPrincipal(myUser,myRoles);
            }

            // failure logic here           
            //.............         
        }
    }

相关文章

这篇文章主要讲解了“WPF如何实现带筛选功能的DataGrid”,文...
本篇内容介绍了“基于WPF如何实现3D画廊动画效果”的有关知识...
Some samples are below for ASP.Net web form controls:(fr...
问题描述: 对于未定义为 System.String 的列,唯一有效的值...
最近用到了CalendarExtender,结果不知道为什么发生了错位,...
ASP.NET 2.0 page lifecyle ASP.NET 2.0 event sequence cha...