Event handlers can only be bound to HttpApplication events during IHttpModule initialization - asp.net

I am getting the following error
'Event handlers can only be bound to HttpApplication events during IHttpModule initialization.' at the following code (line in bold or double **)
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
**app.EndRequest += new EventHandler(Application_EndRequest);**
}
protected void Application_EndRequest(object sender, EventArgs e)
{
UnitOfWork.Commit();
}
which is mentioned in Global.asax file. Can anybody figure out, where I am lacking? Thanks.

The event handler lives the entire life of your application, so, you only need to add it once not add it every request. The event itself will fire every request, and the only-one handler will be called every time the event is raised.
Add it to Application_Start in global.asax not Application_BeginRequest, or better, create an HTTP Module instead.
Also, I think you may not even need an event handler. The method with current name will be called by convention similar to Page/Control AutoEventWireup (like Page_Load). Just note that this might have issues in ASP.NET MVC applications as some people report. So, my suggestion is to rename the function, add the event handler in Application_Start, or better in a new HTTP Module you create.

Try to comment out line marked with "**". Asp.Net will call appropriate methods by itself if followed by naming conventions: "{Scope}"_"{Event}", where "{Scope}" is Application if you want to handle application level events or "Session" if you want to handle session level events, and "{Event}" is name of the event, like Start, End, etc.
More info: http://msdn.microsoft.com/en-us/library/bb470252.aspx#Stages

Related

AsyncLocal Value is Null after being set from within Application_BeginRequest()

In the following example, I am setting a value to an AsyncLocal<string> variable on my HttpApplication subclass (i.e. Global.asax) from within Application_BeginRequest():
public class Global : System.Web.HttpApplication
{
public static AsyncLocal<string> AsyncLocalState = new AsyncLocal<string>();
protected void Application_BeginRequest(object sender, EventArgs e)
{
AsyncLocalState.Value = HttpContext.Current.Request.Path;
}
protected void Application_AuthenticateRequest(object sender, EventArgs e)
{
var path = AsyncLocalState.Value;
}
protected void Application_EndRequest(object sender, EventArgs e)
{
var path = AsyncLocalState.Value;
}
}
Later on, I will attempt to access the value of this AsyncLocal variable from within a handler, such as an MVC action method, or even just a plain IHttpHandler.
If I send a large enough request (e.g. a POST with more than 15KB of data -- the larger the request, the easier it is to observe), there is a very good chance that the value of AsyncLocalState is NULL when accessed from a handler even though it was set on BeginRequest.
This is reproducible from a brand-new ASP.NET project without any other libraries/modules/handlers loaded.
Is this a bug? Or maybe I'm doing something wrong? Or is ASP.NET just too unstable for this?
Addition note: the exact same behavior is observed if I instead use CallContext.LogicalGetData/CallContext.LogicalSetData.
Platform: ASP.NET, .NET 4.6.2, on Windows 7
Update: After trying to dig around, I've found a lot of references to, but nothing authoritatively saying that the ExecutionContext does not flow between ASP.NET pipeline events (except when it does?). And both AsyncLocal and the logical call context are based on the ExecutionContext.
The closest thing to an authoritative answer is this comment by David Fowl on GitHub.
The ExecutionContext does not flow between ASP.NET pipeline events if these events do not execute synchronously. Therefore, don't use AsyncLocal or the logical CallContext to persist state; use HttpContext.Items.
Update: .NET 4.7.1 adds a new callback method, HttpApplication.OnExecuteRequestStep, which per documentation "provides extensibility to the ASP.NET pipeline to make it easy for developers to implement features in ambient context scenarios and build libraries that care about ASP.NET execution flow (for example, tracing, profiling, diagnostics, and transactions)."
This is precisely what someone would need in order to restore the AsyncLocal state or the logical CallContext between ASP.NET pipeline events.

Context is null in the global.asax file

I have global.asax file, and I use this two functions to update cache value every 15 seconds by this code:
protected void Application_Start(object sender,EventArgs e)
{
Context.Cache.Insert("value","some value",null,DateTime.Now.AddSeconds(15),Cache.NoSlidingExpiration,CacheItemProirirt.Default,new CacheItemRemovedCallback(updating));
}
private void updating(string key,object value,CacheItemRemoveReason reason)
{
Context.Cache.Insert("value","updated value",null,DateTime.Now.AddSeconds(15),Cache.NoSlidingExpiration,CacheItemProirirt.Default,new CacheItemRemovedCallback(updating));
}
but it give me an NullReferenceException, and the context is null, please why I can't use context at the "updating" function?
Application_Start doesn't have any context.
The first event that does is Begin_Request.
Application_Start occurs when the particular website gets fired up for the first time, or after been recycled.
To keep the cache item renewed I suggest you do that in the Begin_Request, where you check if it's there, and if not, initiate it again.
This way it's only use memory while the site is being hit, otherwise not.

ASP.NET Session and Page Life Cycle

