asp.net夜话之十一:web.config详解收藏-周金桥

asp.net夜话之十一:web.config详解收藏                

Author: 周金桥

Date: 2008年11月10日

在开发中经常会遇到这样的情况,在部署程序时为了保密起见并不将源代码随项目一同发布,而我们开发时的环境与部署环境可能不一致(比如数据库不一样),如果在代码中保存这些配置这些信息部署时需要到用户那里更改代码再重新编译,这种部署方式非常麻烦。

在.net 中提供了一种便捷的保存项目配置信息的办法,那就是利用配置文件,配置文件的文件后缀一般是.config ,在asp.net 中配置文件名一般默认是web.config 。每个web.config 文件都是基于XML 的文本文件,并且可以保存到Web 应用程序中的任何目录中。在发布Web 应用程序时web.config 文件并不编译进dll 文件中。如果将来客户端发生了变化,仅仅需要用记事本打开web.config 文件编辑相关设置就可以重新正常使用,非常方便。
本篇要讲述的知识如下:
配置文件的查找优先级

配置文件节点说明

配置文件的操作

配置文件的查找优先级

在.net 提供了一个针对当前机器的配置文件,这个文件是machine.config ,它位于%windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG\ 文件下(%windir% 是系统分区下的系统目录,在命令行模式下输入%windir% 然后回车就能查看当前机器的系统目录,在Windows2003 及WindowsXP 中%windir% 是系统分区下的windows 目录,在Windows2000 中%windir% 是系统分区下的WinNT 目录,在笔者机器上这个系统目录是C:\WINDOWS )。这个文件里面定义了针对当前机器的WinForm 程序和asp.net 应用程序的配置。下面是machine.config 文件的内容:
 
在这个文件夹下还有一个web.config 文件,这个文件包含了asp.net 网站的常用配置。下面是这个web.config 文件的内容:
asp.net 网站IIS 启动的时候会加载配置文件中的配置信息,然后缓存这些信息,这样就不必每次去读取配置信息。在运行过程中asp.net 应用程序会监视配置文件的变化情况,一旦编辑了这些配置信息,就会重新读取这些配置信息并缓存。
当我们要读取某个节点或者节点组信息时,是按照如下方式搜索的:
(1) 如果在当前页面所在目录下存在web.config 文件,查看是否存在所要查找的结点名称,如果存在返回结果并停止查找。
(2) 如果当前页面所在目录下不存在web.config 文件或者web.config 文件中不存在该结点名,则查找它的上级目录,直到网站的根目录。
(3) 如果网站根目录下不存在web.config 文件或者web.config 文件中不存在该节点名则在%windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config 文件中查找。
(4) 如果在%windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG\web.config 文件中不存在相应结点,则在%windir%\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config 文件中查找。
(5) 如果仍然没有找到则返回null 。
所以如果我们对某个网站或者某个文件夹有特定要求的配置,可以在相应的文件夹下创建一个web.config 文件,覆盖掉上级文件夹中的web.config 文件中的同名配置即可。这些配置信息的寻找只查找一次,以后便被缓存起来供后来的调用。在asp.net 应用程序运行过程中,如果web.config 文件发生更改就会导致相应的应用程序重新启动,这时存储在服务器内存中的用户会话信息就会丢失(如存储在内存中的Session )。一些软件(如杀毒软件)每次完成对web.config 的访问时就会修改web.config 的访问时间属性,也会导致asp.net 应用程序的重启。

配置文件节点说明

web.config 文件是一个XML 文件,它的根结点是<configuration> ,在<configuration> 节点下的常见子节点有:<configSections> 、<appSettings> 、<connectionStrings> 和<system.web> 。其中<appSettings> 节点主要用于配置一些网站的应用配置信息,而<connectionStrings> 节点主要用于配置网站的数据库连接字符串信息。
<system.web> 节点主要是网站运行时的一些配置,它的常见节点有如下:
<appSettings> 节点
<appSettings> 节点主要用来存储asp.net 应用程序的一些配置信息,比如上传文件的保存路径等,以下是一个例子:

