1.4 ASP.NET配置

在ASP.NET 4之前,ASP.NET Web应用程序项目中的配置文件非常复杂,如在使用Visual Studio 2008Sp1创建一个Web应用程序项目的Web.config就有125行之多。在实际开发中,通常还会自己加上一些项目所需要的配置文件。这样,Web.config文件的大小和复杂度不断增长,很不容易读取和管理。而在ASP.NET 4中,微软在配置方面做了很大的突破,从而使Web.config变得非常地简洁、清晰。

1.4.1 machine.config文件

打开C:\WINDOWS\Microsoft.NET\Framework\v4.0.21006\Config文件夹,你会发现里面有一个machine.config文件。machine.config用于将计算机范围的策略应用到本地计算机上运行的所有.NET Framework应用程序。该文件定义支持的配置文件节,配置ASP.NET工作进程,注册可用于高级特性(如配置文件、成员资格以及基于角色安全等)的提供程序。同时,它与.NET Framework 2.0、.NET Framework 3.0和.NET Framework 3.5的文件是同时存在,并可以同时使用。

相对于.NET Framework 4之前的版本,在新的machine.config中注册了所有的ASP.NET标识部分((sction)、处理器((hnlder)和模块。其中所包括的有以下功能:

1)ASP. NET AJAX.

2)ASP. NET Dynamic Data:ASP.NET动态数据。

3)ASP. NET Routing:ASP.NET路径选择或导向,现在可为ASP.NET WebForms和ASP.NET MVC两者兼用。

4)ASP. NET Chart Control:ASP.NET图表控件,也就是以前的MSChart,现在已经内置于ASP.NET 4中,这使得以后开发图表应用就更加方便简单了。

除了machine.config之外,ASP.NET还使用了根Web.config文件,与machine.config在同一个目录下。它提供额外的设置,这些设置注册ASP.NET的核心HTTP处理程序和模块,为浏览器支持建立规则,定义安全策略等。计算机上的所有Web应用程序都继承这两个文件的设置。

1.4.2 Web.config文件

在上面已经讲过,ASP.NET 4中的Web.config相比于以前的版本变得非常简洁、清晰。以上面的“Hello, World”Web应用程序项目的Web.config文件为例,见代码清单1-9。

代码清单1-9“Hello, World”Web应用程序项目的Web.config文件


<?xml version="1.0"?>

<!——

For more information on how to configure your ASP.NET application, please visit

http://go.microsoft.com/fwlink/?LinkId=169433

——>

<configuration>

<system.web>

<compilation debug="true"targetFramework="4.0"/>

</system.web>

</configuration>


如上面配置文件所示,其中:


<system.web>

<compilation debug="true"targetFramework="4.0"/>

</system.web>


