How to initialize in an ASP. NET application

Source: Internet
Author: User

Every program requires initialization. It is used to read configurations or set some runtime environments (variables). Where should I execute initialization tasks for ASP. NET programs?

I think most people know the initialization process in Global. asax,
However, we need to pay attention to some details.

Use Cases

In the sample code of this blog, AppInitializer contains the website initialization implementation code:

Public static class AppInitializer {public static ConnectionStringSettings MyNorthwindConnectionSetting {get; private set;} public static void Init () {// read the connection string. LoadConnectionString (); // sets the SQLSERVER cache dependency notification. SetSqlDependency (); // other initialization operations. OthersInit ();} static void LoadConnectionString () {ConnectionStringSettings setting = ConfigurationManager. connectionStrings ["MyNorthwind"]; if (setting = null) throw new ConfigurationException ("The MyNorthwind connection string is not configured. "); If (string. IsNullOrEmpty (setting. ConnectionString) throw new ConfigurationException (" the content is not specified for the MyNorthwind connection string. "); If (string. IsNullOrEmpty (setting. ProviderName) throw new ConfigurationException (" ProviderName is not specified for the MyNorthwind connection string. "); // Save the read connection string for use by the program. MyNorthwindConnectionSetting = setting;} static void SetSqlDependency () {// checks whether the SQL Server version is 2005 or later, and // checks whether the Service Broker is enabled without listing the check code. SqlDependency. Start (MyNorthwindConnectionSetting. ConnectionString);} static void OthersInit () {// other initialization operations. // Example: // 1. Load the necessary cache data. // 2. Check whether the upload directory does not exist. // 3 ....................}}

The intention of this Code is clear. Make sure that the database connection string is correctly configured; otherwise, it is reported as an exception.

The sample program also has a page, Default. aspx

<Body> <form id = "form1" runat = "server"> <div> 

It is actually a logon page, and the background code is:

Protected void btnLogin_Click (object sender, EventArgs e) {bool OK = false; using (SqlConnection connection = new SqlConnection (AppInitializer. myNorthwindConnectionSetting. connectionString) {connection. open (); // other database operations. OK = true;} if (OK) Response. Redirect ("Default2.aspx ");}
The Global. asax strange thing you didn't think!

Some may write their initialization code like this:

Void Application_Start (object sender, EventArgs e) {// code run at application startup try {AppInitializer. init ();} catch (Exception ex) {LogException (ex ); //.....................}}

What is the problem with this code?
In fact, the cause is: why do we need to add a try... catch statement because we know that exceptions may occur?
If an exception occurs, Will subsequent requests encounter unexpected errors?

Obviously, exceptions cannot be eaten here. Otherwise, the subsequent requests may be faulty because their dependent settings are not correctly initialized.

Okay, then I will remove the try... catch statement, so that the total line will be:

Void Application_Start (object sender, EventArgs e) {// code that runs when the application starts AppInitializer. Init ();}

Let's take a look at the actual running situation.

Oh, sorry, I really forgot to configure the connection string,This exception prompt is awesome.

Add the connection string now?
Don't worry. Imagine what would happen if this website is a real online website?
There are two answers:
1. Another user also initiates a request.
2. The current user refresh the current page after seeing the error page.

Now I want to use Opera to play the second browsing user, or open the same URL.

It's strange that the second user can open the page. Okay, let him log on.

Result The error message displayed by the second user is different from that displayed by the first user.

If the first user refresh his browser, the page is displayed again. However, when logging on, the system will see the same exception information as the second user.

The sample code is too simple. I want the maintainer to find the answer based on the clue of NullReferenceException.
If the initialization code is more complex, for example, if an exception occurs in SetSqlDependency (), the program can still run normally,
However, our expected cache dependency may be ineffective, and performance problems may eventually occur, making it much harder to troubleshoot.

I remember this situation when I was working on a project. At that time, I felt very strange. Why is there no yellow pages when I refresh it? However, the following errors are quite confusing,
Finally, I learned this lesson.
Therefore, I suggest: if an exception occurs during the initialization phase, simply do not let the program continue to run. Each request is displayed in yellow pages until the fault is rectified.

How can I ensure that the initialization exception is always displayed?

When an exception occurs during initialization, how can I ensure that the initialization exception is always displayed?

The method is actually not difficult. We need to modify the code:

Private static Exception s_initException; void Application_Start (object sender, EventArgs e) {try {AppInitializer. Init () ;}catch (Exception ex) {// write down the initialization Exception. S_initException = ex ;}} protected void Application_BeginRequest (object sender, EventArgs e) {// If an initialization exception exists, it is thrown out. // Wait until the developer finds the exception and resolves the exception. If (s_initException! = Null) throw s_initException ;}

Now, no matter how many users are visiting or how many times the first visitor refreshes the browser, the same exception information is displayed:

Note: this problem of Global. asax does not exist in IIS7 or a later version.

What other initialization methods are available?

In addition to Application_Start in Global. asax, what other methods can be used to execute initialization tasks in ASP. NET programs?

Currently, I know three other methods:
1. AppInitialize method in App_Code.
2. Write a dedicated HttpModule.
3. PreApplicationStartMethodAttribute of ASP. NET 4.0

AppInitialize method in App_Code

ASP. NET allows us to define an AppInitialize Method for any type in App_Code. It can also be used to execute initialization tasks.

public class Class1{    public static void appInitialize()    {        AppInitializer.Init();            }}

If I run the sample program again (the code in Global. asax has been commented out), the following is displayed:

Obviously, the initialization code we expect is indeed called.

What are the limitations of this AppInitialize method?
Let's take a look at the source code of ASP. NET:

internal class BuildResultMainCodeAssembly : BuildResultCompiledAssembly{    private MethodInfo FindAppInitializeMethod(Type t)    {        return t.GetMethod("AppInitialize",             BindingFlags.Public | BindingFlags.Static | BindingFlags.IgnoreCase,             null, new Type[0], null);    }

Based on the code, we can find that the AppInitialize method has the following features:
1. It must be a Public Static method: BindingFlags. Public | BindingFlags. Static
2. method names are case insensitive: BindingFlags. IgnoreCase
3. The method does not allow input parameters: new Type [0]

HttpModule can also execute initialization tasks

HttpModule is always called in the ASP. NET pipeline, so we can also use it for initialization.

Public class InitAppModule: IHttpModule {public void Init (HttpApplication context) {// Note: The Init event may be called multiple times, so this method will be called multiple times. AppInitializer. Init ();}

As the code comment says, this call code is incorrect unless you can accept that the initialization code is called multiple times!

Therefore, we should rewrite the code in the singleton mode:

Private static readonly object s_lock = new object (); private static bool s_initOK; public void Init (HttpApplication context) {lock (s_lock) {if (s_initOK = false) {// ensure that the initialization code is executed only once. AppInitializer. Init (); s_initOK = true ;}}}

If you want the code to be simpler, you can do the following:

Public class InitAppModule: IHttpModule {static InitAppModule () {AppInitializer. init ();} public void Init (HttpApplication context) {// leave an empty method, // ASP. NET will call this method, and finally can trigger the call of the static method. }
Initialization Method added by ASP. NET 4.0

To enable some class libraries to perform initialization automatically, ASP. NET provides a new method that allows you to specify a PreApplicationStartMethodAttribute for the Assembly.

To demonstrate this usage, I moved the previous example (developed by VS2008) to a class library (developed by VS2012) and set the namespace of the class library to InitClassLibrary1.

Then, I added a call class:

namespace InitClassLibrary1{    public class Class1    {        public static void InitApp()        {            AppInitializer.Init();        }    }}

Finally, we can add an Attribute in the AssemblyInfo. cs file of the InitClassLibrary1 class library.

[assembly: System.Web.PreApplicationStartMethod(                typeof(InitClassLibrary1.Class1), "InitApp")]

Of course, you can also set it directly like below, so as not to create one more type:

[assembly: System.Web.PreApplicationStartMethod(                typeof(InitClassLibrary1.AppInitializer), "Init")]

After this setting, run the website again and you will find that our initialization code is indeed running: the yellow pages are still displayed.

Differences in various initialization Methods

I have introduced four initialization methods in ASP. NET. What are the differences between them?

Because they can all implement initialization operations, their differences are only different in the execution time,
We can use a simple method to differentiate their call locations: View abnormal call stack information.

Call Stack information when the AppInitialize method is abnormal:

Call Stack information when the HttpModule is abnormal:

Call Stack information when preapplicationstartmethodattri is abnormal:

The calling methods of the Application_Start event processor of Global. asax are different. ASP. NET uses reflection calls,
When an exception occurs, only internal exceptions are retained, and we cannot see the call stack (if you don't believe it, try it yourself ).

It doesn't matter. Since ASP. NET does not tell us to call the stack information, we can also retrieve it by ourselves. Please refer to the following code:

void Application_Start(){    System.Diagnostics.StackTrace stack = new System.Diagnostics.StackTrace();    System.IO.File.WriteAllText("h:\\Application_Start_stack.txt", stack.ToString());}

Open the file and check it.

Note: The Application_Start event processor of Global. asax has several equivalent methods:

// Both methods can implement the same behavior as Application_Start (object sender, EventArgs e. Void Application_OnStart () {}void Application_Start (){}

Based on the above analysis, we can know that:
1. The time when AppInitialize and preapplicationstartmethodattrie point to the method is called occurs when ASP. NET creates the host environment, which is a relatively early time.
2. Call Application_Start and HttpModule later.

Is this conclusion useful?
In fact, I don't think it makes much sense, but I just want to analyze it to satisfy my curiosity and curiosity. Do you have such curiosity?
If you are still curious about the sequence of execution timing of these four methods, I can also tell you:
1. the method that PreApplicationStartMethodAttribute points.
2. appInitialize method in App_Code.
3. Application_Start.
4. HttpModule

In the development environment, when we compile a website, the methods pointed to by PreApplicationStartMethodAttribute may be called, which is executed on the assembly of the class library for modification.

Which initialization method should I choose?

Today, we have introduced four initialization methods in ASP. NET. Some may wonder which initialization method should be selected?

Indeed, the more methods, the more confusing.
The following points only represent my personal suggestions. You can also choose one based on your preferences.

1. Select Application_Start first (although you need to write more code in the Classic Mode of IIS), becauseAnyone will think of it when looking for initialization code.To facilitate maintenance by others.

2. Although the AppInitialize method is easy to useNot suitable for WebApplication Projects.

3. PreApplicationStartMethodAttribute only supports ASP. NET 4.0 and later versions, andEspecially suitable for internal initialization of Class Libraries.

4. When none of the above methods is available,HttpModule will be the final lifelineIt is suitable for all ASP. NET versions.

Click here to download the sample code

If you believe that reading this blog has some benefits, click 【Recommendation] Button.
If you want to discover my new blog more easily, click 【Follow Fish Li].
Because my enthusiasm for writing is inseparable from your support.

Thank you for reading this article. If you are interested in the content of my blog, please continue to follow up on my blog. I am Fish Li.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.