‘壹’ .net 如何在web.config中读取自定义节点以及注意的问题
要创建自定义设置 要求有2步:写cs代码 和 修改web.config代码这里我们创建了一个简单的handler ,此handler 用在web.config文件中。 using system; using system.collections; using system.xml; using system.configuration; using system.web.configuration; namespace devhood { internal class pagestylehandler:iconfigurationsectionhandler { public virtual object create(object parent, object context, xmlnode node) { pagestyle config = new pagestyle((pagestyle)parent); config.(node); return config; } } public class pagestyle { string _backcolour; internal pagestyle(pagestyle parent) { if (parent != null) _backcolour = parent._backcolour; } internal void (xmlnode node) { xmlattributecollection attribcol = node.attributes; _backcolour = attribcol["backcolour"].value; } public string backcolour { get { return _backcolour; } } } } 这里有两个类:继承iconfigurationsectionhandler接口的pagestylehandler类 和 用于从webconfig返回数据的pagestyle类。pagestyle 类可以读取一个xml 节点(自web.config)并且把节点数据保存的backcolour属性中。 设置web.config文件 为了能够访问pagestylehandler必须对web.config做相应的配置。 这样就可以在你的web应用中 访问自己定义的节点了。
‘贰’ win7下面用IIS部署系统,出现web.config无法写入配置文件
楼主~不对啊
怎么看你的网站里又是*.asp又是*.aspx这个好像不能共存吧?
无法读写问题应该是你的网站文件夹属性配置的不正确
你可以按照图片上的配置试一下
把读写都选上
‘叁’ ASP.NET MVC 4中如何读取web.config中的配置
用ConfigurationManager这个类。
‘肆’ 如何高逼格读取Web.config中的AppSettings
在ASP.NET网站里(也包括其他有web.config, app.config)的.NET工程里,读AppSettings的值是个很常见的场景。比如:
<add key="EnableAzureWebTrace" value="true"/>
在代码里读的时候就会用到:
ConfigurationManager.AppSettings["EnableAzureWebTrace"];
这个[]索引器返回的是string类型。所以下一步咱们通常需要类型转换才能在代码里拿来用。比如这个例子里,咱们就要转换成bool。其他时候,可能要转换为int等类型。
string enableAzureWebTraceConfig = ConfigurationManager.AppSettings["EnableAzureWebTrace"];
bool enableAzureWebTrace = bool.Parse(enableAzureWebTraceConfig);
if(enableAzureWebTrace)
{
// do some logic
}
但问题是,config文件的值对于咱们代码来说是不稳定因素,不可控的,这里拿回来的string未必能正确转换格式。所以通常会用TryParse方法来防爆:
string enableAzureWebTraceConfig = ConfigurationManager.AppSettings["EnableAzureWebTrace"];
bool enableAzureWebTrace = false;
if (bool.TryParse(enableAzureWebTraceConfig, out enableAzureWebTrace) && enableAzureWebTrace)
{
// do some logic
}
else
{
throw new ConfigurationException("EnableAzureWebTrace value must be true of false.");
}
当然,不要忘了一点。读出来的string有可能首先就是空的。所以又得加上对string的判断,并且考虑到ConfigurationManager.AppSettings[]索引器本身可能会爆,所以还得加try-catch,最终代码就变成这样了:
try
{
string enableAzureWebTraceConfig = ConfigurationManager.AppSettings["EnableAzureWebTrace"];
if (!string.IsNullOrEmpty(enableAzureWebTraceConfig))
{
bool enableAzureWebTrace = false;
if (bool.TryParse(enableAzureWebTraceConfig, out enableAzureWebTrace) && enableAzureWebTrace)
{
// do some logic
}
else
{
throw new ConfigurationException("EnableAzureWebTrace value must be true of false.");
}
}
}
catch (ConfigurationException ce)
{
// error handling logic
throw;
}
这样的代码非常没有逼格,重用性很差,如果自己的config里面AppSettings比较多,或者一个settings在程序里到处被用,显然不应该每次都把这样的代码到处复制。所以封装一下呗:
public bool IsEnableAzureWebTrace()
{
try
{
bool enableAzureWebTrace = false;
string enableAzureWebTraceConfig = ConfigurationManager.AppSettings["EnableAzureWebTrace"];
if (!string.IsNullOrEmpty(enableAzureWebTraceConfig))
{
if (!bool.TryParse(enableAzureWebTraceConfig, out enableAzureWebTrace))
{
throw new ConfigurationException("EnableAzureWebTrace value must be true of false.");
}
}
return enableAzureWebTrace;
}
catch (ConfigurationException ce)
{
// error handling logic
return false;
}
}
现在要用到EnableAzureWebTrace的地方都只要调用public bool
IsEnableAzureWebTrace()就行了,就把如何读config的逻辑抽离了。重构的目的是,万一以后读config的机制变了,只
要改这一处。不用到处改。但是,重构的粒度还不够。这个方法只能用来读EnableAzureWebTrace这一个设置。要通用一下,让它也能
读其他bool类型的设置。把key单独的抽出来变成参数:
public bool GetBooleanConfiguration(string key)
{
try
{
bool val = false;
string rawConfigValue = ConfigurationManager.AppSettings[key];
if (!string.IsNullOrEmpty(rawConfigValue))
{
if (!bool.TryParse(rawConfigValue, out val))
{
throw new ConfigurationException(string.Format("{0} value must be true of false.", key));
}
}
return val;
}
catch (ConfigurationException ce)
{
// error handling logic
return false;
}
}
但是这还不够,因为这个方法只能满足于bool类型的config,咱们希望有个公用的方法,能读取其他类型。这时候就需要用泛型了。把返回类型给抽离出来。
难点在于,每种数据类型的类型转换写法不一样。比如bool类型是bool.TryParse,int类型是int.TryParse,怎么把这部分逻辑抽象出来呢?
一种办法是用C#本身的类型转换:
(T) Convert.ChangeType(rawConfigValue, typeof (T));
另一种是把类型转换的逻辑作为委托加在方法的参数里,这样就用lambda表达式去传,咱比较偏向这种方法,因为方法的调用者能非常清晰的知道“该干嘛,该怎么干”。
这时候,如果因为非法类型转换爆,是得让调用者知道的。所以个人偏向把TryParse改为Parse,死就要死个明白。
public T GetConfiguration<T>(Func<string, T> parseFunc, string key)
{
try
{
T val = default(T);
string rawConfigValue = ConfigurationManager.AppSettings[key];
if (!string.IsNullOrEmpty(rawConfigValue))
{
return parseFunc(rawConfigValue);
}
return val;
}
catch (ConfigurationException ce)
{
// error handling logic
return default(T);
}
}
现在,调用这个方法就能这样去写:
GetConfiguration<bool>(bool.Parse, "EnableAzureWebTrace");
看起来已经很牛逼了。但其实还不够。考虑到之前说的config值为空字符串的问题,安全一点的做法是,当遇到空字符串时候,返回一个默认值。因为
这种错误,并不是key不存在的错误,而是key存在,但是值没填。非法值是应该认为错误的。但是空值个人认为更应该处理为一种“警告”,是应该有
fallback的策略的,而非不可饶恕的错误。为了返回默认值,咱们可以多加一个委托。
public T GetConfiguration<T>(Func<string, T> parseFunc, Func<T> defaultTValueFunc, string key)
{
try
{
string rawConfigValue = ConfigurationManager.AppSettings[key];
return !string.IsNullOrEmpty(rawConfigValue) ?
parseFunc(rawConfigValue) :
defaultTValueFunc();
}
catch (ConfigurationException ce)
{
// error handling logic
return default(T);
}
}
现在,调用者就能灵活处理遇到config为空时候的默认值了:
GetConfiguration<bool>(bool.Parse, () => false, "EnableAzureWebTrace");
但是如果每次都在条件判断里写上面那样的语句是挺麻烦的,在一般的系统开发中,常常会用一个管理配置的Settings类来对应
Web.config里的设置表,维护这个关系。为了使用方便,咱们会把每个Settings的名字,也就是key,作为属性去暴露给调用者,于是就能
这样写:
public bool EnableAzureWebTrace
{
get
{
return GetConfiguration<bool>(bool.Parse, () => false, "EnableAzureWebTrace");
}
}
以为装逼结束了吗?当然不行!没发现,属性名称和传进去的string类型的key名称是重复的吗?这样写代码是不是有点蛋疼?而且最惨的是,
在VS2015,C#6.0之前(也就是下版本的C#),string这种东西,要是写错了是编译不出来的,所以应该尽量避免用string传
key。经常会发生改了属性名,没有一起改string值的悲剧。比如MVVM框架的RaisePropertyChanged(string)就经常坑
爹(题外话)。。。
好在,.NET4.5有个CallerMemberName特性,意思是”调用咱的方法叫什么名字”,就能帮咱们把这个string参数撸掉。
所以,只需要把方法签名里的string key改成:
public T GetConfiguration<T>(Func<string, T> parseFunc, Func<T> defaultTValueFunc, [CallerMemberName]string key = "")
这样这个方法被调用的时候,key就会自动赋值为调用它的方法或属性名。然后,刚才的那个属性就能够这样去写:
public bool EnableAzureWebTrace
{
get
{
return GetConfiguration<bool>(bool.Parse, () => false);
}
}
以为装逼真的结束了吗?还有最后一步。万一要是碰到有些情况,属性名真的和appSettings里的key名字不一样怎么办?为了灵活处理这种
边缘情况,还可以加个参数,强撸这种名称不一样的情况,如果这个参数被赋值了(下面的supressKey),就用它去读config而不用传入
的key。
下面给出咱博客里读AppSettings的通用代码:
private T TryGetValueFromConfig<T>(Func<string, T> parseFunc, Func<T> defaultTValueFunc,
[CallerMemberName]string key = "", string supressKey = "")
{
try
{
if (!supressKey.IsNullOrEmptyOrWhiteSpace())
{
key = supressKey;
}
var node = ConfigurationManager.AppSettings[key];
return !string.IsNullOrEmpty(node) ? parseFunc(node) : defaultTValueFunc();
}
catch (Exception ex)
{
Logger.Error(string.Format("Error Reading web.config on AppSettings node: {0}", key), ex);
return default(T);
}
}
现在,就能灵活装逼了,给几个例子:
string类型,属性名和key不一样,默认值“FileSystemImageProvider”:
public string PostImageProvider
{
get
{
return TryGetValueFromConfig(_ => _, () => "FileSystemImageProvider", supressKey: "ImageProvider");
}
}
bool类型,默认值想要true
public bool
{
get
{
return TryGetValueFromConfig(bool.Parse, () => true);
}
}
int类型,默认值为20
public int
{
get
{
return TryGetValueFromConfig(int.Parse, () => 20);
}
}
‘伍’ C#怎么读取自定义web.config配置
<appSettings>
<add key="ConnectionString" value="server=192.168.19.250;database=hrms_test;uid=pmstest;pwd=pmstest" />
<add key="WebObjectPath" value="http://localhost/LMS/Files/" />
<add key="PhysicsObjectPath" value="E:/Files/"/>
<add key="SystemCode" value="12" />
<add key="OrganizationPath" value ="organization" />
</appSettings>
System.Configuration.ConfigurationManager.AppSettings["ConnectionString"].ToString();
‘陆’ asp.net(c#)中动态更改web.config连接数据库参数
读写XML的方式修改存储web.config
但是,如果想动态修改connectionstring,建议别放在web.config中,自己建立一个XML文件进行读写
附上一个实例:
已知有一个XML文件(bookstore.xml)如下:
<?xml
version="1.0"
encoding="gb2312"?>
<bookstore>
<book
genre="fantasy"
ISBN="2-3631-4">
<title>Oberon's
Legacy</title>
<author>Corets,
Eva</author>
<price>5.95</price>
</book>
</bookstore>
1、往<bookstore>节点中插入一个<book>节点:
XmlDocument
xmlDoc=new
XmlDocument();
xmlDoc.Load("bookstore.xml");
XmlNode
root=xmlDoc.SelectSingleNode("bookstore");//查找<bookstore>
XmlElement
xe1=xmlDoc.CreateElement("book");//创建一个<book>节点
xe1.SetAttribute("genre","李赞红");//设置该节点genre属性
xe1.SetAttribute("ISBN","2-3631-4");//设置该节点ISBN属性
XmlElement
xesub1=xmlDoc.CreateElement("title");
xesub1.InnerText="CS从入门到精通";//设置文本节点
xe1.AppendChild(xesub1);//添加到<book>节点中
XmlElement
xesub2=xmlDoc.CreateElement("author");
xesub2.InnerText="候捷";
xe1.AppendChild(xesub2);
XmlElement
xesub3=xmlDoc.CreateElement("price");
xesub3.InnerText="58.3";
xe1.AppendChild(xesub3);
root.AppendChild(xe1);//添加到<bookstore>节点中
xmlDoc.Save("bookstore.xml");
//===============================================
结果为:
<?xml
version="1.0"
encoding="gb2312"?>
<bookstore>
<book
genre="fantasy"
ISBN="2-3631-4">
<title>Oberon's
Legacy</title>
<author>Corets,
Eva</author>
<price>5.95</price>
</book>
<book
genre="李赞红"
ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>候捷</author>
<price>58.3</price>
</book>
</bookstore>
2、修改节点:将genre属性值为“李赞红“的节点的genre值改为“update李赞红”,将该节点的子节点<author>的文本修改为“亚胜”。
XmlNodeList
nodeList=xmlDoc.SelectSingleNode("bookstore").ChildNodes;//获取bookstore节点的所有子节点
foreach(XmlNode
xn
in
nodeList)//遍历所有子节点
{
XmlElement
xe=(XmlElement)xn;//将子节点类型转换为XmlElement类型
if(xe.GetAttribute("genre")=="李赞红")//如果genre属性值为“李赞红”
{
xe.SetAttribute("genre","update李赞红");//则修改该属性为“update李赞红”
XmlNodeList
nls=xe.ChildNodes;//继续获取xe子节点的所有子节点
foreach(XmlNode
xn1
in
nls)//遍历
{
XmlElement
xe2=(XmlElement)xn1;//转换类型
if(xe2.Name=="author")//如果找到
{
xe2.InnerText="亚胜";//则修改
break;//找到退出来就可以了
}
}
break;
}
}
xmlDoc.Save("bookstore.xml");//保存。
//==================================================
最后结果为:
<?xml
version="1.0"
encoding="gb2312"?>
<bookstore>
<book
genre="fantasy"
ISBN="2-3631-4">
<title>Oberon's
Legacy</title>
<author>Corets,
Eva</author>
<price>5.95</price>
</book>
<book
genre="update李赞红"
ISBN="2-3631-4">
<title>CS从入门到精通</title>
<author>亚胜</author>
<price>58.3</price>
</book>
</bookstore>
3、删除
<book
genre="fantasy"
ISBN="2-3631-4">节点的genre属性,删除
<book
genre="update李赞红"
ISBN="2-3631-4">节点。
XmlNodeList
xnl=xmlDoc.SelectSingleNode("bookstore").ChildNodes;
foreach(XmlNode
xn
in
xnl)
{
XmlElement
xe=(XmlElement)xn;
if(xe.GetAttribute("genre")=="fantasy")
{
xe.RemoveAttribute("genre");//删除genre属性
}
else
if(xe.GetAttribute("genre")=="update李赞红")
{
xe.RemoveAll();//删除该节点的全部内容
}
}
xmlDoc.Save("bookstore.xml");
//===========================================
最后结果为:
<?xml
version="1.0"
encoding="gb2312"?>
<bookstore>
<book
ISBN="2-3631-4">
<title>Oberon's
Legacy</title>
<author>Corets,
Eva</author>
<price>5.95</price>
</book>
<book>
</book>
</bookstore>
4、显示所有数据。
XmlNode
xn=xmlDoc.SelectSingleNode("bookstore");
XmlNodeList
xnl=xn.ChildNodes;
foreach(XmlNode
xnf
in
xnl)
{
XmlElement
xe=(XmlElement)xnf;
Console.WriteLine(xe.GetAttribute("genre"));//显示属性值
Console.WriteLine(xe.GetAttribute("ISBN"));
XmlNodeList
xnf1=xe.ChildNodes;
foreach(XmlNode
xn2
in
xnf1)
{
Console.WriteLine(xn2.InnerText);//显示子节点点文本
}
}
‘柒’ web项目中如何读取配置文件config.xml
servlet初始化的时候会去读取web.xml,把这个文件的路径配置到web.xml里。或者你在web.xml里加载个初始化类,这个类去加载config.xml