1.    
  2.        
  3.        
  4.        
  5.        
  6.    

对于<appSettings> 节点中的值可以按照key 来进行访问,以下就是一个读取key 值为“FileType” 节点值的例子:

1.    string fileType=ConfigurationManager.AppSettings["FileType "];

<connectionStrings> 节点

<connectionStrings> 节点主要用于配置数据库连接的,我们可以<connectionStrings> 节点中增加任意个节点来保存数据库连接字符串,将来在代码中通过代码的方式动态获取节点的值来实例化数据库连接对象,这样一旦部署的时候数据库连接信息发生变化我们仅需要更改此处的配置即可,而不必因为数据库连接信息的变化而需要改动程序代码和重新部署。
以下就是一个<connectionStrings> 节点配置的例子:

1.    
  2.        
  3.        
  4.    

在代码中我们可以这么实例化数据库连接对象:

1.    //读取web.config节点配置  2.    string connectionString = ConfigurationManager.ConnectionStrings["AspNetStudyConnectionString1"].ConnectionString;  3.    //实例化SqlConnection对象  4.    SqlConnection connection = new SqlConnection(connectionString);

这样做的好处是一旦开发时所用的数据库和部署时的数据库不一致,仅仅需要用记事本之类的文本编辑工具编辑connectionString 属性的值就行了。

<compilation> 节点

<compilation> 节点配置 ASP.NET 使用的所有编译设置。默认的debug 属性为“true” ,即允许调试,在这种情况下会影响网站的性能,所以在程序编译完成交付使用之后应将其设为“false” 。

<authentication> 节点

设置asp.net 身份验证模式,有四种身份验证模式,它们的值分别如下:
Mode  说明
Windows  使用Windows 身份验证,适用于域用户或者局域网用户。
Forms  使用表单验证,依靠网站开发人员进行身份验证。
Passport  使用微软提供的身份验证服务进行身份验证。
None  不进行任何身份验证。

<authentication> 节点

<authentication> 节点控制用户对网站、目录或者单独页的访问,必须配合<authentication> 节点一起使用。

<customErrors> 节点

<customErrors> 节点用于定义一些自定义错误信息的信息。此节点有Mode 和defaultRedirect 两个属性,其中defaultRedirect 属性是一个可选属性,表示应用程序发生错误时重定向到的默认URL ,如果没有指定该属性则显示一般性错误。Mode 属性是一个必选属性,它有三个可能值,它们所代表的意义分别如下:
Mode  说明
On  表示在本地和远程用户都会看到自定义错误信息。
Off  禁用自定义错误信息,本地和远程用户都会看到详细的错误信息。
RemoteOnly  表示本地用户将看到详细错误信息,而远程用户将会看到自定义错误信息。
这里有必要说明一下本地用户和远程用户的概念。当我们访问asp.net 应用程时所使用的机器和发布asp.net 应用程序所使用的机器为同一台机器时成为本地用户,反之则称之为远程用户。在开发调试阶段为了便于查找错误Mode 属性建议设置为Off ,而在部署阶段应将Mode 属性设置为On 或者RemoteOnly ,以避免这些详细的错误信息暴露了程序代码细节从而引来***的***。
下面我们添加一个页面CustomErrorsDemo.aspx ,在它的Page_Load 事件里抛出一个异常,代码如下:

1.    using System;  2.    using System.Data;  3.    using System.Configuration;  4.    using System.Collections;  5.    using System.Web;  6.    using System.Web.Security;  7.    using System.Web.UI;  8.    using System.Web.UI.WebControls;  9.    using System.Web.UI.WebControls.WebParts;  10.    using System.Web.UI.HtmlControls;  11.     12.    public partial class CustomErrorsDemo : System.Web.UI.Page  13.    {  14.        protected void Page_Load(object sender, EventArgs e)  15.        {  16.            throw new Exception("故意抛出的异常。");  17.        }  18.    }

我们先配置<customErrors> 如下:

1.    
  2.         
  3.         
  4.    

这时本地运行CustomErrorsDemo.aspx 的效果如下:

 
远程访问时看到的效果:
 