这个配置部分告诉ASP.NET默认允许应用调试,并向Visual Studio指定在提供intellisense时该定向的.NET版本((V 2010支持多定向,IDE中的intellisense会根据你当前针对的框架版本自动改变)。

1.4.3 Web.config转换文件

或许这时候你已经发现,在Web.config文件下还生成了另外两个文件:Web.Debug.config和Web.Release.config文件。从它们的名称中就可以看出,ASP.NET 4 W eb.config使用了多文件配置方案,其主要作用是让Web应用程序中的配置文件能够从Debug转换到Release配置文件,即实现从开发到产品的发布转化。

其实,在日常开发中,Web.config文件通常包括根据应用程序的运行环境而必须的不同的设置。例如,在部署Web.config文件时,你可能必须更改数据库连接字符串或禁用调试。对于Web应用程序项目,ASP.NET提供了一些工具,用于自动完成在部署这些项目时更改(转换)Web.config文件的过程。对于要部署到的每个环境,你将创建一个转换文件,该文件仅指定原始Web.config文件和适用于该环境的已部署Web.config文件之间的差异。

转换文件是一个XML文件,该文件指定在部署Web.config文件时应如何更改该文件。转换操作通过使用在XML-Document-Transform命名空间(映射到xdt前缀)中定义的XML特性来指定(即<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">)。当然,除了系统自动生成的Web.Debug.config和Web.Release.config文件之外,还可以根据自己的需要来创建转换文件。

要创建自定义转换文件,首先需要配置编译选项,如图1-26所示。

figure_0065_0045

图 1-26 配置编译选项

在图1-26中,选择“Configuration Manager”,会打开一个Configuration Manager窗体,如图1-27所示。

figure_0065_0046

图 1-27 Configuration Manager窗体

在Configuration Manager窗体中,选择下拉表中的“New”选项,就可以打开New Solution Configuration窗体,如图1-28所示。

在New Solution Configuration窗体中,建立一个本地部署测试环境的配置。注意,这里默认就选中了Create new project configurations复选框。单击“OK”按钮,就可以在Configuration Manager窗体的下拉表中看所创建配置编译选项“MyConfig”,如图1-29所示。

figure_0065_0047

图 1-28 新建一个本地部署测试环境的配置

figure_0065_0048

图 1-29 Configuration Manager窗体

创建好配置编译选项“MyConfig”之后,就可以在项目里用鼠标右击Web.config配置文件,然后在弹出的快捷菜单里选择“Add Config Transforms”选项,如图1-30所示。

选择“Add Config Transforms”选项之后,一个新的自定义转换文件Web.MyConfig.config文件便自动添加到Web.config文件下了,如图1-31所示。

figure_0066_0049

图 1-30 选择“Add Config Transforms”选项

figure_0066_0050

图 1-31 添加好的Web.MyConfig.config

接下来,为了帮助读者了解Web.MyConfig.config文件的作用,首先在Web.config配置文件中添加一个appSettings元素,并在该元素里面添加一个名为TestKey的Key,将TestKey的值设置为“我是Web.config”。详细代码如下所示:


<?xml version="1.0"?>

<!——

For more information on how to configure your

ASP.NET application, please visit

http://go.microsoft.com/fwlink/?LinkId=169433

——>

<configuration>

<appSettings>

<add key="TestKey"value="我是Web.config"/>

</appSettings>

<system.web>

<compilation debug="true"targetFramework="4.0"/>

</system.web>

</configuration>


同样,也需要在Web.MyConfig.config文件中添加一个appSettings元素。同样在该元素里面添加一个名为TestKey的Key,将TestKey的值设置为“我是Web.MyConfig.config”。其中,关于转换文件的语法知识将在后面详细介绍。详细代码如下所示:


<?xml version="1.0"?>

<!——For more information on using web.config

transformation visit

http://go.microsoft.com/fwlink/?LinkId=125889——>

<configuration xmlns:xdt="

http://schemas.microsoft.com/XML-Document-Transform">

<appSettings>

<add key="TestKey"value="我是Web.MyConfig.config"

xdt:Transform="Replace"xdt:Locator="Match(key)"/>

</appSettings>

<system.web>

<compilation xdt:Transform="RemoveAttributes(debug)"/>

</system.web>

</configuration>


其实,从Web.MyConfig.config文件的代码中可以简单地看出,当使用MyConfig发布时,要求修改appSettings属性TestKey的值。同时,删除compilation中打开debug的功能。为了进一步查看其结果,我们来继续发布项目。即选中要发布的项目文件,在右键菜单中选择“Publish”选项,就可以打开Publish Web窗体,如图1-32所示。

figure_0067_0051

图 1-32 发布项目

因为上面的配置编译选项是“MyConfig”,因此,当打开发布项目文件的Web.config配置文件时,会发现appSettings元素里面的TestKey的值被修改成了“我是Web.MyConfig.config”。如下面的代码所示:


<?xml version="1.0"?>

<!——

For more information on how to configure your

ASP.NET application, please visit

http://go.microsoft.com/fwlink/?LinkId=169433

——>

<configuration>

<appSettings>

<add key="TestKey"value="我是Web.MyConfig.config"/>

</appSettings>

<system.web>

<compilation targetFramework="4.0"/>

</system.web>

</configuration>


1.4.4 Locator特性语法

XML-Document-Transform命名空间定义两个特性:Locator和Transform。其中,Locator特性指定要以某种方式更改的Web.config元素或一组元素;而Transform特性指定要对Locator特性所查找的元素执行哪些操作。本节就来详细阐述Locator特性的语法知识。

1.Condition

它指定一个XPath表达式,该表达式会追加到当前元素的XPath表达式。

如下面的示例演示如何选择其name特性值为oldname的连接字符串元素,或其值为oldprovider的providerName特性。在部署的Web.config文件中,所选元素将替换为在转换文件中指定的元素。


<connectionStrings>

<add name="ASPNET4"connectionString="newstring"

providerName="newprovider"

xdt:Transform="Replace"

xdt:Locator="Condition(@name='oldname'

or@providerName='oldprovider')"/>

</connectionStrings>


2.Match

它选择针对指定的一个或多个特性具有匹配值的一个或多个元素。如果指定了多个特性名称,则将仅选择与所有指定特性匹配的元素。

如下面的示例演示如何选择连接字符串add元素,该元素在开发的Web.config文件的name特性中具有ASPNET4。在部署的Web.config文件中,所选元素将替换为在转换文件中指定的add元素。


<connectionStrings>

<add name="ASPNET4"connectionString="newstring"

providerName="newprovider"

xdt:Transform="Replace"

xdt:Locator="Match(name)"/>

</connectionStrings>


3.XPath

它指定应用于开发Web.config文件的绝对XPath表达式。与Condition不同,它所指定的表达式不追加到与当前元素对应的隐式XPath表达式。

如下面的示例演示如何选择与前面的Condition关键字示例中所选元素相同的元素。


<connectionStrings>

<add name="ASPNET4"connectionString="newstring"

providerName="newprovider"

xdt:Transform="Replace"

xdt:Locator="XPath(configuration/connectionStrings[

@name='ASPNET4'or@providerName='System.Data.SqlClient'])"/>

