IHttpModule is not being called for my WebMethod - asp.net

Ok, so I have an existing application to which I have added a custom HttpModule. I'm registering two events in the Init() method (PreRequestHandlerExecute and PostRequestHandlerExecute). The HttpModule gets called for every 'normal' request. But not I have created an .aspx containing a few WebMethods that are being called for ajaxifying some UI components. The WebMethod gets called nicely, but the trouble is that my HttpModule does NOT get called at all (no events, no init, even no constructor) when accessing the WebMethod. The module gets called nicely when accessing the .aspx in question as a 'normal' request. But it refuses to be called when calling the WebMethod.
My .aspx looks like this:
public partial class SelectionListService : System.Web.UI.Page
{
[WebMethod]
[ScriptMethod]
public static RadComboBoxData GetItemsAsRadComboBoxData(RadComboBoxContext context)
{
...
}
}
My HttpModule look like this:
public class MyModule : IHttpModule, IRequiresSessionState
{
public MyModule ()
{
}
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += new EventHandler(Application_PreRequestHandlerExecute);
context.PostRequestHandlerExecute += new EventHandler(Application_PostRequestHandlerExecute);
}
private void Application_PreRequestHandlerExecute(object sender, EventArgs e)
{
...
}
private void Application_PostRequestHandlerExecute(object sender, EventArgs e)
{
...
}
}
I have been digging into this for quite some time now, but I just can't get it to work. Any ideas?
PS1: the BeginRequest, etc in global.asax.cs do get called when accessing the WebMethod.
PS2: I'm running IIS7 on Windows7.

since PageMethods must be static, an instance of the Page class with all it's events and the ASP.NET pipeline never happens. You simply get the result of your PageMethod call, and that is all.

I have a project that had the same problem. We found that the first event in the pipeline that we could get to fire for the WebMethods was the AcquireRequestState event. We hooked into that with our HttpModule in order to do the authorization checking required for the application.
I don't know what your pre and post request handlers do, but maybe you could shift some of the logic into the AcquireRequestState event handler.

Related

Is there any built in Events in asp.net which triggers for all PageLoads?

After Completing My asp Project I came up with a new requirement. For this, I have to Execute some code in all page Load events. Can I get an event for all those page loads? I can't use Session_start of Global.asax since it will include WebHandlers with Session State. Any Ideas?
You keep a Base Page and Inherit it from all aspx pages. In this way you can keep the logic centralized.
Example
Aspx Page
public partial class MyAspxPage : BasePage
{
}
Base Page
public class BasePage : Page
{
protected override void OnLoad(EventArgs e)
{
}
}
You should also leave AutoEventWireup set to false.
Session start would not be suitable as it will only be fired when a users is given a new session rather than each time a page is loaded.
There are several options, including using a base page which all of you pages inherit from. This will mean you need to remember to hook this up to all pages.
My suggestion would be to write an http module which is fired for all aspx page loads.
You will need to create a module which implements System.Web.IHttpModule.
using System;
using System.Web;
public class HelloWorldModule : IHttpModule
{
public HelloWorldModule()
{
}
public String ModuleName
{
get { return "HelloWorldModule"; }
}
// In the Init function, register for HttpApplication
// events by adding your handlers.
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)
{
// Create HttpApplication and HttpContext objects to access
// request and response properties.
HttpApplication application = (HttpApplication)source;
HttpContext context = application.Context;
string filePath = context.Request.FilePath;
string fileExtension =
VirtualPathUtility.GetExtension(filePath);
if (fileExtension.Equals(".aspx"))
{
context.Response.Write("<h1><font color=red>" +
"HelloWorldModule: Beginning of Request" +
"</font></h1><hr>");
}
}
public void Dispose() { }
}
Then hook it up in the web.config as per the example here.
<httpModules>
<add name="HelloWorldModule" type="HelloWorldModule" />
</httpModules>
You would need to check the context.Request.Path property in the module to exclude any request where the path did't meet your criteria (i.e. not ending aspx).
More info here.
https://web.archive.org/web/20200618051219/http://www.4guysfromrolla.com:80/demos/printPage.aspx?path=/articles/011404-1.aspx
I think the best solution here whould be to create a custom base page class which implements PageLoad and then inherit all your pages from it.
Something like:
public abstract class BasePage: Page
{
protected void Page_Load(object sender, EventArgs e) {
// your code
}
}
You can register base page class in web.config:
<system.web>
<!-- ... -->
<pages pageBaseType="MyWeb.UI.BasePage" />
<!-- ... -->
</system.web>

How to register delegating handlers in a MVC Application? (not Web API)

How do I register a global message handler in a MVC application?
I tried registering it in my Global.asax.cs, but this handler never gets called whenever I access any of my endpoints in all my controllers that inherit from System.Web.Mvc.Controller.
However, it does get called when I access routes all my controllers that inherit from System.Web.Http.ApiController.
This is what I put in my Global.asax.cs:
protected void Application_Start()
{
//other initializing stuff here
**GlobalConfiguration.Configuration.MessageHandlers.Add(new AuthenticationHandler());**
}
I believe you're looking for Filters. You could build something like this:
public class MyAuthorizationFilter : IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
// do your work here
}
}
and then add it to the global filters list in Application_Start:
GlobalConfiguration.Configuration.Filters.Add(new MyAuthorizationFilter());

