Dynamically initialized httpmodule not firing for all requests - c#

If I add my HttpModule using the following method it fires for the page request only and not for any static image requests.
[assembly: PreApplicationStartMethod(typeof(MyHttpModule), "Start")]
public class MyHttpModule :
{
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(MyHttpModule));
}
}
If I register it normally within the modules section within system.webServerin the web.config the HttpModule works correctly and handles all requests.
The event handler registered in the HttpModule is the PostAuthorizeRequestevent handler
Any ideas?

Related

HttpApplication.Start event does not exist

I looked for an answer to this for quite sometime now but didn't find any.
I will refer to Application start as a stage.
Most of the documentations out there talk about the Global.asax file and the Application_Start method which is invoked only once when the first request reaches the Application, even if this behaviour is similar to subscribing to an event it's technicaly not an event.
While lifecycle events such as BeginRequest, AuthenticateRequest and so on are accessible through the application instance as events, the Application.Start is not.
I can subscribe to BeginRequest event in an HttpModule.Init() method or Global.asax Init() method but not to the Application.Start stage like so:
Module
public class MyModule : IHttpModule
{
public void Init(HttpApplication httpApplication)
{
httpApplication.BeginRequest += new EventHandler(ApplicationBeginRequest);
}
}
Global
public class Global : HttpApplication
{
public override void Init()
{
BeginRequest += new EventHandler(ApplicationBeginRequest);
}
}
My question:
Since there is no HttpApplication.Start event accessible from the Application instance, is Global.asax and the "Application_Start" method the only hope to subscribe to the Application start stage ?
After jumping to the .NET source code i found that the HttpApplicationFactory class looks for a method named Application_OnStart or Application_Start in the Global.asax file and then invokes it using reflection => ReflectOnMethodInfoIfItLooksLikeEventHandler().
I don't have the answer why HttpApplication.Start is not event but it's clearly intended to be handled in an event like fashion using Application_OnStart or Application_Start methods.

Handling Forms Authentication events in a HTTP Module

I'm creating a HTTP module by implementing IHttpModule and I'd like to handle the Authenticate event, raised by the Forms Authentication module.
The documentation only states how to handle this event from within Global.asax, how can I handle this event from within my HTTP module?
You can handle the AuthenticateRequest event of the HttpApplication that is passed to the Init method of your IHttpModule implementation:
// IHttpModule.Init
public void Init(HttpApplication context)
{
// subscribe to the AuthenticateRequest event
context.AuthenticateRequest += this.onApplicationAuthenticateRequest;
}
private void onApplicationAuthenticateRequest(object sender, EventArgs e)
{
// your code goes here
}
This article has an example of the basic authentication in Web API which uses custom HttpModule, might be helpful.

Subscribing to main app events without loading the plugin into the main app domain