</connectionStrings>


4.省略Locator特性

Locator特性是可选的。如果未指定Locator特性,要更改的元素将由为其指定Transform特性的元素隐式指定。在下面的示例中,将替换整个system.web元素,因为未指定任何Locator特性来指示其他方面。


<?xml version="1.0"?>

<configuration xmlns:xdt="

http://schemas.microsoft.com/XML-Document-Transform">

<system.web xdt:Transform="Replace">

<customErrors defaultRedirect="GenericError.htm"

mode="RemoteOnly">

<error statusCode="500"redirect="InternalError.htm"/>

</customErrors>

</system.web>

</configuration>


1.4.5 Transform特性语法

上一节详细地阐述了Locator特性的语法知识,本节阐述Transform特性的语法知识。

1.Insert

它将转换文件中定义的元素作为所选的一个或多个元素的同级进行添加。该新元素被添加到任何集合的末尾。

如下面的示例演示如何选择开发Web.config文件中的所有连接字符串。在部署的Web.config文件中,指定的连接字符串将添加到集合的末尾。


<connectionStrings>

<add name="ASPNET4"connectionString="newstring"

providerName="newprovider"

xdt:Transform="Insert"/>

</connectionStrings>


2.InsertBefore

它将转换XML中定义的元素直接插入到由指定XPath表达式选择的元素之前。该XPath表达式必须是一个绝对表达式,因为它作为一个整体应用于开发Web.config文件,而不只是追加到当前元素的隐式XPath表达式中。

如下面的示例演示如何选择拒绝所有用户访问的deny元素,然后在它之前插入为管理员授予访问权限的allow元素。


<authorization>

<allow roles="Admins"

xdt:Transform="InsertBefore(

/configuration/system.web/authorization/deny[@users='*'])"/>

</authorization>


3.InsertAfter

与InsertBefore相反,它将转换XML中定义的元素直接插入到由指定XPath表达式选择的元素之后。与InsertBefore相同,该XPath表达式也必须是一个绝对表达式,因为它作为一个整体应用于开发Web.config文件,而不是追加到当前元素的隐式XPath表达式中。

如下面的示例演示如何选择为管理员授予访问权限的allow元素,然后在它之后插入拒绝指定用户访问的deny元素。


<authorization>

<deny users="UserName"

xdt:Transform="InsertAfter(/configuration

/system.web/authorization/allow[@roles='Admins'])"/>

</authorization>


4.Remove

