How to get what event raise in Http Module - c#

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

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?

Your question is very wide and the following MSDN Library documentation references might help you to understand this process:
ASP.NET Application Life Cycle Overview for IIS 5.0 and 6.0
ASP.NET Application Life Cycle Overview for IIS 7.0
Here are the events and the request pipeline for ASP.NET 4.0:
Validate the request, which examines the information sent by the browser and determines whether it contains potentially malicious markup.
Perform URL mapping, if any URLs have been configured in the UrlMappingsSection section of the Web.config file.
Raise the BeginRequest event.
Raise the AuthenticateRequest event.
Raise the PostAuthenticateRequest event.
Raise the AuthorizeRequest event.
Raise the PostAuthorizeRequest event.
Raise the ResolveRequestCache event.
Raise the PostResolveRequestCache event.
[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).
Raise the PostMapRequestHandler event.
Raise the AcquireRequestState event.
Raise the PostAcquireRequestState event.
Raise the PreRequestHandlerExecute event.
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.
Raise the PostRequestHandlerExecute event.
Raise the ReleaseRequestState event.
Raise the PostReleaseRequestState event.
Perform response filtering if the Filter property is defined.
Raise the UpdateRequestCache event.
Raise the PostUpdateRequestCache event.
[IIS 7.0] Raise the LogRequest event.
[IIS 7.0] Raise the PostLogRequest event.
Raise the EndRequest event.
Raise the PreSendRequestHeaders event.
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

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?

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.

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

Related

How to get the callback to viewmodel from library

I have a UIControl(LatestHeadline) in a view(Home.xaml)(there are around 10 more controls on the same page) which is a textblock.I want to set the text of this control when user clicks on a button(named "Retrieve") from the same view.I have to call the method in utilities library from my viewmodel .The method(GetLatestHeadline) in the utilitieslibrary connects to a web api through webclient class and it fires the (deleagate)method Retrieve_Completed event.
Once this event is completed the required data is retrieved from eventargs paramater e.Now from the utilitieslibrary I want to return the data to the viewmodel so that the I can bind this to the LatestHeadline textblock.
LatestHeadline textblock has binding to a property(named "PropHeadLine") defined in viewmodel.
Is there a way we can achieve this in C#.Net?
If you have access to the utility class from the view model, then surely you can just add a handler to your Retrieve_Completed delegate in the view model.
utilityClass.Retrieve_Completed += UtilityClassRetrieve_Completed;
utilityClass.GetLatestHeadline();
...
public void UtilityClassRetrieve_Completed(EventArgs e)
{
// Do something with your e.New value here in the view model
LatestHeadlineProperty = e.New;
}
Of course, I'm just guessing at what your Retrieve_Completed definition is here, but hopefully you get the idea.
I like the concept of a "callback" for this kind of thing -- specifically, pass an Action<string> from the View Model to the service. The service can then save a reference to the callback, or pass it along to the completed-handler in the "UserState". So, the utilities method would look something like this:
public void GetLatestHeadline(Action<string> callback)
{
_apiClient.Retrieve(userState: callback);
}
private void Retrieve_Completed(object sender, RetrieveCompletedEventArgs args)
{
var callback = args.UserState as Action<string>;
if (callback != null)
callback(args.Result.Headline);
}
Now the view model can pass a callback to the utilities method -- the callback should presumably just set the property "PropHeadLine" to the result value:
private void Button_Click()
{
Utilities.GetLatestHeadline( result => PropHeadLine = result );
}
Expose a Delegate or Event in your service, in your view model just subscribe or hook to
that delegate or event
when ever you want to notify the viewmodel Once a particular operation is completed, just invoke the delegate or event
The method which is hooked in your viewmodel will get called.
In your viewmodel now you can do the necessary actions you want

OnActionExecuting equivalent in standard asp.NET?

Is there an equivalent for MVC.NET's OnActionExecuting in standard asp.NET? ?
I thought it would be Page_Load since OnActionExecuting would be called each time an action is executed (or the page loads). But I'm running into inheritance issues when I try to use Page_Load instead.
Since it is very difficult to make my solution work with a Page_Load I'm thinking I might not have the best ... solution.
Any thoughts on whether they are equivalent or close enough?
Background:
I'm converting a piece of an MVC3 application into a standard .NET to wrap in a SharePoint Web Part.
Here's the MVC code I'm trying to translate, as you can see its the user security bits I'm translating:
protected override void OnActionExecuting(ActionExecutingContext filterContext) {
if (!SiteCacheProvider.ItemCached(enmCacheKey.SiteSetting)) {
if (filterContext.IsImplementedGeneralPrincipal()) {
IUserProfile userProfile = ((IGeneralPrincipal)filterContext.HttpContext.User).UserProfile;
SiteCacheProvider.ChangeSiteSetting(userProfile.SiteID);
}
}
base.OnActionExecuting(filterContext);
}
First, take on account that no Actions are in ASP.NET because the model is different (Event-Based) - There're no methods(actions) which you can decorate with Action Filters, it's all about the Page-Cycle events.
Second, In ASP.NET, you may use HTTP modules (HttpApplication.BeginRequest particularly) in order to intercept incoming requests to your application pages by adding your required logic.
From MSDN:
HTTP Modules use to intercept HTTP requests for modifying or utilize
HTTP based requests according to needs like authentication,
authorization, session/state management, logging, modifying Response,
URL rewriting, Error handling, Caching....
For example:
using System;
using System.Web;
using System.Collections;
public class HelloWorldModule : IHttpModule
{
public string ModuleName
{
get { return "HelloWorldModule"; }
}
public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
application.EndRequest += (new EventHandler(this.Application_EndRequest));
}
private void Application_BeginRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<h1>HelloWorldModule: Beginning of Request</h1><hr>");
}
private void Application_EndRequest(Object source, EventArgs e)
{
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
context.Response.Write("<hr><h1>HelloWorldModule: End of Request</h1>");
}
public void Dispose()
{
}
}

