如何在ASP.NET应用程序中初始化

每个程序都需要初始化的过程,用来读取配置或者设置一些运行环境(变量),对于ASP.NET程序来说,又该在哪里执行初始化的任务呢?

我想应该绝大多数人都知道在Global.asax中执行初始化的过程,然而有些细节是我们需要关注的。

本文用例

在这篇博客的示例代码中,AppInitializer包含了网站的初始化的实现代码:


  1. public static class AppInitializer  
  2. {  
  3.     public static ConnectionStringSettings MyNorthwindConnectionSetting { get; private set; }  
  4.  
  5.     public static void Init()  
  6.     {  
  7.         // 读取连接字符串。  
  8.         LoadConnectionString();  
  9.  
  10.         // 设置SQLSERVER缓存依赖通知。  
  11.         SetSqlDependency();  
  12.  
  13.         // 其它的初始化操作。  
  14.         OthersInit();  
  15.     }  
  16.  
  17.     static void LoadConnectionString()  
  18.     {  
  19.         ConnectionStringSettings setting = ConfigurationManager.ConnectionStrings["MyNorthwind"];  
  20.         if( setting == null )  
  21.             throw new ConfigurationException("没有配置MyNorthwind连接字符串。");  
  22.  
  23.         if( string.IsNullOrEmpty(setting.ConnectionString) )  
  24.             throw new ConfigurationException("没有为MyNorthwind连接字符串指定内容。");  
  25.  
  26.         if( string.IsNullOrEmpty(setting.ProviderName) )  
  27.             throw new ConfigurationException("没有为MyNorthwind连接字符串指定ProviderName 。");  
  28.  
  29.         // 保存读取到的连接字符串,供程序使用。  
  30.         MyNorthwindConnectionSetting = setting;  
  31.     }  
  32.  
  33.     static void SetSqlDependency()  
  34.     {  
  35.         // 判断SQLSERVER版本是否为 2005以上版本,  
  36.         // 是否开启Service Broker的检查代码就不列出了。  
  37.  
  38.         SqlDependency.Start(MyNorthwindConnectionSetting.ConnectionString);  
  39.     }  
  40.  
  41.     static void OthersInit()  
  42.     {  
  43.         // 其它的初始化操作。  
  44.  
  45.         // 例如:  
  46.         // 1. 加载必要的缓存数据。  
  47.         // 2. 检查上传目录是不存在。  
  48.         // 3. ...................  
  49.     }  

这段代码的意图很清楚,一定要确保正确的配置了数据库连接字符串,否则以异常的形式报告出来。

示例程序还有一个页面,Default.aspx


  1. <body> 
  2.     <form id="form1" runat="server"> 
  3.     <div> 
  4.         <h1>User Login</h1> 
  5.     </div> 
  6.  
  7.         <p style="line-height: 150%;"> 
  8.             UserName: <asp:TextBox ID="txtUserName" runat="server" Width="200px" Text="Fish Li"></asp:TextBox><br /> 
  9.             Password: <asp:TextBox ID="txtPassword" runat="server" Width="200px" TextMode="Password"></asp:TextBox><br /> 
  10.             <asp:Button ID="btnLogin" runat="server" Text="登录" OnClick="btnLogin_Click" /> 
  11.         </p> 
  12.     </form> 
  13. </body> 

其实就是一个登录页面,后台代码为:


  1. protected void btnLogin_Click(object sender, EventArgs e)  
  2. {  
  3.     bool ok = false;  
  4.  
  5.     using( SqlConnection connection  
  6.         = new SqlConnection(AppInitializer.MyNorthwindConnectionSetting.ConnectionString) ) {  
  7.  
  8.         connection.Open();  
  9.  
  10.         // 其它的数据库操作。  
  11.  
  12.         ok = true;  
  13.     }  
  14.  
  15.     if( ok )  
  16.         Response.Redirect("Default2.aspx");  

你没有想到的Global.asax怪事!

或许有些人会这样写他们的初始化代码:


  1. void Application_Start(object sender, EventArgs e)  
  2. {  
  3.     //在应用程序启动时运行的代码  
  4.     try {  
  5.         AppInitializer.Init();  
  6.     }  
  7.     catch( Exception ex ) {  
  8.         LogException(ex);  
  9.           
  10.         // .....................  
  11.     }  
  12. }  

这段代码有什么问题呢?

其实问题的线索在于:为什么要加try....catch语句,是因为知道可能会发生异常吗?

如果真有异常情况发生,这样处理后,后续的请求是不是会发生各种想像不到的错误?

显然这里不能吃掉异常,要不然后面的请求肯定会有问题,因为它们依赖的设置没有正确的初始化。

好吧,那我去掉 try.....catch语句,这样总该行了吧:


  1. void Application_Start(object sender, EventArgs e)  
  2. {  
  3.     //在应用程序启动时运行的代码  
  4.  
  5.     AppInitializer.Init();  
  6. }  

还是看来一下真实的运行情况吧。

噢,抱歉,我还真忘记了配置连接字符串,这个异常提示太给力了。

现在就加上连接字符串吗?

别急,想像一下,如果这个网站是一个真实的在线网站,会是什么情况呢?
答案有二种:

1. 另一个用户也发起了一次请求。

2. 当前用户看到错误页面后,重新刷新了一次当前页面。

现在我用Opera来扮演第二个浏览用户吧,还是打开同样的网址。

太奇怪了,第二个用户居然能打开页面,好吧,让他登录试试。

结果第二个用户看到的错误情况和第一个用户完全不同。

如果此时第一个用户刷新他的浏览器,发现页面又可以显示了,然而登录时,会看到与第二个用户一样的异常信息。

这个示例代码实在太简单了,我想维护人员根据NullReferenceException这个线索找下去,很快就能找到答案。如果初始化代码再复杂一些,比如SetSqlDependency()中出现异常呢,那么程序仍然能够正常运行,但是我们期望的缓存依赖可能就没有效果了,最终可能会产生性能问题,排查的难度就会大多了。

记得以前做项目时,就遇到过这种情况,当时感到很奇怪,为什么刷新一下就没黄页了,不过后面的错误就很折腾人了,最终也让我总结了这个教训。所以我建议:如果在初始化阶段出现了异常,干脆就别让程序继续运行了,每个请求都直接显示黄页,直到排除故障为止。

如何保证初始化异常一直显示?

当初始化发生异常时,如何保证初始化异常一直显示呢?

方法其实并不难,我们需要修改一下代码:


  1. private static Exception s_initException;  
  2.  
  3. void Application_Start(object sender, EventArgs e)  
  4. {  
  5.     try {  
  6.         AppInitializer.Init();  
  7.     }  
  8.     catch( Exception ex ) {  
  9.         // 记下初始化的异常。  
  10.         s_initException = ex;  
  11.     }      
  12. }  
  13.  
  14. protected void Application_BeginRequest(object sender, EventArgs e)  
  15. {  
  16.     // 如果存在初始化异常,就抛出来。  
  17.     // 直到开发人员发现这个异常,并已解决了异常为止。  
  18.     if( s_initException != null )  
  19.         throw s_initException;  
  20. }  

现在不管有多少个用户来访问,或者第一个访问者刷新浏览器多少次,都会看到同样的异常信息:

说明:Global.asax的这个问题在IIS7以上版本的集成模式下并不存在。

以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索异常
, 字符串
, static
, sqldependency
, 代码
, 用户
, 字符串显示异常
, void
用户初始化
,以便于您获取更多的相关知识。

时间: 2024-10-18 07:45:42

如何在ASP.NET应用程序中初始化的相关文章

c#3 0-如何在c#窗口应用程序中打开一个数据库

问题描述 如何在c#窗口应用程序中打开一个数据库 在下新手,在数据库编程时做书上的例子,通过c#程序登录界面,登录到一个数据库,我使用了本地服务器.在SQL server management studio中,使用账号sa以sqlserver身份验证方式可以登录服务器名为HY-20141014UKZESQLEXPRESS的数据库引擎,并且创建了一个名为Fiancing的数据库, 参考书上的例子如下,怎么样可以在这个c#程序中登录Fiancing数据库?private void btnLogin_

CFindReplaceDialog如何在MFC对话框的程序中使用啊

问题描述 CFindReplaceDialog如何在MFC对话框的程序中使用啊 看了几篇文章代码,都实现不了,有没有谁做过这个功能的介绍下CFindReplaceDialog的详细用法? 解决方案 p_FindReplaceDlg = new CFindReplaceDialog(); p_FindReplaceDlg->Create( true m_FindString NULL FR_DOWN this ); //创建查找对话框 p_FindReplaceDlg->ShowWindow(

java-如何在web服务器端的程序中添加一个Servlet

问题描述 如何在web服务器端的程序中添加一个Servlet 如何在web服务器端的程序中添加一个Servlet servlet是用什么语言编写的 如果是java写的需要编译成.class文件吗 其他语言写的也需要编译吗 解决方案 如果是eclipse环境,那么点文件夹,直接添加,里面有模板 servlet一般是java写的类 是java写的,要运行肯定需要编译为.class 脚本语言,比如python,js不需要,编译语言都需要编译.

如何在ASP.NET 2.0中使用 Web Parts

asp.net|web Web Parts 是ASP.NET2.0中一个非常令人感兴趣的特性.它为创建动态的网页接口提供了一系列的可用控件,使得用户非常容易就可以进行配置或者个性化页面.用户可以显示.隐藏或者移动Web Parts组件.下面,我将为大家介绍一下Web Parts的概貌. 划分页面 Microsoft SharePoint的开发人员和用户可能会对Web Parts比较熟悉,因为Web Parts就是SharePoint开发环境中的一项标准属性.Web Parts是控制部分页面的软件

ASP.NET应用程序中调用EJB

摘要 本文将介绍如何实现你的ASP.NET应用程序与J2EE应用程序服务器之间的交互以及怎样使得调用EJB与调用XML Web服务一样地容易. 简介 今天,许多大型组织发现他们自己正在拥有和使用由.NET技术和J2EE技术混合组成的开发团队和发布服务器.为了平衡通过J2EE应用程序服务器发送的企业质量,公司的商业逻辑经常以企业JavaBean(EJB)的形式发布于J2EE应用程序服务器上.另一方面,为了满足日益变化的商业发展的要求,多数开发者比较喜欢在具有高度生产性能的Visual Studio

asp.net 应用程序中的服务器错误

问题描述 "/"应用程序中的服务器错误.--------------------------------------------------------------------------------未将对象引用设置到对象的实例.说明:执行当前Web请求期间,出现未处理的异常.请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息.异常详细信息:System.NullReferenceException:未将对象引用设置到对象的实例.源错误:执行当前Web请求期间生成了

在ASP.NET应用程序中捕捉身份验证状态的变化

asp.net|程序 前年我写过一篇随笔抱怨Microsoft在ASP.NET架构中Session_End事件上处理,说来惭愧,其实当年我对ASP.NET运行时的复杂性理解不足.实话说,捕捉通过身份验证和注销身份验证对我来说,意义重大.例如: 在登录前先检查是否已经存在SSO提供器: 登录完成后加载相关的权限,这些加载过程可能与具体应用项目完全无关: 登录结束后通知SSO提供器清除Cookie内容: ...... 目前的ASP.NET提供的解决方案是在Global.cs中加上FormsAuthe

如何在ASP.NET MVC 3 中利用Jsonp跨域访问

在信息系统开发的时,根据相关业务逻辑难免会多系统之间互相登录.一般情况下我们需要在多系统之间使用多个用户名和密码.这样客户就需要在多个系统之间重复登陆.每次登录都需要输入用户名和密码.最近比较流行的就是OAuth.新浪微博这个开放系统做的就很好.但OAuth并非本文讨论范畴.这里主要讨论jQuery1.5 jsonp 在Asp.net MVC3 中的应用. 本文应用场景: 假设您的开发团队欲为某集团公司开发一整套信息管理系统,目前首要开发的就是一套订单系统和一套内部OA系统.前提是这两套系统使用

二、ASP。NET程序中动态修改web.config中的设置项目 (前台页面代码)

web|程序|动态|项目|页面 <%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApplication1.WebForm1" %><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >