HTTP module session not being set in extensionless page - c#

I have a HTTP module that I have written that needs to access the session. I have done the following:
Module is registered in web.config
Module attaches my method call to the PostAcquireRequestState event
The module implement IRequiresSessionState
However, when my page doesn't have an extension (i.e. as when htp://www.mywebsite.com) the session is not available and my code fails. If the page does have an aspx extension then all is ok.

You need to have an item that is processed by ASP.NET in order for your module to be part of the request life-cycle. Serving a page like index.html won't accomplish that. An ASPX page will.

The code from the following thread does the trick (1):
public class Module : IHttpModule, IRequiresSessionState
{
public void Dispose()
{
}
void OnPostMapRequestHandler(object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
if (app.Context.Handler is IReadOnlySessionState || app.Context.Handler is IRequiresSessionState)
return;
app.Context.Handler = new MyHttpHandler(app.Context.Handler);
}
void OnPostAcquireRequestState(object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
MyHttpHandler resourceHttpHandler = HttpContext.Current.Handler as MyHttpHandler;
if (resourceHttpHandler != null)
HttpContext.Current.Handler = resourceHttpHandler.OriginalHandler;
}
public void Init(HttpApplication httpApp)
{
httpApp.PostAcquireRequestState += new EventHandler(OnPostAcquireRequestState);
httpApp.PostMapRequestHandler += new EventHandler(OnPostMapRequestHandler);
}
public class MyHttpHandler : IHttpHandler, IRequiresSessionState
{
internal readonly IHttpHandler OriginalHandler;
public void ProcessRequest(HttpContext context)
{
throw new InvalidOperationException("MyHttpHandler cannot process requests.");
}
public MyHttpHandler(IHttpHandler originalHandler)
{
OriginalHandler = originalHandler;
}
public bool IsReusable
{
get { return false; }
}
}
}

It turns out its an II7 issue, see here:
http://forum.umbraco.org/yaf_postst9997_ContextSession-always-null-on-top-umbraco-page.aspx

Related

how to add access security to a function caused by an event in asp.net c#

ASP.NET C#
I have a question, how can I make an access control to a request provided by a botton, to stop the execution of the function, I need something generic in which it can be configured and say that roles or profiles can access to certain functions request Executed by a button.
I don't want something like that
protected void DownloadFile_ServerClick(object sender, EventArgs e)
{
if (RoleAdmin)
{
// do something
}
}
I need something that directly validates in the request of the pag when the method is executed, to see if that profile matches with the method stored in the base, so I do for all pag and do not have to put it in hard in each one of the executed methods.
I need the name of fucntion that is request.
public class PageBase : Page
{
protected override void OnLoad(EventArgs e)
{
***How to capture the function name of request ???***
if (User.Identity.IsAuthenticated == false) { Response.Redirect("~/Account/login.aspx?ReturnUrl=/admin"); };
if (!(User.IsInRole("admin") || User.IsInRole("super user"))) { Response.Redirect("/"); };
}
}
Maybe with this:
public class StaticObjects
{
public static string UserRole
{
get
{
try
{
return (string)HttpContext.Current.Session["UserRole"];
}
catch (Exception)
{
return "";
}
}
set
{
HttpContext.Current.Session["UserRole"]=value;
}
}
public static bool AuthorizeExecution(EventHandler method)
{
bool autorized = YourDataBaseQuery(UserRole, method.Method.Name);
return autorized;
}
}
////////////////////////////// ANOTHER FILE /////////////////
public static void DownloadFile_ServerClick(object sender, EventArgs e)
{
//You send the method itself because it fits the delegate "EventHandler"
if(!StaticObjects.AuthorizeExecution(DownloadFile_ServerClick))
return;
}

HttpModule and IoC in ASP.Net

So I had this problem where I absolutely needed to use the IoC of the solution I was working (and Am working) on but also needed to use an HttpModule to redirect the request before it even got in the container.
Well I found some ways to do it that weren't what I needed nor wanted.
I didn't want to add a dependency to a library to use it on just an HttpModule.
Well after fiddling a little with the module I got to a success.
It may not be pretty, it may cause some eye soreness, but it's working!
It will only actually use the EndRequest once and a simple boolean comparison isn't that costly. Also if for some reason the service isn't resolved propperly, it will use the EndRequest again. "Simple"!
I hope to have helped all the others that had the same problem as me!
public sealed class ChannelRedirectionModule : IHttpModule
{
private readonly Func<IChannelRedirectionService> _channelRedirectionService;
private static bool _firstCall = true;
public ChannelRedirectionModule()
{
_channelRedirectionService = DependencyResolver.Current.GetService<Func<IChannelRedirectionService>>();
}
public void Init(HttpApplication context)
{
context.BeginRequest += (sender, e) =>
{
if (!_firstCall)
{
Redirect(sender, e);
}
};
context.EndRequest += (sender, e) =>
{
if (_firstCall)
{
Redirect(sender, e);
}
};
}
private void Redirect(object sender, EventArgs e)
{
var app = (sender as HttpApplication);
var channelRedirectionService = _channelRedirectionService();
if (channelRedirectionService == null)
{
_firstCall = true;
return;
}
_firstCall = false;
string redirectUrl = channelRedirectionService.GetRedirectAddressForChannelId(app.Request);
if (!string.IsNullOrEmpty(redirectUrl))
{
app.Response.Redirect(redirectUrl);
}
}
public void Dispose()
{
//there's realy nothing to be disposed here,
//but we're enforced to have this by the IHttpModule interface...
}
}

