.net1.1中如果需要灵活的操作和读写配置文件并不是十分方便,一般都会在项目中封装一个配置文件管理类来进行读写操作。而在.net2.0中使用ConfigurationManager 和WebConfigurationManager 类可以很好的管理配置文件,ConfigurationManager类在System.Configuration中,WebConfigurationManager在System.Web.Configuration中。根据MSDN的解释,对于 Web 应用程序配置,建议使用 System.Web.Configuration.WebConfigurationManager 类,而不要使用 System.Configuration.ConfigurationManager 类。
下面我给出一个简单的例子说明如何使用WebConfigurationManager操作配置文件:
//打开配置文件
Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
//获取appSettings节点
AppSettingsSection appSection = (AppSettingsSection)config.GetSection("appSettings");
//在appSettings节点中添加元素
appSection.Settings.Add("addkey1", "key1's value");
appSection.Settings.Add("addkey2", "key2's value");
config.Save();
运行代码之后可以看见配置文件中的改变:
<appSettings>
<add key="addkey1" value="key1's value" />
<add key="addkey2" value="key2's value" />
</appSettings>
修改和删除节点或属性也非常方便:
//打开配置文件
Configuration config = WebConfigurationManager.OpenWebConfiguration("~");
//获取appSettings节点
AppSettingsSection appSection = (AppSettingsSection)config.GetSection("appSettings");
//删除appSettings节点中的元素
appSection.Settings.Remove("addkey1");
//修改appSettings节点中的元素
appSection.Settings["addkey2"].Value = "Modify key2's value";
config.Save();
配置文件:
<appSettings>
<add key="addkey2" value="Modify key2's value" />
</appSettings>
在ASP.NET2.0里不但进一步扩展了配置文件web.config,更为重要的是系统提供了一组API函数,让我们可以以编程的方式从配置文件里提取信息
首先,先看看如果从web.config里提取appSettings里的配置值,示例代码如下:
<appSettings>
<add key="pagetitle" value="http://blog.netbei.com/Job Site Starter Kit (Ver.1.0)"></add>
<add key="sitelogo" value="logo.gif"></add>
<add key="advertiseemail" value="
[email protected]"></add>
</appSettings>
利用ASP.NET2.0提供的一组API函数,您可以很容易的获取AppSettingsSection里所有的Keys/value组对,如下:
Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
AppSettingsSection appSettings = (AppSettingsSection) config.GetSection("appSettings");
string[] appKeys = appSettings.Settings.AllKeys;
for (int i = 0; i < appSettings.Settings.Count; i++)
{
//这里只进行简单的输出
Response.Write(appSettings.Settings[appKeys[i]].Value);
Response.Write("<BR>");
}
上面代码只是进行简单的输出所有Key的value值,然而,你可能想获取的仅仅是某一个key的值,这也非常简单,如下:
Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("appSettings")
string pateTitle= appSettings.Settings["pagetitle"].Value; //获取key为patetitle的value值
string siteLogo= appSettings.Settings["siteLogo"].Value; //获取key为sitelogo的value值
对于数据库连接字符串,在ASP.NET2.0里提供了专门的配置节如下:
<connectionStrings>
<add name="connectionstring"
connectionString="Data Source=SQLEXPRESS;AttachDbFilename=JsskDb.mdf; … .."/>
<add name="MyProviderConnectionString"
connectionString="Data Source=SQLEXPRESS;Integrated Security=True; … …"/>
</connectionStrings>
这样我们很容易获取数据库连接字符串如下:
Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
ConnectionStringsSection conSection = (ConnectionStringsSection)config.GetSection("connectionstring ");
ConnectionStringSettingsCollection conCollection = conSection.ConnectionStrings;
foreach (ConnectionStringSettings conSetting in conCollection)
{
Response.Write(conSetting.ConnectionString);
Response.Write("<BR>");
}
另外,利用API函数,你同时还可以在代码里更改web.config数据库连接的配置的值,如下
Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
ConnectionStringsSection conSection= (ConnectionStringsSection)config.GetSection("connectionStrings");
conSection.ConnectionStrings["SQLConnectionString"].ConnectionString =
"Data Source=SQLEXPRESS;Integrated Security=True; … …";
config.Save();
这里最有意思的可能就是类的转换,在<appSettings ></appSettings>里,使用的是AppSettingsSection类,在<connectionStrings></ connectionStrings>里使用的的是ConnectionStringsSection类,事实上,ASP.NET2.0提供的一组函数都是“配置节名+Section”的形式提供的类。
在ASP.NET官方网站曾经对此专门介绍,可以找不到该文件了。
在ASP.NET2.0里提供了两种方式对数据库连接字符串加密,一种是使用asp_regii命令,一种是通过代码,下面显示的是通过代码方式对数据库连接字符串加密,代码如下:
Configuration config = WebConfigurationManager.OpenWebConfiguration(Request.ApplicationPath);
ConfigurationSection configSection = config.GetSection("connectionStrings");
if (configSection.SectionInformation.IsProtected)
{//如果已经加密,就不用再加密了
configSection.SectionInformation.UnprotectSection();
config.Save();
}
else
{
configSection.SectionInformation.ProtectSection ("DataProtectionConfigurationProvider");
config.Save();
}
这样,你检查该文件的配置可能如下:
<connectionStrings configProtectionProvider="DataProtectionConfigurationProvider">
<EncryptedData>
<CipherData>
<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAVClqG40BZkCjK40
adynN8gQAAAACAAAAAAADZgAAqAAAABAAAABIhtOW …PE
</CipherData>
</EncryptedData>
</connectionStrings>
ASP.NET2.0
里的配置接口
API
ASP.NET2.0
里的配置
API
接口函数允许我们读
/
写配置文件
----
包括对
web.config
和
machine.config
的读写。您可以读写您自己应用程序里的配置文件,也可以读写同一机器上其它应用程序的配置文件,您甚至可以读写不同服务器上的应用程序配置文件。本文我们将以
ASP.NET
开发人员的角度看一下
ASP.NET2.0
的新亮点,这其中包括如何加密和解密配置文件。
AppSettings
和
Connection
字符串
在
ASP.NET
开发中,两个常规任务是从配置文件里读取应用程序的设置和数据库链接字符串。在
ASP.NET2.0
中,这些设置分别驻留在
<appSettings>
和
<connectionStrings>
配置节。一个
web.config
示例看起来应该类似如下:
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings>
<add key="message" value="Hello World!" />
</appSettings>
<connectionStrings>
<add name="AdventureWorks" connectionString="..."/>
<add name="pubs" connectionString="..."/>
</connectionStrings>
<system.web>
<compilation debug="true" />
<authentication mode="Windows"/>
<identity impersonate="true"/>
</system.web>
</configuration>
ASP.NET
提供的
API
接口函数是以
WebConfigurationManager
类开始的,该类在
System.Web.Configuration
命名空间。
WebConfigurationManager
类
包含了静态方法以获取应用程序的设置和数据库连接字符串。例如为了读取上面示例中
appSetting
的
“message”
信息
,我们可以使用类似如下的代码:
string message;
message = WebConfigurationManager.AppSettings["message"];
同样,如果我们想获取第二个数据库连接字符串--连接名为
pubs
的--我们可以使用如下的代码
string connectionString =
WebConfigurationManager.ConnectionStrings["pubs"].ConnectionString;
通过使用
GetSection
静态方法,使得读取配置文件里的任何设置变的简单。
GetSection
采用
XPath
表达式来响应你想读取的节,你可以使用强类型转换将对对象的引用转换为对内置节的引用。例如使用
AuthorizationSection
类来操作对
<authorization>
节的配置,使用
PageSection
类来操作对
<pages>
节
的操作。
如果我们想更改
web.config
里对
<identity>
节模拟的设置,我们可以使用如下代码
protected void readImpersonationButton_Click(object sender, EventArgs e)
{
// note: currently broken in BETA2, works in post BETA2 builds.
// in BETA2 GetSection returns a wrapper
// that will not cast to IdentitySection
IdentitySection section;
section = WebConfigurationManager.GetSection("system.web/identity")
as IdentitySection;
if (section != null)
{
WriteMessage("Impersonate = " + section.Impersonate);
}
}
private void WriteMessage(string message)
{
// this method assumes a PlaceHolder control
// on the web form with the ID of messagePlaceHolder
HtmlGenericControl generic = new HtmlGenericControl();
generic.InnerHtml = message;
messagePlaceHolder.Controls.Add(generic);
}
又如对<pages>节的设置:
修改配置文件
protected void readImpersonationButton_Click(object sender, EventArgs e)
{
System.Configuration.Configuration config = WebConfigurationManager.OpenWebConfiguration(path);
PagesSection pages = (PagesSection)config.GetSection("system.web/pages");
this.lblSession.Text = pages.EnableSessionState.ToString();
this.lblViewState.Text = pages.EnableViewState.ToString();
this.lblMaxPage.Text = pages.MaxPageStateFieldLength.ToString();
this.lblAutoEvent.Text = pages.AutoEventWireup.ToString();
//获取整节appSettings相关的XML格式代码
ConfigurationSection appSettings = config.GetSection("appSettings");
this.Label1.Text=Server.HtmlEncode(appSettings.SectionInformation.GetRawXml());
}
WebConfigurationManager
类提供静态方法
OpenWebConfiguration
同样允许我们打开
web
的配置文件并进行更新。我们可以通过根据传递应用程序的相对路径来指明需要打开哪个应用程序的配置文件。我们还可以通过传递
IIS
站点名称和虚拟路径的名称来读取其它应用程序的配置问题。使用后面这种方式,就可以读取其它应用程序的配置文件。
如果我们想获取当前应用程序
web.config
里
<compliation>
配置节的
debug
属性,更改
debug
为
true
或者为
false
,我们可以使用在
button
的事件里使用如下代码
protected void toggleDebugButton_Click(object sender, EventArgs e)
{
string path = Request.CurrentExecutionFilePath;
path=path.Substring(0,path.LastIndexOf("/"));
Configuration config;
config = WebConfigurationManager.OpenWebConfiguration(path);
CompilationSection compilation;
compilation = config.GetSection("system.web/compilation")
as CompilationSection;
if (compilation != null)
{
compilation.Debug = !compilation.Debug;
config.Save();
WriteMessage(
"Debug setting is now: " + compilation.Debug
);
}
}
使用强类型的
CompilationSection
对象允许我们读写
<compliation>
节里的属性。我们可以改变节的配置并使用
System.Configuration.Configuration
里的
Save
保存所有的修改。
在更改配置文件时,还有一个小的细节,首先,你应该具有修改配置文件的权限,典型的启动
.NET runtime
运行时的
NETWORD SERVICE
和
ASPNET
帐户并没有修改应用程序里配置文件的权限。
一个安全的解决方法是使用基于
windows
的身份验证并启用模拟技术。这些设置允许客户端执行请求的任务。如果客户端具有修改配置文件的权限,上面的操作才能够成功。
另外一个注意事项是
ASP.NET runtime
将随时监视
web.config
,一旦
web.config
有了改动,
ASP.NET
将重新启动应用程序。具体的说
ASP.NET
运行时将根据你更改
web.config
所在的应用程序域,重新建立应用程序对象实例。重建实例对性能有显著影响,所以不应该经常修改
web.config
。
如果你想要在修改
web.config
时,既能够获取更多的控制权限同时又不使应用程序重新启动,你可以使用外部配置文件,下一节将介绍这个问题。
使用外部配置文件
你可以将配置文件里的任意配置节取出并单独存放,例如我们看一下新的配置
web.config
文件
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<appSettings configSource="appSettings.config"/>
<connectionStrings configSource="connections.config"/>
<system.web>
<compilation debug="true" />
<authentication mode="Windows"/>
<identity impersonate="true"/>
</system.web>
</configuration>
在这个例子中,我们将
<appSettings>
和
<connectionStrings>
的配置移动到了
web.config
的外部,这些外部文件同样是基于
XML
格式的配置节片段,例如
appSettings.config
的文件看起来类似如下:
<appSettings>
<add key="message" value="Hello World!"/>
</appSettings>
使用外部配置文件在某些情况下较为有用,例如在开发,或者在测试甚至在成品软件开发中,由于阶段的不同我们需要一种简易的方式切换设置,此时就可以使用外部配置文件。
如果你需要更多的控制权限也可以使用外部配置,例如你对你的
web.config
进行了锁定,只有
Administrators
用户可以更改该配置问题,但是你可以让
<appSettings>
节使用外部配置文件并允许其它角色的用户修改其内容。
使用外部文件还有其它的优越性--它可以控制我们的应用程序是否重新启动。
如果在
web.config
里进行了改动。
ASP.NET
应用程序总会重新启动--不存在选择的余地,但是使用外部文件,你可以告诉
runtime
运行时,是否在外部文件改动时重启应用程序。
如果你查看
machine.config
里的配置,在
<configSections>
节,你可以看到每一个节定义的处理句柄(
Handler
)。每一个节包含一个属性:
restartOnExternalChanges
。
请注意对
appSettings
的配置,其
restartOnExternalChanges
设置为
"false"
,这意味这如果使用外部文件存放设置信息,当外部文件改变时,应用程序并不重新启动,但是你使用
WebConfigurationManager.AppSettings
读取的将是新值。
在使用
restartOnExternalChanges
请注意,有些外部文件改变时,必须重启应用程序才能够生效。在这种情况下,虽然你可以设置
restartOnExternalChanges
为
false
,但是请确保不要在应用程序里缓存节的参数,并重新使用
WebConfigurationManager
读取配置值。
使用加密
在
ASP.NET2.0
里提供了对配置节直接加密的功能。在配置文件里有几处配置可能包含敏感信息,例如
<connectionStrings>
节,它可能包含连接数据库的用户名和密码。
<identity>
节可能包含
runtime
使用模拟帐户的用户和密码。
你甚至可能在配置文件的
appSettings
里或者在自定义节里包含共享
web service
使用的密码。不管哪种情况,您都不希望密码以明文的方式存放在配置文件里。
注意:在配置文件里也包含你无法加密的节,主要是
<precessModul>
节。此时你可以需要利用
ASPNET_SETREG.EXE
工具单独设置该节密码。
下面的代码演示了加密和解密节是多么的简单,注意:在从节里读取配置信息时,你不需要解密。
ASP.NET
运行时会自动读取加密的文本,并在应用程序需要的地方自动解密加密的信息。在这里调用
Unprotect
方法主要是演示如何返回未加密的节
protected void toggleEncryptionButton_Click(object sender, EventArgs e)
{
Configuration config;
config = WebConfigurationManager.OpenWebConfiguration("~");
ConnectionStringsSection section;
section = config.GetSection("connectionStrings")
as ConnectionStringsSection;
if (section.SectionInformation.IsProtected)
{
section.SectionInformation.UnprotectSection();
}
else
{
section.SectionInformation.ProtectSection(
"DataProtectionConfigurationProvider"
);
}
config.Save();
WriteMessage("connections protected = " +
section.SectionInformation.IsProtected);
}
在执行上述代码后,如果我们检测
web.config
,我们将看到其配置如下:
<?xml version="1.0"?>
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
<protectedData>
<protectedDataSections>
<add name="connectionStrings"
provider="DataProtectionConfigurationProvider"
inheritedByChildren="false" />
</protectedDataSections>
</protectedData>
<appSettings configSource="appSettings.config"/>
<connectionStrings configSource="connections.config"/>
<system.web>
<compilation debug="true" />
<authentication mode="Windows"/>
<identity impersonate="true"/>
</system.web>
</configuration>
这里我们使用的是外部配置文件,
打开外部配置文件可以看到内容类似如下:
<connectionStrings>
<EncryptedData>
<CipherData>
<CipherValue>AQAAANCMnd8BF....</CipherValue>
</CipherData>
</EncryptedData>
</connectionStrings>
运行时,
ASP.NET
解密区域信息,我们可以仍然使用
WebConfigurationManager.ConnectionStrings
返回应用程序可以直接使用的数据库连接字符串。
为了理解配置文件,我们首先需要明白名运行时是怎么处理加密和解密工作的。解密和解密分别使用了
Provider
模型,
ASP.NET2.0
使用这两个
Provider
模型分别是:
DataProtectionConfigurationProvider
和
RSAProtectedConfigurationProvider
(如果需要,你也可以自定义自己的加密
/
解密
Provider
)
我们可以通过传递给
ProtectSetion
的参数来指示使用
Provider
的具体模型。在前面代码片段中,我们使用的是
DataProtectionConfigurationProvider
DataProtectionConfigurationProvider
使用
Windows Data Protection API (DPAPI)
接口,这提供了加密和解密的工作,因为
Windows Data Protection API (DPAPI)
依赖于具体的机器密钥。只有在同一机器上,针对加密的解密才有效。
如果你需要将配置从一台机器转移到另外一台机器,你需要使用
RSAProtectedConfigurationProvider
模型。
RSAProtectedConfigurationProvider
,正如其名称所示意,使用
RSA
作为加密密钥。
你可以使用具有
RSAProtectedConfigurationProvider
功能的
aspnet_regiis.exe
命令进行操作。
aspnet_regiis.exe
包含一些列参数包括建立密钥对(
-pc
),导出密码(
-pc
)等
总结
本文介绍了如何使用
API
配置函数读写配置文件。在配置文件修改时,讨论了应用程序的重启问题。