Asp.net : HttpApplication context authentication for aspx page gets called infinite times and page never loads

I have an asp.net web application that performs some license checks before calling up the login page... if the product is not licensed then it navigates to a abc.aspx page with some error details. This license check is an HttpModule which is configured via web.config.
I have an event handler for context authentication. Whenever the abc.aspx page is called, this event is fired multiple times and the page load never happens.
on Init, i use this code to add the event handler
context.AuthenticateRequest += new EventHandler
When i use a html page, this issue does not seem to occur. The issue exists even if i use some other aspx page for example xyz.aspx...
How can stop this authentication to takes place n number of times. I have tried with HttpContext.Current.Response.End(), it stops the infinite calls, but does not load the page, the page appears blank.
Any one has any idea about this issue?
snippet of Global.asax.
<%# Application Language="C#" Inherits="Microsoft.Practices.CompositeWeb.WebClientApplication" %>
<script runat="server">
private static bool _initializedAlready = false;
private static readonly Object s_lock = new Object();
//fires once on asp.net worker process start
protected override void Application_Start(object sender, EventArgs e)
{
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (_initializedAlready)
{
return;
}
lock (s_lock)
{
if (_initializedAlready)
{
return;
}
//custom initialization code
base.Application_Start(sender, e);
_initializedAlready = true;
}
}
public override void Init()
{
base.Init();
//initialize the license module here....
licenseModule.Init(this);
}
</script>
The init() method of license module
public void Init(HttpApplication context)
{
context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
}
I think the problem is due to the fact that you are authenticating abc.aspx as well.
When you go to a page and the license check fails, it redirects to abc.aspx. Unfortunately, you did not exempt abc.aspx from this check, and it checks itself, and then redirects to itself again and again and again.
What you can do is to only attach the authenticate request event in your Init() method when the page is not "abc.aspx". Something like:
if(!context.Context.Request.RawUrl.Contains("abc.aspx"))
context.AuthenticateRequest += new EventHandler(context_AuthenticateRequest);
However, if you only want to do this check on the login page, you would be better off putting the authentication check just on the login page code behind.

Handling application-wide events without Global.asax

My project has no "global.asax" for various reasons and I can't change that (it's a component). Also, I have no access to web.config, so an httpModule is also not an option.
Is there a way to handle application-wide events, like "BeginRequest" in this case?
I tried this and it didn't work, can someone explain why? Seems like a bug:
HttpContext.Current.ApplicationInstance.BeginRequest += MyStaticMethod;
No, this is not a bug. Event handlers can only be bound to HttpApplication events during IHttpModule initialization and you're trying to add it somewhere in the Page_Init(my assumption).
So you need to register a http module with desired event handlers dynamically. If you're under .NET 4 there is a good news for you - there is PreApplicationStartMethodAttribute attribute (a reference: Three Hidden Extensibility Gems in ASP.NET 4):
This new attribute allows you to have
code run way early in the ASP.NET
pipeline as an application starts up.
I mean way early, even before
Application_Start.
So the things left are pretty simple: you need to create your own http module with event handlers you want, module initializer and attribute to your AssemblyInfo.cs file . Here is a module example:
public class MyModule : IHttpModule
{
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
}
public void Dispose()
{
}
void context_BeginRequest(object sender, EventArgs e)
{
}
}
To register module dynamically you could use DynamicModuleUtility.RegisterModule method from the Microsoft.Web.Infrastructure.dll assembly:
public class Initializer
{
public static void Initialize()
{
DynamicModuleUtility.RegisterModule(typeof(MyModule));
}
}
the only thing left is to add the necessary attribute to your AssemblyInfo.cs:
[assembly: PreApplicationStartMethod(typeof(Initializer), "Initialize")]

page event when using page methods?

I have the following that I'm using in every page:
public partial class Pages_MyPage : System.Web.UI.Page
{
ViewUserPreferencesModel TheUserPreferences;
Protected void Page_Load(object sender, EventArgs e)
{
TheUserPreferences = (ViewUserPreferencesModel)Session["SessionUserPreferences"];
And then I use a Page Method like this:
[WebMethod]
public static string GetAppointements(string DateInput)
{
ViewUserPreferencesModel TheUserPreferences = (ViewUserPreferencesModel)HttpContext.Current.Session["SessionUserPreferences"];
My question is this: Do I need to include the statement that loads user preferences when I run the page method or are the statements in the Page_Load event triggered when the page method is called, and if they are, will the variable be populated?
Thanks.
No, Page Methods do not follow the ASP.NET page lifecycle. However, even if they did, your TheUserPreferences variable won't be accessible in the static context.

Resources