如果我们将customErrors 的Mode 属性设置为“On” 本地运行和远程访问都会看到如下效果:
 
如果将customErrors 的Mode 属性设置为“Off” 本地运行和远程访问都会看到如下效果:
 

<error> 子节点

在<customErrors> 节点下还包含有<error> 子节点,这个节点主要是根据服务器的HTTP 错误状态代码而重定向到我们自定义的错误页面,注意要使<error> 子节点下的配置生效,必须将<customErrors> 节点节点的Mode 属性设置为“On” 。下面是一个例子:

1.    
  2.         
  3.         
  4.    

在上面的配置中如果用户访问的页面不存在就会跳转到404.htm 页面,如果用户没有权限访问请求的页面则会跳转到403.htm 页面,403.htm 和404.htm 页面都是我们自己添加的页面,我们可以在页面中给出友好的错误提示。

<httpHandlers> 节点

<httpHandlers> 节点用于根据用户请求的URL 和HTTP 谓词将用户的请求交给相应的处理程序。可以在配置级别的任何层次配置此节点,也就是说可以针对某个特定目录下指定的特殊文件进行特殊处理。

下面是与machine.config 文件同一目录下的web.config 文件中的<httpHandlers> 节点配置:

1.    
  2.                
  3.                
  4.                
  5.                
  6.                
  7.                
  8.                
  9.                
  10.                
  11.                
  12.                
  13.                
  14.                
  15.                
  16.                
  17.                
  18.                
  19.                
  20.                
  21.                
  22.                
  23.                
  24.                
  25.                
  26.                
  27.                
  28.                
  29.                
  30.                
  31.                
  32.                
  33.                
  34.                
  35.                
  36.                
  37.                
  38.                
  39.                
  40.                
  41.                
  42.                
  43.                
  44.                
  45.                
  46.                
  47.                
  48.                
  49.                
  50.            

从上面的配置中可以看出,针对*.mdf 、*.ldf 文件的Get 或者Post 请求都会交给System.Web.HttpForbiddenHandler 来处理,处理的结果就是用户不能查看或者下载相关的文件。如果我们某个文件夹下的文件或者某个类型的文件不允许用户下载,可以在</httpHandlers> 节点中增加相应的子节点。

下面我们以一个例子来说明<httpHandlers> 节点的用法,在我们的asp.net 应用程序中建立一个IPData 目录,在IPData 目录中创建一个IPData.txt 文件,然后在Web.config 中添加以下配置:

1.    
  2.          
  3.    

上面的代码的作用是禁止访问IPData 目录下的任何txt 文件。

然后新建一个页面,在页面中添加一个超级链接,链接到该目录下IPData.txt 文件,代码如下:

1.    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="HttpHandlersDemo.aspx.cs" Inherits="HttpHandlersDemo" %>  2.     3.      4.     5.    
  6.    
  7.        
httpHandlers节点的例子  8.      9.      10.        
  11.        
  12.        
打开IPData/IPData.txt  13.        
  14.          15.      16.    

运行这个页面的效果如下:

当前web.config 文件的<customErrors> 节点配置如下:
<customErrors mode="On" defaultRedirect="GenericErrorPage.htm">
     <error statusCode="403" redirect="403.htm" />
     <error statusCode="404" redirect="404.htm" />
</customErrors>
如果存在403.htm 和404.htm 页面,点击超级链接之后会出现如下效果:
 
我们从上图中可以看到当<customErrors> 节点的Mode 属性为“On” 时,因为被禁止访问IPData 文件夹下的所有txt 文件,所以会跳转到自定义的没有权限提示页面,即403.htm 。

<httpRuntime> 节点

<httpRuntime> 节点用于对 ASP.NET HTTP 运行库设置。该节可以在计算机、站点、应用程序和子目录级别声明。
例如下面的配置控制用户最大能上传的文件为40M (40*1024K ),最大超时时间为60 秒,最大并发请求为100 个。

1.    

<pages> 节点

