Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sharing an HttpModule between multiple sub-applications without the GAC

I have a website setup in IIS with one web.config set at the root for many sub-application virtuals (about 35), some of which use their own unique overrides/configurations.

I have two HttpModules that I would like to implement for all of the sub-apps at once. Without using the GAC, is there a way to specify the implementation in web.config so that these modules can apply to all sub-apps without re-compiling module code into each sub-application? Can I store the HttpModule assembly somewhere in the site structure that it can be utilized by all sub-apps?

like image 838
NickSuperb Avatar asked Jun 06 '12 18:06

NickSuperb


2 Answers

It is possible to register a http module in the root web.config (system.webServer/modules section). The module must have a strong name (must be signed):

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

Now IIS expects that the module is in the bin directory (or in GAC). dependentAssembly section instructs IIS where can be the assembly file found:

   <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>
like image 190
Jakub Linhart Avatar answered Nov 12 '22 19:11

Jakub Linhart


Assuming the normal adding it to the web config and bin folders after the fact does not work for you there are a couple of possibilities for you in the current framework:

If you don't mind altering the web configs, but need to store the module outside the bin you can use System.Web.PreApplicationStartMethod to register a handler for AppDomain.AssemblyResolve event then have the event handler load and return the type

If you don't want to mod the web.config or need your events to be at the top of the stack like you would get by GACing it and altering the machine level web config you can use System.Web.PreApplicationStartMethod to get code to run on startup just by being in the bin directory then use Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule from the MVC Razor libraries. Doing this gives you about the same result as being the last module in the machine module list.

If you don't want to mod the web config and need to be earlier in the event stack then you need to do something to re-order the event handlers. I needed to do this once to try and debug something that was swallowing errors. A little poking about in reflector and I came up with this function to get the existing event handlers

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

If you pass the HttpApplication instance to it with an EventName you get all the registered handler delegates, which will allow you to call RemoveEventHandler() on each of them.

If you do that to the error event, then add your own handler, then re-add the pre-existing delegates in the correct order then your handler fires first, before any of the other handlers has a chance to mangle the even state and the rest of the application seems to be none the wiser as long as you don't alter the event state yourself.

like image 41
Bill Avatar answered Nov 12 '22 20:11

Bill