Let's say that in an ASP.NET .aspx page I have the Page Load method and another method for a button click event.
In the Page Load method I'm checking if the user is logged in by checking the Session. Whether he is or not, I'm storing the result in a Global Variable.
Boolean isGuest = false;
protected void Page_Load(object sender, EventArgs e) {
if(Session["id"]==null)
isGuest = true;
else
isGuest = false;
}
Let's say 20 minutes have passed, and I don't know if the Session has terminated or not, and then I click a Button, the event goes like this:
protected void Button_Click(object sender, EventArgs e) {
if(isGuest==false)
//do something
else
// do another thing
}
My Question is : When I'm clicking the button, does ASP.NET go through the Page_Load method again (check isGuest again) or it simply executes what's inside the Button_Click method, means, it uses a Boolean isGuest that could be false, but in reality the session is terminated, means it should be true.
Page_Load is triggered always before the control events.
Have a look: ASP.NET Page Life Cycle Overview
Side-note: If you want to do things only on the first load and not on every postback you have to check the IsPostBack property.
You can:
Define your own class with the UserID, and other profile properties;
Add that class to session in the global.asax session started event Session["NameReferingToYourClass"] = new YourClass();
Set a member variable to your session object early in the page life cycle mYourClass = Session["NameReferingToYourClass"] casted if you need to;
Then you can make any changes to your class anywhere in the code your member variable is available;
Save back your class with all the changes into session on the Page.Unload(..){ Session["NameReferingToYourClass"] = mYourClass.
This way you are using your class properties in your code, including UserId, pretty much like a windows application, there will be no mentioning of session anywhere else in your code.

how to get a asp.net page event on user control

I have asp.net page which loads the user controls at run time I want to capture the save/cancel event of page on the user control.
User control will be load at run time so, for further development I don't want to change my code on page level.
Any help.
I solve it, with the help of observer pattern but with some more modification because my challenge is Page don't know which user control will be load on run-time in its place holder.
I create change-manager which holds the Observers references with their intended types(submit,cancel,viewonly)
Page holds the reference of change-manager and call the notify of change manager with (eventtype(enum),response(this.response object)) then change manager calls the update method In this method call Observers, kept in the dictionary of change-manager.
Iterate the dictionary and call their updates according to their interested event types.
Now I am free to remember the user-control reference of any type of casting.
see below example of get user control from page you need to use public modifier
///user control code see event is public
public void btn1_Click(object sender, EventArgs e)
{
///do you stuff
}
/// page code
protected void Page_Load(object sender, EventArgs e)
{
uc1.btn1_Click(sender,e);
}

Global.asax, global variables, and editing with code

I have two questions:
1) I have a few global variables for my website declared in my global.asax file. They are simple, small key/value pairs and there are only a few of them. Is this a good practice for values that are small and need to be accessed by almost every page on my website? Storing them in the database and requiring a db lookup seems as thought it would waste resources for values that don't change rapidly.
2) If one of the values changes once per week, is it possible to allow a user to edit the global variable with a form or some other means?
Example:
<script runat="server">
Overloads Sub Application_Start(ByVal sender As Object, ByVal e As EventArgs)
Application("default_scoring_id") = 3
Application("week_current") = 3
End Sub
</script>
In the above example, the system needs to know which week (out of 15 of them) that the current date is within. So, once every Monday morning, the "week_current" value needs to change.
I can easily do this, but is there a way to give a user access to changing this value without touching the code?
The typical practice is to put these into the web.config, which can be edited. These <appSettings> values will then be available on every page, yet the file can be edited.
1) Good practice is usually to store those sort of values in the web.config. See here and here for some guides.
2) a) If you store this in the web.config it will be easily updatedable without the need for recompiling and the web application should immediatly pick up the changes.
b) Does updating something like the 'week number' really need to be a manual process? It sounds a bit error prone and i would suggest automating this if at all possible by calculating it based on the current date.
I would consider using the built in Cache (System.Web.Caching.Cache)
That way you can store them where ever you want (say in a database), change them from within the app easily, and have quick and cheap retrieval.
From within a class which inherits from BasePage use the given Cache object (eg Cache.Add(..)) and from elsewhere use HttpContext.Current.Cache (eg. HttpContext.Current.Cache.Remove(Key))
The other answers suggest the different ways this can be done, and must be done. But, even then if you want to allow the user to edit the global variable, you'll have to take a lock or Mutex on a shared object, change the value of your global variable, and release the lock or Mutex.
lock(globalsharedobject) //This is C# code.
{
Application("default_scoring_id") = 3;
}
Web.config is the .NET way, or ASP.NET way, it's not always the most efficent or most suitable.
You're Global.asax file is much more than some events, you can put static data in any class that subclass System.Web.HttpApplication and inherit that in your Global.asax file.
The HttpSessionState and HttpApplicationState are relics, from the classic ASP time and you would do well to avoid them, becuase the serve no real purpose.
Depending on the type (System.Type) of your objects you can design your own strongly typed objects that store information about your application and session, for application level data a bunch of static fields would be enough.
They have to be static becuase each HttpModule as well as HttpApplication instance are pooled object, so to avoid that confusion, make sure your persistent data is stored in a static or several static dicionaries. But be aware of concurrency issues when modyfying these collections. A good strategy is to lock the object, only for the duration you're modifying it and make sure you don't call any other code while modyfiny the collection, a simple swap idiom, might be helpful here, it's fast and it's a non-deadlock guarntee.
<%# Application Language="C#" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
}
void Application_End(object sender, EventArgs e)
{
// Code that runs on application shutdown
}
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
}
void Session_Start(object sender, EventArgs e)
{
// Code that runs when a new session is started
}
void Session_End(object sender, EventArgs e)
{
// Code that runs when a session ends.
// Note: The Session_End event is raised only when the sessionstate mode
// is set to InProc in the Web.config file. If session mode is set to StateServer
// or SQLServer, the event is not raised.
}
protected void Application_BeginRequest(Object sender, EventArgs e)
{
Context.Items.Add("Request_Start_Time", DateTime.Now);
}
protected void Application_EndRequest(Object sender, EventArgs e)
{
TimeSpan tsDuration = DateTime.Now.Subtract((DateTime)Context.Items["Request_Start_Time"]);
Context.Response.Write("<b>Request Processing Time: From Global.asax file " + tsDuration.ToString());
Application["time"] = tsDuration.ToString();
}
</script>

Resources