它表示移除选定元素。如果选择了多个元素,则移除第一个元素。

如下面的示例演示如何选择开发Web.config文件中的所有连接字符串add元素。在部署的Web.config文件中,将仅移除第一个连接字符串元素。


<connectionStrings>

<add xdt:Transform="Remove"/>

</connectionStrings>


5.RemoveAll

与Remove不同,它可以移除选定的一个或多个元素。如在下面的示例中,在部署的Web.config文件中将移除所有元素。


<connectionStrings>

<add xdt:Transform="RemoveAll"/>

</connectionStrings>


6.RemoveAttributes

它表示从所选元素移除指定的特性。

如下面的示例演示如何选择开发Web.config文件中的所有compilation元素。在部署的Web.config文件中,将从compilation元素中移除debug和batch特性。


<compilation

xdt:Transform="RemoveAttributes(debug, batch)">

</compilation>


7.Replace

它将所选的一个或多个元素替换为在转换文件中指定的元素。

如下面的示例代码所示,在部署的Web.config文件中,它将替换TestKey的值为“我是Web.MyConfig.config”。


<appSettings>

<add key="TestKey"value="我是Web.MyConfig.config"

xdt:Transform="Replace"xdt:Locator="Match(key)"/>

</appSettings>


8.SetAttributes

它将所选元素的特性设置为指定的值。与Replace不同,Replace转换特性将替换整个元素,包括其所有特性。而SetAttributes特性则使你能够按原样保留元素而只更改所选特性。

下面的示例演示如何选择开发Web.config文件中的所有compilation元素。在部署的Web.config文件中,compilation元素的batch特性的值设置为false。


<compilation

batch="false"

xdt:Transform="SetAttributes(batch)">

</compilation>


9.XSLT

它表示将XSLT文件应用于所选元素。

如下面的示例演示如何选择appSettings元素并指定在appSettings.xslt文件中定义的转换。


<appSettings

xdt:Transform="XSLT(C:\MyProject\appSettings.xslt)"/>

</appSettings>


1.4.6 Web.config文件的配置继承

ASP. NET使用了一个多层的配置系统,它允许你为Web应用程序的不同部分使用不同的配置。即可以在虚拟目录里面创建另外一个或者多个子目录,而这些子目录又可以包含它们自己的Web.config文件。而这些Web.config文件属于继承关系,每个子目录都可以从它的父目录获取设置,这种关系可以使用图1-33来解释。

figure_0071_0052

图 1-33 Web.config文件的配置继承关系图

在图1-33中,计算机上的所有Web应用程序都必须继承Config目录里的Machine.config文件和Web.config文件中的配置。而A目录和B目录都可以应用它们各自的Web.config文件里面的配置,但必须继承它们父级目录的配置(即B继承A, A继承虚拟目录里面的配置,虚拟目录又继承Config目录里的Machine.config文件和Web.config文件中的配置)。因此,A目录和B目录只可以指定与Web应用程序其他部分不同的很少的一部分自己特有的设置。

其实,在日常开发中,我们很少会使用这种多层配置,除非是要在项目中应用不同的安全设定,即要求安全因素比较高的文件放到一个特定的目录中,Web.config文件在那里定义比根虚拟目录更加严格的安全设置。否则只需要在项目的根虚拟目录加一个Web.config文件就可以了。

但如果设置有冲突,嵌套目录中Web.config文件里的设置就会覆盖从父目录继承来的设置,当然可以专门定义不可改变的锁定节来处理这种情况。

1.4.7 在实际开发中常用的Web.config配置节设置

通常,在实际开发中经常需要用到如下3个配置节:<customErrors>、<connectionStrings>、<appSettings>。

1.<customErrors>

<customErrors>属于<system.web>里的节,它允许你在发生各种HTTP错误时配置应用程序的行为。如下所示:


<!——如果在执行请求的过程中出现未处理的错误,

则通过<customErrors>节可以配置相应的处理步骤。具体来说,

开发人员通过该节可以配置要显示的html错误页以代替错误堆栈跟踪。——>

<customErrors mode="RemoteOnly"defaultRedirect="CommonErrorPage.aspx">