Event handling in a disconnected class

I am looking for a way to handle an event raised by class A in class B without coupling the classes.
The situation is that class A is a state machine. I need to send an email when a state of class A becomes Active. I would like to create a class that would listen up for that event and handle it.
I encapsulate the state logic in class A and I instantiate it from a web page (asp.net webform).
I could instantiate the email class inside the webform as well, but I do not wish to do so, in that case, the developer that codes the webform will have to hook up the logic and events. I would like to push all that logic back to the business layer. But I can't seem to have a way to do it.
in BLL
class StateHandler()
{
public event EventHandler StateChanged;
SetState(int newState)
{
// to keep things simple for sample let's assume 2 states
if (newState ==1 ) this.State = "Active";
else this.State = "Inactive";
if (this.StateChanged != null)
this.StateChanged(this, new EventArgs());
}
}
class EmailProvider()
{
SendEmail()
{
// logic to send email
}
}
Asp.net page
....
void OnSubmit_click()
{
StateHandler sh = new StateHandler();
//adds an event handler to the StateChanged event
sh.StateChanged += new EventHandler(sh_StateChanged);
//setting this will fire the StateChanged event
sh.SetState(1);
}
EventBus might be a useful pattern for your case. It is simply a message broker that passes events to registered subscribers. I don't know if there is any C# library for that. But is should be easily implemented. Have a look at guava's EventBus. It's Java but you shoud get the idea.
In a container managed situation like EJB the container handles asynchronous message dispatch. In Java/Java EE again you'd have Message Driven Beans.

How to make sure not to call http module from particular file in asp.net

I have an website under which i have 5 files
test1.aspx
test2.aspx
test3.aspx
test4.aspx
test5.aspx
i have an http module which gets called in all the pages
but i have an condition where on test5.aspx page i do not want the http module to be called what settings need to be done in order to resolve the issue?
HttpModules get run before your page lifecycle, so you'd have to match it on the request path.
Assuming your HttpModule's Init function sets up a BeforeRequest handler, something like:
public class MyModule : IHttpModule
{
public void Init(HttpApplication application)
{
application.BeginRequest += this.BeginRequest;
}
public void BeginRequest(object sender, EventArgs e)
{
var app = sender as HttpApplication;
if (app.Request.Path.Contains("test5.aspx")) {
return;
}
// Process logic for other pages here
}
}

Update UpdatePanel on different user’s web page

I have a web page (aspx). This page has a button , a UpdatePanel and a Timer. Now my problem is as follow suppose 10 users are on this page at the same time and suppose user number 3 and 8 click its button then all user’s UpdatePanel should get updated. What is right way to achieve this functionality?
Since each user is running its own copy of the web application so whats happenning on one user's browser can't be notified to the other user. One thing you could do is when one user clicks the button to update, you could save it, whereas all the user application could ping the server may be every 2 secs to know if updation happens and if so updates.
You could use a Global property. On that property, you can put an Observer pattern, and let the visitors subscribe. When you alter the Application property ( shared throughout all Sessions ), you call the Notify() method. The client Notify() method gets called, and there you put functionality to update the UpdatePanel.
This code is NOT TESTED, it is a guideline
// *** GLOBAL.ASAX
// This collection will contain all the updatepanels that need to be updated
private List<IUpdatePanelClient> _registeredClients = new List<IUpdatePanelClient>();
public static void RegisterClient(IUpdatePanelClient client)
{
_registeredClients.Add(client);
}
public static void UnregisterClient(IUpdatePanelClient client)
{
_registeredClients.Remove(client);
}
// Which client is triggering the update call ?
private IUpdatePanelClient _clientUpdating = null;
public static IUpdatePanelClient ClientUpdating
{
get { return _clientUpdating ; }
set { _clientUpdating = value; Notify(); }
}
// Notify the clients
public static void Notify()
{
foreach(IUpdatePanelClient client in _registeredClients)
{
client.Update();
}
}
// *** IUPdatePanelClient.CS
interface IUpdatePanelClient // Interface to make the calls
{
void Update();
}
// *** Your codepage
public class MyUpdatePanelPage : Page, IUpdatePanelClient // Inherit the interface
{
public void Page_Load(Object sender, EventArgs e)
{
MyUpdatePanelPage.Global.RegisterClient(this);
}
public void Btn_Click(Object sender, EventArgs e)
{
MyUpdatePanelPage.Global.ClientUpdating = this;
}
public void Update()
{
this._updatePanel1.Update();
}
}
Your question doesn't have enough information for anyone to answer properly. If there is information that you want to keep all users update-to-date on, store that information in a database. When one user edits the data from their user session, whenever other user's get their page refreshed, they will have the most updated data. If you want to have their page refreshed periodically, use a javascript timer.

Categories

Resources