1

I want to get what event in what class cause request from server in Http Module.

I mean foe example : when user clicks on a button in Page1 I want to get : Button1_Click in Page1 class or when user changes a dropdown list selected index in that page I want to get DropdownList1_SelectedIndexChange in Page1 class.

thanks

Mike Beeler
  • 4,081
  • 2
  • 29
  • 44
Arian
  • 12,793
  • 66
  • 176
  • 300

5 Answers5

2

Page events are associated with the page. modules are lifecycle events. You won't see any click type event from events modules listen to like these from another post

BeginRequest
AuthenticateRequest
AuthorizeRequest
ResolveRequestCache
AcquireRequestState
PreRequestHandlerExecute
PostRequestHandlerExecute
ReleaseRequestState
UpdateRequestCache
EndRequest

HTTPModule Event Execution Order?

Community
  • 1
  • 1
Peter Kellner
  • 14,748
  • 25
  • 102
  • 188
1

Your question is very wide and the following MSDN Library documentation references might help you to understand this process:

Here are the events and the request pipeline for ASP.NET 4.0:

  1. Validate the request, which examines the information sent by the browser and determines whether it contains potentially malicious markup.
  2. Perform URL mapping, if any URLs have been configured in the UrlMappingsSection section of the Web.config file.
  3. Raise the BeginRequest event.
  4. Raise the AuthenticateRequest event.
  5. Raise the PostAuthenticateRequest event.
  6. Raise the AuthorizeRequest event.
  7. Raise the PostAuthorizeRequest event.
  8. Raise the ResolveRequestCache event.
  9. Raise the PostResolveRequestCache event.
  10. [IIS 5.0/6.0] Based on the file name extension of the requested resource (mapped in the application's configuration file), select a class that implements IHttpHandler to process the request. If the request is for an object (page) derived from the Page class and the page needs to be compiled, ASP.NET compiles the page before creating an instance of it. [IIS 7.0] Raise the MapRequestHandler event. An appropriate handler is selected based on the file name extension of the requested resource. The handler can be a native-code module such as the IIS 7.0 StaticFileModule or a managed-code module such as the PageHandlerFactory class (which handles .aspx files).
  11. Raise the PostMapRequestHandler event.
  12. Raise the AcquireRequestState event.
  13. Raise the PostAcquireRequestState event.
  14. Raise the PreRequestHandlerExecute event.
  15. Call the ProcessRequest method (or the asynchronous version IHttpAsyncHandler.BeginProcessRequest) of the appropriate IHttpHandler class for the request. For example, if the request is for a page, the current page instance handles the request.
  16. Raise the PostRequestHandlerExecute event.
  17. Raise the ReleaseRequestState event.
  18. Raise the PostReleaseRequestState event.
  19. Perform response filtering if the Filter property is defined.
  20. Raise the UpdateRequestCache event.
  21. Raise the PostUpdateRequestCache event.
  22. [IIS 7.0] Raise the LogRequest event.
  23. [IIS 7.0] Raise the PostLogRequest event.
  24. Raise the EndRequest event.
  25. Raise the PreSendRequestHeaders event.
  26. Raise the PreSendRequestContent event.

Note: The MapRequestHandler, LogRequest, and PostLogRequest events are supported only if the application is running in Integrated mode in IIS 7.0 and with the .NET Framework 3.0 or later.

References to follow: HTTP Handlers and HTTP Modules Overview

Yusubov
  • 5,815
  • 9
  • 32
  • 69
1

The events that you are looking for are specific to the asp.net page model. Http module is at a lower level ( transport based ) and would not be used to capture page events.

Can you provide more detail please?

Mike Beeler
  • 4,081
  • 2
  • 29
  • 44
  • I want to develop a security system that add some attributes to event (for roles that can access to this event) and check authorization using session and this attributes.I want to get event name and then attributes that belong to it and check authorization – Arian Jan 07 '13 at 04:37
  • Two different event models one for the page (asp.net controls) and one for the transport of web requests / responses. I don't see how this would be possible using a http module. – Mike Beeler Jan 07 '13 at 14:56
1

I'm going to suggest that if you are starting with a website to inherit a class from page and make all your pages to inherit from this class.

public abstract class LoggingPage : System.Web.UI.Page
{
    protected override void RaisePostBackEvent(
        IPostBackEventHandler sourceControl, string eventArgument)
    {
        //doing something with the information.
        EventLog.WriteEntry("Page event for " + sourceControl.UniqueID + " at " + this.Request.Url);

        //then call the base implementation
        base.RaisePostBackEvent(sourceControl, eventArgument);
    }
}

If you need to get the information of the event because of exceptions and you never get to RaisePostBackEvent, then you will need to handle PreRequestHandlerExecute of HttpApplication in your module and get 2 fields in the request

public class LoggingModule : System.Web.IHttpModule
{
    private HttpApplication _app;

    public void Dispose() 
    {
        this._app.PreRequestHandlerExecute -= new EventHandler(this.PreRequestExecution);
    }

    public void Init(HttpApplication application)
    {
        this._app = application;
        this._app.PreRequestHandlerExecute += new EventHandler(this.PreRequestExecution);
    }

    private void PreRequestExecution(object sender, EventArgs e)
    {
        var request = this._app.Context.Request;
        var target = request.Form["__EVENTTARGET"];
        var arg = request.Form["__EVENTARGUMENT"];
        //this gives you enough information about events
        //you need to check if they are null before using them (target and arg)
        //through the same request you can get extra info including URL
    }
}

UPDATE:
If your concern is security and since you have roles implemented in your system I would recommend to make use of System.Security.Permissions.PrincipalPermissionAttribute to decorate your event handlers like this:

protected void Page_Load()
{
    myButton.Click += new EventHandler(this.myButton_Click);
}

[PrincipalPermission(SecurityAction.Demand, Role = "Administrator")]
private void myButton_Click(object sender, EventArgs e)
{
    //your code to handle the event
}

You can add the attributes multiple times to fit your needs.

hope this helps.

Arturo Martinez
  • 3,737
  • 1
  • 22
  • 35
1

Regarding your question I noticed the remark:

I want to develop a security system that add some attributes to event (for roles that can access to this event) and check authorization using session and this attributes.I want to get event name and then attributes that belong to it and check authorization

Because events are registered in the class, which is not available during the Module/Handler phase, what you ask cannot be done.

However, there are always options, and I can see what you're trying to achieve :-) My solution is to simply register all events by calling a method (myEventHooks.HookAll(this);) and in the hook implementation check security (and either throwing an exception or removing all registered events when the check fails -- fill in the gaps however you see fit).

Note that when you change the Children / tree, you need to update the event hooks to bind to all their methods as well. The easiest way to do the binding is by overriding RaisePostBackEvent in a base page and then hooking everything.

This solution can be improved in a couple of different ways; most obviously making the handling more generic as well and lack of the 0-parameter handler. I kept it as simple as possible for clearance. This should get you started.

My solution has 2 parts: (1) a generic hook class and (2) the implementation in the form. Currently the solution is lazy, e.g. I put event handlers at the end, not at the front of the queue. You should be able to fix this by using GetInvocationList or something similar.

The generic hook class basically hooks the events and fires when an event is called:

public class EventHooks
{
    private class EventHooksEquality : IEqualityComparer<Tuple<string, object>>
    {
        public bool Equals(Tuple<string, object> x, Tuple<string, object> y)
        {
            return x.Item1.Equals(y.Item1) && object.ReferenceEquals(x.Item2, y.Item2);
        }

        public int GetHashCode(Tuple<string, object> obj)
        {
            return obj.Item1.GetHashCode();
        }
    }

    public void CheckSecurity(string eventName, object container) 
    {
        // Add your security code that checks attributes and the likes here
    }

    private abstract class BaseHookHandler
    {
        protected BaseHookHandler(object container, string eventName, EventHooks hooks)
        {
            this.hooks = hooks;
            this.container = container;
            this.eventName = eventName;
        }

        protected string eventName;
        protected object container;
        protected EventHooks hooks;
    }

    private class HookHandler<T1> : BaseHookHandler
    {
        public HookHandler(object container, string eventName, EventHooks hooks)
            : base(container, eventName, hooks)
        {
        }
        public void Handle(T1 t1)
        {
            hooks.CheckSecurity(eventName, container);
        }
    }

    private class HookHandler<T1, T2> : BaseHookHandler
    {
        public HookHandler(object container, string eventName, EventHooks hooks)
            : base(container, eventName, hooks)
        {
        }
        public void Handle(T1 t1, T2 t2)
        {
            hooks.CheckSecurity(eventName, container);
        }
    }
    // add more handlers here...

    public void HookAll(object obj)
    {
        foreach (var eventHandler in obj.GetType().GetEvents()) 
        {
            Hook(obj, eventHandler.Name);
        }
    }

    public void Hook(object obj, string eventHandler)
    {
        if (obj == null)
        {
            throw new Exception("You have to initialize the object before hooking events.");
        }

        // Create a handler with the right signature
        var field = obj.GetType().GetEvent(eventHandler);
        var delegateInvoke = field.EventHandlerType.GetMethod("Invoke");
        Type[] parameterTypes = delegateInvoke.GetParameters().Select((a) => (a.ParameterType)).ToArray();

        // Select the handler with the correct number of parameters
        var genericHandler = Type.GetType(GetType().FullName + "+HookHandler`" + parameterTypes.Length);
        var handlerType = genericHandler.MakeGenericType(parameterTypes);
        var handlerObject = Activator.CreateInstance(handlerType, obj, eventHandler, this);
        var handler = handlerType.GetMethod("Handle");

        // Create a delegate
        var del = Delegate.CreateDelegate(field.EventHandlerType, handlerObject, handler);

        // Add the handler to the event itself
        field.AddEventHandler(obj, del);
    }
}

Usage in the base class can be done as follows (example):

    protected override void RaisePostBackEvent(
        IPostBackEventHandler sourceControl, string eventArgument)
    {
        // Hook everything in Page.Controls
        Stack<Control> st = new Stack<Control>();
        st.Push(Page);

        while (st.Count > 0)
        {
            var control = st.Pop();
            eventHooks.HookAll(control);
            foreach (Control child in control.Controls)
            {
                st.Push(child);
            }
        }

        // Raise events
        base.RaisePostBackEvent(sourceControl, eventArgument);
    }

    private EventHooks hooks = new EventHooks();
atlaste
  • 30,418
  • 3
  • 57
  • 87
  • Thanks dear friend but can you please extend second code section.`protected override void RaisePostBackEvent(...`? I use this code to that method but it does not execute:`hooks.HookAll(Page.Controls);` please help me – Arian Jan 10 '13 at 18:26
  • There you go, implemented as stack. – atlaste Jan 11 '13 at 09:35
  • thanks dear @Stefan de Bruijn.I place a button in an empty page and I write some code in `Click` event.sorry but I don't know how I can use your code.how I can use events name to authorization? How do I use the variable `hooks`? – Arian Jan 11 '13 at 15:57
  • Place a System.Diagnostics.Debug.WriteLine("foo") in the CheckSecurity method and a breakpoint on that. Click on the button. Notice how the CheckSecurity is called while providing the information you requested (e.g. which event was fired on which object). From there on you can go on with security checks and take the appropriate action. Personally, I would use attributes for this, but I suppose that's a bit over your head judging by your comments so far; a simple switch/case or a database call or something similar will suffice I guess... – atlaste Jan 11 '13 at 16:18
  • ok.thanks.I got it.there is a pronlem.in just one click on the button `CheckSecurity` fires about 25 times.consider I want to get data from data base for autorization, it cause about 25 connection for just one click... – Arian Jan 11 '13 at 20:02
  • @Kerezo that's because multiple events are fired, such as OnPreRender and other stuff. I assume the data in your database stays the same in these 25 calls, so you can simply store that info in a variable that you check when it is called again... – atlaste Jan 11 '13 at 20:31
  • I think it's better to add just events in the code behind to `stack` isn't it?but I don't know how – Arian Jan 11 '13 at 20:34
  • No, it's better to cache the authorization data in a variable and cache it for as long as possible, to limit the number of roundtrips to the database. After all, this won't change much and usually isn't much data. Use session state, variables or a cache for this. 25 security checks shouldn't pose much of a problem; some of my frameworks used to do hundreds of security checks per click... – atlaste Jan 11 '13 at 21:50
  • Yes I understand what you said but I havae performance considerations...I'm perfectionist and I want do best works... :) – Arian Jan 12 '13 at 07:51
  • Your serious? If 25 method calls and variable checks pose a problem with performance, you should consider not running it on a 8086 but on a pentium... You should end up with 25 dictionary lookups, which are O(1) in complexity and a single roundtrip to the database (which will take most of the time). Without the database call that will take you just about 0 ms on the slowest hardware you can find. Either way, I suppose this is going more or less off-topic, since we're now going to discuss how to implement security... – atlaste Jan 12 '13 at 10:58
  • Dear @Stefan de Bruijn your answer is good and I give you prize :).Yet your comment is right for static authorization.Number of users work with my project are about 1000 person and some times their roles change with admin decision. If I want get data from database once (or even on time in day) my system fails... – Arian Jan 12 '13 at 16:06
  • Dear @Kerezo , thanks... but not what I was after to be honest. What you must ask yourself is what "realtime" means. If you query a database once per request and get all the stuff you need, that's fast enough. If there's a one second delay that's also probably fast enough for users... For computers a second or a minute is a lifetime. If you care about optimization and performance, you have to consider what matters: disk IO and network IO. A database must do a roundtrip to disk and network IO to be ACID and is therefore slow - while your application doesn't need this. That was my point. – atlaste Jan 13 '13 at 00:20