<error statusCode="403"redirect="NoAccess.htm"/>

<error statusCode="404"redirect="FileNotFound.htm"/>

</customErrors>


可以为你的应用程序创建这样的节来重定向403、404等错误到特定的错误信息提示页面,从而使你的程序提示更加友好。在上面的代码中,如果错误码是404(文件未找到),将会把用户重定向FileNotFound.htm页面;如果发生403和404以外的错误,用户将被重定向到CommonErrorPage.aspx页面。因为mode被设置为RemoteOnly,所以本地的管理员能够看见真实的错误信息而不被重定向,但远程用户只能够看到被定向的信息提示页面。其中mode可以设置为三种模式:

1)On:自定义错误被启用,如果没有提供defaultRedirect属性,用户将看到一个一般的错误。

2)Off:自定义错误被禁用,用户将看到错误的详细信息。

3)RemoteOnly:本地的管理员能够看见真实的错误信息而不被重定向,但远程用户只能够看到被定向的信息提示页面。在使用时需要注意两点:一是你在配置文件里定义的自定义错误设置只在ASP.NET处理请求时才有效;二是如果你的自定义页面发生错误,ASP.NET将不能够处理。它不会再次把用户转送同一页面,相反,它将会显示一个带有一般信息的普通客户端错误页面。

2.<connectionStrings>

<connectionStrings>属于<configuration>里的节,它主要是为你的项目设置数据库连接字符串所用,可以在里面添加一个或者多个数据库连接字符串。如下所示:


<connectionStrings>

<add name="ConnectString"connectionString="server=.;

database=Eipsoft.Test;uid=sa;pwd=mawei;"

providerName="System.Data.SqlClient"/>

<add name="ConnectString1"connectionString="server=.;

database=Eipsoft.Test1;uid=sa;pwd=mawei;"

providerName="System.Data.SqlClient"/>

</connectionStrings>


3.<appSettings>

<appSettings>属于<configuration>里的节,它主要用于信息的自定义的设置。例如,可以在里面添加项目的版权信息、项目名称等。如下所示:


<appSettings>

<!——系统用户配置信息——>

<add key="CustomerName"value="默认用户"/>

<add key="Title"value="系统名称"/>

<add key="LoginPhoto"value="Images/LoginPhoto.jpg"/>

<add key="FrameTopPhoto"value="Images/FrameTopPhoto.jpg"/>

<add key="CopyRight"value="版权信息说明"/>

<add key="Power"value="

Eipsoft.PowerManagement.AppCode.PowerInterface, bin\Eipsoft.PowerManagement.dll"/>

<add key="DefaultPage"value="Login.aspx"/>

<add key="Isviewmenu"value="false"/>

<add key="Template"value="E:/Eipsoft工作目录/upFiles"/>

<add key="FCKeditor:BasePath"value="~/fckeditor/"/>

<add key="FCKeditor:UserFilesPath"value="~/FCKeditorfiles/"/>

</appSettings>


1.4.8 通过编程读写Web.config配置节

早在.NET 2.0的时候,微软就提供了ConfigurationManager和WebConfigurationManager这两个类来管理配置文件。其中,ConfigurationManager类在System.Configuration命名空间中,而WebConfigurationManager类在System.Web.Configuration命名空间中。在它们的使用上,对于Web应用程序配置,建议使用System.Web.Configuration.WebConfigurationManager类,而不建议使用System.Configuration.ConfigurationManager类。此外,使用时还应该注意其他类都无法继承这两个类。

1.使用ConfigurationManager访问配置信息

若要使用ConfigurationManager类来访问配置信息,可以调用GetSection方法。但对于某些节,例如appSettings和connectionStrings,可以使用AppSettings和ConnectionStrings来进行访问。如下面的代码所示:


//获取connectionStrings节点

ConfigurationManager.ConnectionStrings["ConnectString"]

//获取appSettings节点

ConfigurationManager.AppSettings["CustomerName"];


2.使用WebConfigurationManager访问配置信息

前面已经说过,在对于Web应用程序配置操作方面,ConfigConfigurationManager类提供强大的支持,它允许你在运行时从配置文件抓取信息。在日常操作中,主要使用它的如下成员,如表1-2所示。