I have a main application which loads a plugin into a separate app domain. In that plugin I am subscribing to an event on object passed from the main app. Creating the plugin in a separate app domain will load the plugin dll into that domain but subscribing to an event on main app object will cause the plugin dll to be loaded into the main app domain too.
I want to be able to unload the plugin domain (which works) but I also need to be able to replace the plugin dll which I cannot currently do because that dll is loaded in the main app domain (because of that subscription).
Here is a sample code that resembles my actual code (for brevity):
I have an interface called IContract which is used to instantiate the plugin:
namespace PluginShared
{
public interface IContract
{
void Init(IHostObject hostObject);
void Shutdown();
}
}
It resides in a separate PluginShared.dll. That interface defines 2 methods, Init for passing an object created in the main app and Shutdown to do the necessary cleanup in plugin before the plugin's app domain is unloaded.
IHostObject is in the same PluginShared.dll and looks like this:
namespace PluginShared
{
public interface IHostObject
{
event Action ValueChanged;
}
}
This interface is implemented by HostObject in the main app:
public class HostObject : MarshalByRefObject, IHostObject
{
public event Action ValueChanged;
public void Foo()
{
if (ValueChanged != null)
ValueChanged();
}
}
The main app code loads the plugin, calls Init and passes HostObject instance to plugin. Then calls Shutdown on the plugin and unloads the plugin domain.
private void LoadUnloadPlugin()
{
IHostObject hostObject = new HostObject();
AppDomain pluginAppDomain = AppDomain.CreateDomain("PluginAppDomain");
IContract plugin = (IContract)pluginAppDomain.CreateInstanceFromAndUnwrap(#".\Plugin1.dll", "Plugin1.Plugin1");
plugin.Init(hostObject);
plugin.Shutdown();
AppDomain.Unload(pluginAppDomain);
}
The plugin is it its own Plugin1.dll:
namespace Plugin1
{
public class Plugin1 : MarshalByRefObject, IContract
{
IHostObject myHostObject;
public void Init(IHostObject hostObject)
{
myHostObject = hostObject;
myHostObject.ValueChanged += OnValueChanged;
}
public void Shutdown()
{
myHostObject.ValueChanged -= OnValueChanged;
myHostObject = null;
}
private void OnValueChanged()
{
// Do Stuff
}
}
}
So again, the issue is that when myHostObject.ValueChanged += OnValueChanged; executes, it will load Plugin1.dll into main app domain which will lock the dll and thus prevent me to delete it.
Btw. I have many IHostObject like interfaces which define different ValueChanged like events fired by different objects. Also in general, my plugins do not subscribe to all object's events. I am mentioning this because ValueChanged event in the sample code above could be easily replaced with a method in IContract which would be called for each plugin instead of firing an event but my real implementation calls for more event-like approach.
So is there a way/technique/pattern I could use in order to be able to get selected notifications/events from the main app without loading the plugin dll into main app domain?

Custom Error Handler that uses a Master Page

I have a custom error handler class like this:
namespace AccountCenterUserControls
{
public class EWHErrorModule : IHttpModule
{
public void Init(HttpApplication app)
{
app.Error += new System.EventHandler(OnError);
}
public void OnError(object obj, EventArgs args)
{
Page myPage = (System.Web.UI.Page)HttpContext.Current.Handler;
ctx.Server.ClearError();
}
public void Dispose() { }
}
}
I've instantiated this error handler in my web.config like this:
<httpModules>
<!-- EWH Custom Error Handler -->
<add type="AccountCenterUserControls.EWHErrorModule" name="EWHErrorModule"/>
</httpModules>
It traps errors ok. My question is, how can I let my trapped error pages benefit from my masterpage? I can get to the individual masterpages from my page, but I'm not quite sure how I set the contentplaceholder when I am in this deep.
In ASP.NET the app error event can be raised at any point during the page life-cycle you may be executing your error handler at a time it is entirely illegal to modify the Page. If it is allowable you can attain a reference to the element you wish to modify or replace using FindControl. Again, if the timing is legal you can modify the controls collection of the control or add or remove controls from the control's control collection to achive the eventual desired rendering.
I hope my assumptions are correct about your situation If they are I did wonder why you do not simply implement Application_Error in Global.asax/.cs? This would be automatically wired to the ASP.NET application's OnError event. Inside that handler you would have references available to Request, Response, and Session.
Also, you should be aware that HttpContext.Current.Handler can and will return null at certain stages of the life-cycle. For example an error has occurred before the request is handed off to the handler like during authenticate request.

Custom C# HttpModule Infinite Redirect Loop

I am writing a custom c# HttpModule that will handle requests from all file types. As a simple proof of concept I have setup the module by adding a reference to the httpModules section of the web config and added application extensions for the demo IIS website with a reference to the aspnet_isapi.dll so that it currently only intercepts request for ".htm" files
But even if there is no significant code in the "OnBeginRequest" event (code below) it causes an infinite redirect loop. I am using IIS 5 on XP Anyone got any ideas?
So far I have only seen HttpModule examples for use with ASPX files but surely you can configure the for any file type?
#region IHttpModule Members
public void Dispose() { }
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(OnBeginRequest);
}
///
///
///
///
public void OnBeginRequest(Object s, EventArgs e)
{
HttpApplication context = s as HttpApplication;
Uri currentURL = context.Request.Url;
string pageName = currentURL.Segments.Last().ToLower();
}
#endregion
OK. The problem was actually in the HttpModule itself.
It appears that you have to use the HttpApplication context in order for it to render on the client.
For Example after you have performed all your custom logic you need to write to the context:
context.Response.Write("/n/r");
//or
context.Response.Redirect("test.htm");
Everything then renders as you would expect

Categories

Resources