<pages> 节点用于表示对特定页设置,主要有三个属性,分别如下:
属性名  说明
buffer  是否启用了 HTTP 响应缓冲。
enableViewStateMac  是否应该对页的视图状态运行计算机身份验证检查(MAC) ,以放置用户篡改,默认为false ,如果设置为true 将会引起性能的降低。
validateRequest  是否验证用户输入中有跨站点脚本***和SQL 注入式漏洞***,默认为true ,如果出现匹配情况就会发 HttpRequestValidationException 异常。对于包含有在线文本编辑器页面一般自行验证用户输入而将此属性设为false 。
下面就是一个配置节点的例子:

1.    

<sessionState> 节点

<sessionState> 节点用于配置当前asp.net 应用程序的会话状态配置。以下就是一个常见配置:

1.    

上面的节点配置是设置在asp.net 应用程序中启用Cookie ,并且指定会话状态模式为在进程中保存会话状态,同时还指定了会话超时为30 分钟。

<sessionState> 节点的Mode 属性可以是以下几种值之一:
属性值  说明
Custom  使用自定义数据来存储会话状态数据。
InProc  默认值。由asp.net 辅助进程来存储会话状态数据。
Off  禁用会话状态。
SQLServer  使用进程外SQL Server 数据库保存会话状态数据。
StateServer  使用进程外 ASP.NET 状态服务存储状态信息。
一般默认情况下使用InProc 模式来存储会话状态数据,这种模式的好处是存取速度快,缺点是比较占用内存,所以不宜在这种模式下存储大型的用户会话数据。

<globalization> 节点:

用于配置应用程序的全球化设置。此节点有几个比较重要的属性,分别如下:
属性名  说明
fileEncoding  可选属性。设置.aspx 、.asmx 和 .asax 文件的存储编码。
requestEncoding  可选属性。设置客户端请求的编码,默认为UTF-8.
responseEncoding  可选属性。设置服务器端响应的编码,默认为UTF-8.
以下就是asp.net 应用程序中的默认配置:

1.    

配置文件的读写操作

虽然web.config 文件是一个XML 文件,但是由于权限的原因它在部署中不能像操作普通XML 文件那样进行修改,在.net 中提供了一个类用于对web.config 进行修改。
下面是针对web.config 修改通用类的代码:

