【问题标题】:Sharing an HttpModule between multiple sub-applications without the GAC在没有 GAC 的情况下在多个子应用程序之间共享一个 HttpModule
【发布时间】:2012-06-06 18:03:25
【问题描述】:

我在 IIS 中设置了一个网站,在根目录设置了一个 web.config,用于许多子应用程序虚拟(大约 35 个),其中一些使用自己独特的覆盖/配置。

我有两个 HttpModule,我想同时为所有子应用程序实现它们。在不使用 GAC 的情况下,有没有办法在 web.config 中指定实现,以便这些模块可以应用于所有子应用程序,而无需将模块代码重新编译到每个子应用程序中?我可以将 HttpModule 程序集存储在站点结构中的某个位置以供所有子应用使用吗?

【问题讨论】:

    标签: asp.net .net iis httpmodule


    【解决方案1】:

    可以在根 web.config(system.webServer/modules 部分)中注册 http 模块。模块必须有一个强名称(必须签名):

    <add name="MyModule" preCondition="managedHandler" type="MyModule.Namespace, MyModuleAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=bfd166351ed997df" />
    

    现在 IIS 期望模块位于 bin 目录(或 GAC 中)。 dependentAssembly 部分指示 IIS 在哪里可以找到程序集文件:

       <runtime>
            <assemblyBinding appliesTo="v2.0.50727" xmlns="urn:schemas-microsoft-com:asm.v1">
                <dependentAssembly>
                    <assemblyIdentity name="MyModuleAssembly" publicKeyToken="bfd166351ed997df"/>
                    <codeBase version="1.0.0.0"
                              href="file://c:/SharedLibs/MyModuleAssembly.dll" />
                </dependentAssembly>
            </assemblyBinding>
        </runtime>
    

    【讨论】:

      【解决方案2】:

      假设事后将其正常添加到 web config 和 bin 文件夹对您不起作用,在当前框架中您有几种可能性:

      如果您不介意更改 Web 配置,但需要将模块存储在 bin 之外,您可以使用 System.Web.PreApplicationStartMethod 为 AppDomain.AssemblyResolve 事件注册一个处理程序,然后使用事件处理程序加载并返回类型

      如果您不想修改 web.config 或希望您的事件位于堆栈的顶部,就像您可以通过 GAC 处理它并更改机器级别的 web 配置一样使用 System.Web.PreApplicationStartMethod 让代码在启动时运行,只需位于 bin 目录中,然后使用 MVC Razor 库中的 Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule 即可。这样做会给您带来与成为机器模块列表中的最后一个模块相同的结果。

      如果您不想修改网络配置并且需要更早地进入事件堆栈,那么您需要做一些事情来重新排序事件处理程序。我需要这样做一次以尝试调试正在吞噬错误的东西。在反射器中稍微摸索了一下,我想出了这个函数来获取现有的事件处理程序

      Dim t As Type = target.[GetType]()
      
      Public Function GetEventSubscribers(ByVal target As Object, ByVal eventName As String) As [Delegate]()
          Dim w = CType(t.GetField("_events", BindingFlags.Instance Or BindingFlags.Static Or BindingFlags.NonPublic).GetValue(target), System.ComponentModel.EventHandlerList)
          Dim k = t.GetFields(BindingFlags.[Static] Or BindingFlags.Instance Or BindingFlags.NonPublic).Where(Function(x) x.Name.StartsWith("Event" & eventName)).Select(Function(x) x.GetValue(target)).ToList()
          Dim d() As [Delegate] = k.SelectMany(Function(x)
              If w(x) Is Nothing Then
                  New [Delegate]() {}
              Else
                  Return w(x).GetInvocationList()
              End If
          End Function).ToArray
          Return d
      End Function
      

      如果您使用 EventName 将 HttpApplication 实例传递给它,您将获得所有已注册的处理程序委托,这将允许您在每个委托上调用 RemoveEventHandler()。

      如果你对错误事件这样做,然后添加你自己的处理程序,然后以正确的顺序重新添加预先存在的委托,那么你的处理程序首先触发,然后任何其他处理程序有机会破坏偶数只要您不自己更改事件状态,应用程序的其余部分似乎都不会更明智。

      【讨论】:

      • 这是一个非常有用的提示。谢谢
      【解决方案3】:

      您可以在 dll 中添加 http 模块。将 dll 放在应用程序的 bin 文件夹中,并从 web.config 中引用 http 模块

          <add name="MyHttpModule" type="MyDll.MyHttpModule, MyDll" /> 
      

      【讨论】:

        猜你喜欢
        • 2016-04-21
        • 1970-01-01
        • 2013-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-01
        • 2014-06-04
        • 2013-02-02
        相关资源
        最近更新 更多