figure_0073_0053

(1)获取<appSettings>节点和<connectionStrings>的信息


//获取appSettings节点

WebConfigurationManager.AppSettings["CustomerName"];

//获取connectionStrings节点

WebConfigurationManager.ConnectionStrings["ConnectString"];


上面只是简单地获取<appSettings>配置节点的值,除此之外,还可以像下面这样获取:


//打开配置文件

Configuration config=WebConfigurationManager.OpenWebConfiguration("~");

//获取appSettings节点

AppSettingsSection appSettings=((ApSettingsSection)config.GetSection("appSettings");

//获取key为CustomerName的value值

string customerName=appSettings.Settings["CustomerName"].Value;

//获取所有key的value值

string[]appKeys=appSettings.Settings.AllKeys;

for(int i=0;i<appSettings.Settings.Count;i++)

{

Response.Write(appSettings.Settings[appKeys[i]].Value);

}


(2)在<appSettings>节点中添加新元素


//打开配置文件

Configuration config=WebConfigurationManager.OpenWebConfiguration("~");

//获取appSettings节点

AppSettingsSection appSection=((ApSettingsSection)config.GetSection("appSettings");

//在appSettings节点中添加元素

appSection.Settings.Add("newkey1","newkey1's value");

appSection.Settings.Add("newkey2","newkey2's value");

//保存

config.Save();


运行代码之后就可以看见配置文件的<appSettings>节点中添加了两个新元素,如下所示:


<appSettings>

<add key="newkey1"value="newkey1's value"/>

<add key="newkey2"value="newkey2's value"/>

</appSettings>


(3)修改和删除<appSettings>节点或属性


//打开配置文件

Configuration config=WebConfigurationManager.OpenWebConfiguration("~");

//获取appSettings节点

AppSettingsSection appSection=((ApSettingsSection)config.GetSection("appSettings");

//删除appSettings节点中的元素

appSection.Settings.Remove("newkey1");

//修改appSettings节点中的元素

appSection.Settings["newkey2"].Value="修改newkey2的值";

config.Save();


运行结果如下所示:


<appSettings>

<add key="newkey2"value="修改newkey2的值"/>

</appSettings>


3.用XmlDocument修改Web.config配置节点的值

除了上面的方法之外,还可以使用XmlDocument类来修改Web.config的节点值。程序方法如代码清单1-10所示。

代码清单1-10用程序修改<appSettings>配置节里Key的值


///<summary>

///修改web.config文件appSettings配置节中的add里的value属性

///</summary>

///<param name="key">add里的key</param>

///<param name="strValue">要修改的值</param>

public void UpdateWebConfig(string key, string strValue)

{

//要修改的配置文件路径

string keyPath="/configuration/appSettings/add[@key='?']";

XmlDocument webConfig=new XmlDocument();

//web.config文件的存储路径

string webConfigPath=HttpContext.Current.Server.MapPath("~")+@"\web.config";

//将web.config文件加载到XmlDocument中

webConfig.Load(webConfigPath);

//查找要修改的配置节

XmlNode updateKey=webConfig.SelectSingleNode(((kyPath.Replace("?",key)));

if(updateKey==null)

{

throw new ArgumentException("没有找到<add key='"+key+"'value=/>的配置节");

}

//修改配置节的值

updateKey.Attributes["value"].InnerText=strValue;

//修改后保存

webConfig.Save(webConfigPath);

}


好,现在假设要通过上面的方法将“<add key="Title"value="系统名称"/>”的“value”修改成“EipsoftCRM管理系统”,我们只要传入相关的参数就可以了。代码如下:


UpdateWebConfig("Title","EipsoftCRM管理系统")


利用上面的方法,读者可以举一反三,使用相同的处理方式修改其他配置节。

注意 虽然可以通过多种手段去修改配置文件里的配置节,但这样做是非常不理想的。修改配置所花的代价很大:文件的访问速度会很慢,而且它所需要的同步化增加了许多额外的开销,新程序域创建(在每次配置设置修改时发生)会花很大代价。所以,除非特殊情况,建议不要轻易去修改配置文件。