C# 为什么自定义配置部分的StringValidator总是失败?
我通过继承C# 为什么自定义配置部分的StringValidator总是失败?,c#,asp.net,configuration,C#,Asp.net,Configuration,我通过继承ConfigurationSection在c#类库中创建了一个自定义配置节。我在我的web应用程序(也是c#,ASP.NET)中引用类库,填充适当的属性,一切都很好。当我开始添加验证器时,问题就开始了 例如,此属性: [ConfigurationProperty("appCode", IsRequired = true)] public string ApplicationCode { get { retu
ConfigurationSection
在c#类库中创建了一个自定义配置节。我在我的web应用程序(也是c#,ASP.NET)中引用类库,填充适当的属性,一切都很好。当我开始添加验证器时,问题就开始了
例如,此属性:
[ConfigurationProperty("appCode", IsRequired = true)]
public string ApplicationCode
{
get
{
return (string)base["appCode"];
}
set
{
base["appCode"] = value;
}
}
“照原样”可以很好地工作,但只要我添加以下内容:
[StringValidator(MinLength=1)]
它爆炸时出现以下错误:
属性“appCode”的值无效。错误是:字符串长度必须至少为1个字符
即使在我的
web.config
文件中有一个有效的appCode
值,我也会收到此错误。如果我删除了验证器,它就可以正常工作。有人知道如何解决这个问题吗?似乎答案确实是因为他们没有默认值。似乎有点奇怪,因此如果有人有更好的答案,请告诉我,我会接受他们的答案。根据以下实现,我可以通过使用显式作为属性集合的键而不是字符串来解决此问题:
public class AssemblyElement : ConfigurationElement
{
private static readonly ConfigurationProperty _propAssembly;
private static readonly ConfigurationPropertyCollection _properties;
static AssemblyElement()
{
_propAssembly = new ConfigurationProperty("assembly", typeof(string), null, null, new StringValidator(1), ConfigurationPropertyOptions.IsKey | ConfigurationPropertyOptions.IsRequired);
_properties = new ConfigurationPropertyCollection();
_properties.Add(_propAssembly);
}
internal AssemblyElement() { }
public AssemblyElement(string assemblyName)
{
this.Assembly = assemblyName;
}
[ConfigurationProperty("assembly", IsRequired = true, IsKey = true, DefaultValue = "")]
[StringValidator(MinLength = 1)]
public string Assembly
{
get { return (string)base[_propAssembly]; }
set { base[_propAssembly] = value; }
}
internal AssemblyName AssemblyName
{
get { return new AssemblyName(this.Assembly); }
}
protected override ConfigurationPropertyCollection Properties
{
get { return _properties; }
}
}
(此代码与configuration element类中反映的代码非常相似。我仍然希望不必重复验证,但至少此代码允许我在仍然需要输入值的情况下指定一个空白默认值。)我有一段时间遇到此问题,然后我意识到验证器并不是为了使属性或元素成为必需的,而是为了验证它们 要使属性成为必需的,您需要使用IsRequired和ConfigrationPropertyOptions.IsRequired,例如
[ConfigurationProperty("casLogoutUrl", DefaultValue = null, IsRequired = true, Options = ConfigurationPropertyOptions.IsRequired)]
[StringValidator(MinLength=10)]
或(如果使用api)
这样,配置框架将自行处理所需的属性,而验证器将处理验证值中的内容。验证器不是用来做需要的东西的
这也适用于元素,使子元素成为必需的元素。例如,如果您正在使用子元素创建自定义ConfigSection,并且需要一个子元素。但是,如果您创建的CustomValidator继承自ConfigurationValidatorBase,则需要使用ElementInformation.IsPresent,例如
public override void Validate(object value)
{
CredentialConfigurationElement element = (CredentialConfigurationElement)value;
if (!element.ElementInformation.IsPresent)
return; //IsRequired is handle by the framework, don't throw error here only throw an error if the element is present and it fails validation.
if (string.IsNullOrEmpty(element.UserName) || string.IsNullOrEmpty(element.Password))
throw new ConfigurationErrorsException("The restCredentials element is missing one or more required Attribute: userName or password.");
}
长话短说,您缺少属性的选项部分以使其成为必需的,并且不应该使用StringValidator(MinLength=1)使其成为必需的。事实上,StringValidator(MinLength=1)是完全冗余的。如果将其设为必需,则MinLength=1不可能在没有必需的先失败的情况下失败,因为如果它存在,则保证至少有1个字符长
将验证器更改为
[ConfigurationProperty("appCode", IsRequired = true, Options=ConfigurationPropertyOptions.IsRequired)]
然后丢弃字符串验证器。可以通过以下任一方法来解析字符串验证器:
- 删除MinLength参数
- 设置MinLength=0
- 删除StringValidator属性
- 向ConfigurationProperty属性添加DefaultValue
[ConfigurationProperty("title", IsRequired = true, DefaultValue = "something")]
[StringValidator(InvalidCharacters = "~!@#$%^&*()[]{}/;’\"|\\"
, MinLength = 1
, MaxLength = 256)]
public string Title
{
get { return this["title"] as string; }
set { this["title"] = value; }
}
我已经阅读了整个系列,不幸的是它没有解释我收到错误的原因。您是否尝试过用(有效的)默认值初始化ApplicationCode属性?在从配置文件中读取值之前,验证规则似乎会在某个点失败。是的,它在默认情况下运行良好。但并不是所有字段都有有效/合理的默认值,尤其是可选字段,所以它似乎无法从配置中初始化,这很烦人。你说得对,我希望我也不必这样做。不过我试过了,效果不错,谢谢。我花了一整天的时间来解决这个问题。好极了,这对我来说是个好办法。
[ConfigurationProperty("title", IsRequired = true, DefaultValue = "something")]
[StringValidator(InvalidCharacters = "~!@#$%^&*()[]{}/;’\"|\\"
, MinLength = 1
, MaxLength = 256)]
public string Title
{
get { return this["title"] as string; }
set { this["title"] = value; }
}