1.    using System;  2.    using System.Configuration;  3.    using System.Web;  4.    using System.Web.Configuration;  5.     6.    ///   7.    /// ConfigurationOperator 的摘要说明  8.    ///   9.    public class ConfigurationOperator:IDisposable  10.    {  11.        private Configuration config;  12.     public ConfigurationOperator():this(HttpContext.Current.Request.ApplicationPath)  13.     {  14.              15.     }  16.     17.        public ConfigurationOperator(string path)  18.        {  19.            config = WebConfigurationManager.OpenWebConfiguration(path);  20.        }  21.     22.        ///    23.        /// 设置应用程序配置节点,如果已经存在此节点,则会修改该节点的值,否则添加此节点  24.        ///    25.        /// 
节点名称   26.        /// 
节点值   27.        public void SetAppSetting(string key, string value)  28.        {  29.            AppSettingsSection appSetting = (AppSettingsSection)config.GetSection("appSettings");  30.            if (appSetting.Settings[key] == null)//如果不存在此节点,则添加   31.            {  32.                appSetting.Settings.Add(key, value);  33.            }  34.            else//如果存在此节点,则修改   35.            {  36.                appSetting.Settings[key].Value = value;  37.            }  38.        }  39.     40.        /// 
   41.        /// 设置数据库连接字符串节点,如果不存在此节点,则会添加此节点及对应的值,存在则修改   42.        ///    43.        /// 
节点名称   44.        /// 
节点值   45.        public void SetConnectionString(string key, string connectionString)  46.        {  47.            ConnectionStringsSection connectionSetting = (ConnectionStringsSection)config.GetSection("connectionStrings");  48.            if (connectionSetting.ConnectionStrings[key] == null)//如果不存在此节点,则添加   49.            {  50.                ConnectionStringSettings connectionStringSettings = new ConnectionStringSettings(key, connectionString);  51.                connectionSetting.ConnectionStrings.Add(connectionStringSettings);  52.            }  53.            else//如果存在此节点,则修改   54.            {  55.                connectionSetting.ConnectionStrings[key].ConnectionString = connectionString;  56.            }  57.        }  58.     59.        /// 
   60.        /// 保存所作的修改   61.        ///    62.        public void Save()  63.        {  64.            config.Save();  65.            config = null;  66.        }  67.        public void Dispose()  68.        {  69.            if (config != null)  70.            {  71.                config.Save();  72.            }  73.        }  74.    }

把上面的代码存放到App_Code 文件夹下,我们在项目中就可以直接使用了。

我们通过一个例子演示如果使用这个通用类对web.config 进行设置。新建一个aspx 页面,下面是前台代码:

1.    <%@ Page Language="C#" AutoEventWireup="true" CodeFile="ConfigModifyDemo.aspx.cs" Inherits="ConfigModifyDemo" %>  2.     3.      4.     5.    
  6.    
  7.        
在部署后修改web.config的例子  8.      9.      10.        
  11.        
  12.        
  13.        类型名称值  14.          15.            程序配置  16.                
  17.                
  19.            
  20.          21.            数据库连接  22.                
  23.                
  24.            
  25.          26.            
  27.          28.        
  29.          30.      31.    

编写后台代码有时可能需要增加对配置文件读写操作类所在dll 的引用,如下:

下面是后台代码:

1.    using System;  2.    using System.Data;  3.    using System.Configuration;  4.    using System.Collections;  5.    using System.Web;  6.    using System.Web.Security;  7.    using System.Web.UI;  8.    using System.Web.UI.WebControls;  9.    using System.Web.UI.WebControls.WebParts;  10.    using System.Web.UI.HtmlControls;  11.    using System.Web.Configuration;//注意添加这个命名空间  12.     13.    public partial class ConfigModifyDemo : System.Web.UI.Page  14.    {  15.        protected void Page_Load(object sender, EventArgs e)  16.        {  17.     18.        }  19.        protected void btnModify_Click(object sender, EventArgs e)  20.        {  21.            string appSetting = txtAppSetting.Text;//appSetting子节点值  22.            string connectionString = txtConnectionString.Text;//连接字符串  23.            string key = txtKey.Text;//appSetting子节点Key  24.            string connectionName = txtConnectionName.Text;//连接Name  25.            ConfigurationOperator op = new ConfigurationOperator();  26.            op.SetAppSetting(key, appSetting);  27.            op.SetConnectionString(connectionName, connectionString);  28.            op.Save();  29.        }  30.     31.          32.    }

下面是运行界面:

 
我们在上面的表单中填入如下信息:
 
假设此时web.config 文件相关节点的内容如下:

1.    
  2.      
  3.      
  4.        
  5.      

我们点击“ 修改” 按钮之后的文件内容如下:

1.    
  2.        
  3.      
  4.      
  5.        
  7.      

从执行结果可以看出我们的程序确实能做到修改和添加web.config 中的节点的功能。需要注意的是,在利用了某些版本控制软件之后(如Microsoft Visual SourceSafe ),版本控制软件可能会将web.config 设置为只读属性,就会出现不能设置的情况,我们需要手动将web.config 的只读属性去掉才能设置web.config 文件。在实际部署项目的时候就不会存在这个问题。

总结:web.config 是asp.net 应用程序中一个很重要的配置文件,通过web.config 文件可以方便我们进行开发和部署asp.net 应用程序。此外还能对程序进行一些灵活的控制。在本篇中详细讲述了各节点的作用。因为在部署asp.net 应用程序后因为权限原因不能按照XML 方式进行修改web.config 文件,所以在本篇中还提供了一个针对<appSettings> 节点和<connectionStrings> 节点设置的通用类,读者朋友可以根据实际项目需要对这个通用类进行完善和补充。

下一篇笔者将带领大家进入到asp.net 的内部,了解一下asp.net 的内部运行机制,这对于我们更加灵活地控制asp.net 应用程序是非常有帮助的。

最近事情比较多,忙不过来了,可能发表时间会比较长,不过也好能有时间让我再思考一下我的表述方式。