6

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

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

4

3 回答 3

5

可以在根 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>
于 2012-06-17T11:58:23.847 回答
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。这样做会给您带来与成为机器模块列表中的最后一个模块相同的结果。

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

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()。

如果您对错误事件执行此操作,则添加您自己的处理程序,然后以正确的顺序重新添加预先存在的委托,然后您的处理程序首先触发,然后任何其他处理程序有机会破坏偶数状态和只要您不自己更改事件状态,应用程序的其余部分似乎就更明智了。

于 2012-06-16T12:45:33.080 回答
1

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

    <add name="MyHttpModule" type="MyDll.MyHttpModule, MyDll" /> 
于 2012-06-11T21:44:41.483 回答