Checking the status of an External System on Application Startup

We are developing an ASP.NET MVC web application that is dependent on another system for some of it's data. (The merits of this choice are outside the scope of this question)
When our web application starts up we need it to check the status of the other system. We do this by logging in to it using a HTTPCLient request.
If the system does not respond or the credentials are incorrect, then our system should not start either, and redirect the user to an Error page. If the login is successful, we grab a load of data from it, and put it into our local cache.
The problem i'm having is that the user is not directed to the error page, the are directed to our application login page instead.
Here's my Global ASAX.
private bool _externalSystemAvailable;
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
AutomapperConfiguration.Configure();
_externalSystemAvailable = ExternalSystem.Login();
}
protected void Application_BeginRequest(object source, EventArgs e)
{
var app = (HttpApplication) source;
var ctx = app.Context;
FirstRequestInitialisation.Initialise(ctx, _externalSystemAvailable);
}
I have another class based on this that checks whether the application is initialised already and performs the necessary post initialisation routines. I have this class so that the check is not performed on every request.
public class FirstRequestInitialisation
{
private static bool _alreadyInitialized = false;
private static object _lock = new object();
public static void Initialise(HttpContext context, bool _xternalSystemAvailable)
{
if (_alreadyInitialized)
{
return;
}
lock (_lock)
{
if (_alreadyInitialized)
{
return;
}
}
if ( !externalSystemAvailable)
{
HttpContext.Current.RewritePath("/Home/Error");
}
_alreadyInitialized = true;
}
}
the HttpContext.Current.RewritePath("/Home/Error");is being hit, but the user is not being redirected.
You can redirect user in Application_BeginRequest
protected void Application_BeginRequest(object source, EventArgs e)
{
if (!externalSystemAvailable)
{
Response.Redirect("/Home/Error", false);
Response.StatusCode = 301;
}
}
But there is problem with above code and that is by calling Response.Redirect you create new page request which means that event fires again and again and again and it fall into infinite loop.
I think better place for doing that is Session_Start:
protected void Session_Start(object source, EventArgs e)
{
if (Session.IsNewSession && !externalSystemAvailable)
{
Response.Redirect("/Home/Error", false);
Response.StatusCode = 301;
}
}
Stupid mistake on my part. The Home Controller was restricted to authenticated users.

How can I grab the response text of web page via IIS Module?

I'm working on an IIS module that, when a web page request is made, it looks over the data being passed back to the browser and replaces certain keywords with approved keywords. I realize there are multiple ways to do this, but for our purposes an IIS module will work best.
How can I read the stream of data being send back to the browser into a string so that I can convert keywords as needed?
Any help would be GREATLY appreciated!
Here's the code:
namespace MyNamespace
{
class MyModule : IHttpModule
{
private HttpContext _current = null;
#region IHttpModule Members
public void Dispose()
{
throw new Exception("Not implemented");
}
public void Init(HttpApplication context)
{
_current = context.Context;
context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
}
#endregion
public void context_PreRequestHandlerExecute(Object source, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
HttpRequest request = app.Context.Request;
}
}
There are two ways:
Using Response Filters
https://web.archive.org/web/20211029043851/https://www.4guysfromrolla.com/articles/120308-1.aspx
Handle the PreRequestHandlerExecute event of the application as it is run just before the IHttpHandler processes the page itself:
public class NoIndexHttpModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication context)
{
context.PreRequestHandlerExecute += AttachNoIndexMeta;
}
private void AttachNoIndexMeta(object sender, EventArgs e)
{
var page = HttpContext.Current.CurrentHandler as Page;
if (page != null && page.Header != null)
{
page.Header.Controls.Add(new LiteralControl("<meta name=\"robots\" value=\"noindex, follow\" />"));
}
}
}

http module: Request is not available

I'm creating an http module where I want to check if a request is coming from an authenticated user and redirect to the login page if it's not.
I registered the module in the web.config file and I have the following code that's throwing an exception:
public class IsAuthModule : IHttpModule
{
public void Dispose() { }
public void Init(HttpApplication TheApp)
{
var TheRequest = TheApp.Request;
}
}
It throwing an exception that says "Request is not available in this context"
What am I doing wrong?
In the Init stage you have no request in progress. You have to subscribe the event for beginning of a request:
public void Init(HttpApplication TheApp)
{
TheApp.BeginRequest += Application_BeginRequest;
// End Request handler
//application.EndRequest += Application_EndRequest;
}
private void Application_BeginRequest(Object source, EventArgs e)
{
// do something
}

Categories