I have a ASP.NET Visual Basics Web Application that runs on IIS 8 that needs to call Application_Start in Global.asax in order to initialize several variables. However, as far as I can tell, the method never gets called, through remote debugging or logging. The Application is run on Classic Mode.
If I run it locally on Visual Studio, I see it work
Application pool with Classic mode doesn’t have an impact on this feature. On my side, the application_Start event works properly.
Please ensure that App_global.asax.dll located in the BIN folder. We could clean, rebuild the project, and deploy it again. Moreover, during the Application_start event, we had better not write the IIS log or write/modify a database, this commonly leads to a permission issue, which seems not working.
Besides, you could verify the result by using the IIS log.
public class Global : System.Web.HttpApplication
{
public static int a = 34;
protected void Application_Start(object sender, EventArgs e)
{
a = a + 45;
}
protected void Application_BeginRequest(object sender, EventArgs e)
{
Response.AppendToLog("Application BeginRequest...."+a.ToString());
}
}
This will generate a line of record in the IIS log.
2020-08-26 05:49:10 ::1 POST /WebForm1.aspx
Application+BeginRequest....79 8001 - vabqia969VM
Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/84.0.4147.135+Safari/537.36
http://localhost:8001/WebForm1.aspx 200 0 0 3
Please refer to the below link for troubleshooting.
Application_start not working
Related
I am using the following code in the ASP.NET web forms Global.aspx page to count the number of current active users. It does work when I do local testing.
Understanding is that Application is an Application-level variable and can be accessed at the application level. So value stored in one session will be available in other sessions.
<%# Application Language="C#" %>
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
Application["TotalOnlineUsers"] = 0;
}
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
Application.Lock();
Application["TotalOnlineUsers"] = (int)Application["TotalOnlineUsers"] + 1;
Application.UnLock();
}
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.
Application.Lock();
Application["TotalOnlineUsers"] = (int)Application["TotalOnlineUsers"] - 1;
Application.UnLock();
}
</script>
But while going through this link https://learn.microsoft.com/en-us/dotnet/api/system.web.httpapplication?redirectedfrom=MSDN&view=netframework-4.8, it says that member variables can be used to store per-request data.
Based on this statement and below complete paragraph, there can be multiple instances of HttpApplication for a single application, if not application will be super slow as one HttpApplication instance can process only one request at one point in time
Because of this, each HttpApplication will have its own Application variable and the count will be saved at HttpApplication level.
Instances of the HttpApplication class are created in the ASP.NET
infrastructure, not by the user directly. One instance of the
HttpApplication class is used to process many requests in its
lifetime. However, it can process only one request at a time. Thus,
member variables can be used to store per-request data.
An application raises events that can be handled by custom modules
that implement the IHttpModule interface or by event handler code that
is defined in the Global.asax file. Custom modules that implement the
IHttpModule interface can be put in the App_Code folder or in a DLL in
the Bin folder.
So, to get the exact count without any chance of miscalculating, should I use static variables?
I believe your code will work correctly, assuming you’re using InProc session state and aren’t running in a Web farm.
Confusingly, the word “application” can have three different meanings:
Your Web application (that is, the whole Web site)
One of the multiple HttpApplication instances that serve requests to your Web application
The HttpApplication.Application property
When the documentation says that the Application property returns “the current state of an application,” it means your Web application, not an individual HttpApplication instance.
It’s true that if you add a member variable to your Global class (which inherits from HttpApplication), then the member variable won’t be shared across HttpApplication instances. But the Application property is special: it returns the same HttpApplicationState object no matter which HttpApplication instance you use to access the property. Hence, any values you add via the Application property will be shared across all HttpApplication instances. (And that’s why you must call Lock and UnLock to synchronize access; you wouldn’t need to do so if the HttpApplicationState object weren’t shared.)
I have a global.asax. and I have added a subscription to the LogRequest and BeginRequest
void Application_LogRequest(object sender, EventArgs e)
...
void Application_BeginRequest(object sender, EventArgs e)
....
First, I am not certain what is the real purpose of the LogRequest and when it should fire.
I have also done a test application and I have breakpoints in the LogRequest and BeginRequest above. Somehow the LogRequest is never being fired - it never enters in the breakpoint. And the BeinRequest is firing correctly with each request.
I have done some research online but there is very little about the LogRequest event apart from the fact that it should fire with each request ... but in my case it isn't.
I am running from VS but My website is deployed to IIS.
Many Thanks
According to MSDN Library:
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.
So perhaps you are running IIS 6.0, or IIS 7.0 (or later) in Classic mode.
The following text is from the book I'm reading, 'MCTS Self-Paced Training Kit (Exam 70-515) Web Applications Development with ASP.NET 4". It gives the rundown of the Application Life Cycle.
A user first makes a request for a page in your site.
The request is routed to the processing pipeline, which forwards it to the ASP.NET runtime.
The ASP.NET runtime creates an instance of the ApplicationManager class; this class instance represents the .NET framework domain that will be used to execute requests for your application. An application domain isolates global variables from other applications and allows each application to load and unload separately, as required.
After the application domain has been created, an instance of the HostingEnvironment class is created. This class provides access to items inside the hosting environment, such as directory folders.
ASP.NET creates instances of the core objects that will be used to process the request. This includes HttpContext, HttpRequest, and HttpResponse objects.
ASP.NET creates an instance of the HttpApplication class (or an instance is reused). This class is also the base class for a site’s Global.asax file. You can use this class to trap events that happen when your application starts or stops. When ASP.NET creates an instance of HttpApplication, it also creates the modules configured for the application, such as the SessionStateModule.
Finally, ASP.NET processes request through the HttpApplication pipleline. This pipeline also includes a set of events for validating requests, mapping URLs, accessing the cache, and more.
The book then demonstrated an example of using the Global.asax file:
<script runat="server">
void Application_Start(object sender, EventArgs e)
{
Application["UsersOnline"] = 0;
}
void Session_Start(object sender, EventArgs e)
{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] + 1;
Application.UnLock();
}
void Session_End(object sender, EventArgs e)
{
Application.Lock();
Application["UsersOnline"] = (int)Application["UsersOnline"] - 1;
Application.UnLock();
}
</script>
When does an application start? Whats the difference between session and application level? I'm rather confused on how this is managed. I thought that Application level classes "sat on top of" an AppDomain object, and the AppDomain contained information specific to that Session for that user. Could someone please explain how IIS manages Applicaiton level classes, and how an HttpApplication class sits under an AppDomain? Anything is appreciated.
Nothing lives outside an AppDomain so of course the HttpApplication has to be instantiated inside one.
Step 3 to 6 only happens ONCE in the lifetime of your application. When an ApplicationManager instance has been created it wont be created again for the next request. The same is for HostingEnvironment and HttpApplication. This means that values stored in the Application-collection will be remain there to get for all later requests during the lifetime of the application.
There is one AppDomain per application, not per session or per request.
I want to change page content while it is going from the server because i need to add some advertisements inside the html elements that are advertisement holder.
protected void Application_PreSendRequestContent(object sender, EventArgs e) this is good but i couldn't get access to HttpContext . Should i, i don't know :)
But in this method:
protected void Application_EndRequest(object sender, EventArgs e) i could get the HttpContext but i couldn't find the server response in it.
How can i do this?
You might want to implement a HttpModule instead of global.asax. You can find an example of a module that manipulates the response in MSDN: Walkthrough: Creating and Registering a Custom HTTP Module
See also this page for some additional information (e.g. why a HttpModule instead of global.asax): HTTP Handlers and HTTP Modules Overview
To answer your comment: here are some reasons why to use a module instead of global.asax (have a look at the document linked above for more information):
You can implement much of the functionality of a module in the application's Global.asax file [...] however, modules have an advantage over the Global.asax file because they are encapsulated and can be created one time and used in many different applications.
In IIS 7.0, the integrated pipeline enables managed modules to subscribe to pipeline notifications for all requests, not just requests for ASP.NET resources.
You can enable/disable a module via web.config (without touching any code)
You should use a module whenever you must create code that depends on application events, and when the following conditions are true:
You want to re-use the module in other applications.
You want to avoid putting complex code in the Global.asax file.
The module applies to all requests in the pipeline (IIS 7.0 Integrated mode only).
protected void
Application_PreSendRequestContent(object
sender, EventArgs e) this is good but
i couldn't get access to HttpContext .
Should i, i don't know :)
You can always get access to the HttpContext for the current request by using HttpContext.Current
I have a problem. While migrating from classic pipeline mode to integrated pipeline mode at IIS 7.0 we encounter the problem :
Server Error in '/' Application.
Request is not available in this context...
We found solution for this problem at
mvolo.com/blogs/serverside/archive/2007/11/10/Integrated-mode-Request-is-not-available-in-this-context-in-Application_5F00_Start.aspx
As solution shortly ,in global.asax I must forward the application_start event to Application_BeginRequest event.
void Application_Start(object sender, EventArgs e) { // sender has type 'System.Web.HttpApplicationFactory' }
Application_BeginRequest(Object source, EventArgs e) | {
// sender has type 'System.Web.HttpApplication' }
Or another solution is, Application_Start event can start later then Application_BeginRequest .
any suggestions ?
I have no option like choosing "classic mode "
Move the code to Application_BeginRequest or Session_Start. You shouldn't use the Request object in Application_Start anyway.
The Request object contains information that is specific for one page request. It doesn't really make any sense to do anything with this information in the Application_Start event.
So, change you app pool mode to classic.