Context is null in the global.asax file - asp.net

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.

Related

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.

Event handlers can only be bound to HttpApplication events during IHttpModule initialization

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

ASP.NET Application Lifecycle - how to check configuration properties exist?

I've written a singleton class that exposes the web.config properties in a nice get property kind of way.
I want a Load method to parse the data in the config and set the public properties, and I want to throw exceptions (so they are logged in the EventLog) when a configuration key is missing or can't be parsed.
I tried placing the Load() code in Application_Start of the global.asax but then remembered this will only be run once, or until the application restarts.
Where is the best place to put code that you need to run 'everytime' your site is started/run by the user? I basically want the website to stop functioning if certain config properties cannot be loaded.
Thanks.
When you change your web.config file, the application pool is recycled. This means that the next hit will cause your Application_Start method to be called.
Altering the following files will also
trigger an immediate restart of the
application pool:
- web.config
- machine.config
- global.asax
- Anything in the bin directory or it's sub-directories
On that basis, as soon as your configuration is changed, it will be reloaded the next time a user hits the site, which should resolve the problem with the minimum number of configuration reloads, as opposed to reloading whenever a session starts for example. Therefore, you can do this (in your global.asax):
static bool configValid = false;
void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext context = base.Context;
HttpResponse response = context.Response;
HttpRequest request = context.Request;
// Redirect users to an alternate page if the current config is invalid
// I happen to pass the Url they were attempting to access in the query string
// that way you can give them a "try again" link
if ((!configValid) && (!request.Url.ToString().Contains("BadConfig.aspx")))
{
response.Redirect("BadConfig.aspx?originalUrl=" + context.Server.UrlEncode(request.Url.ToString()));
}
}
void Application_Start(object sender, EventArgs e)
{
// Load config and determine if it's valid, thus setting configValid to true/false
//
//
configValid = false;
}

How do I crash the App Pool?

Our ASP.NET 2 web application handles exceptions very elegantly. We catch exceptions in Global ASAX in Application_Error. From there we log the exception and we show a friendly message to the user.
However, this morning we deployed the latest version of our site. It ran ok for half an hour, but then the App Pool crashed. The site did not come back up until we restored the previous release.
How can I make the app pool crash and skip the normal exception handler? I'm trying to replicate this problem, but with no luck so far.
Update: we found the solution. One of our pages was screenscraping another page. But the URL was configured incorrectly and the page ended up screenscraping itself infinitely, thus causing a stack overflow exception.
The most common error that I have see and "pool crash" is the loop call.
public string sMyText
{
get {return sMyText;}
set {sMyText = value;}
}
Just call the sMyText...
In order to do this, all you need to do is throw any exception (without handling it of course) from outside the context of a request.
For instance, some exception raised on another thread should do it:
protected void Page_Load(object sender, EventArgs e)
{
// Create a thread to throw an exception
var thread = new Thread(() => { throw new ArgumentException(); });
// Start the thread to throw the exception
thread.Start();
// Wait a short while to give the thread time to start and throw
Thread.Sleep(50);
}
More information can be found here in the MS Knowledge Base
Aristos' answer is good. I've also seen it done with a stupid override in the Page life cycle too when someone change the overriden method from OnInit to OnLoad without changing the base call so it recursed round in cirlces through the life cycle: i.e.
protected override void OnLoad(EventArgs e)
{
//some other most likely rubbish code
base.OnInit(e);
}
You could try throwing a ThreadAbortException.

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