为什么StringValidator总是因自定义配置部分而失败?

我通过inheritanceConfigurationSection在ac#类库中创建了一个自定义配置节。 我在我的Web应用程序(也是c#,ASP.NET)中引用了类库,填写了适当的属性,一切都很好。 当我开始添加validation器时,问题就开始了。

例如,这个属性:

  [ConfigurationProperty("appCode", IsRequired = true)] public string ApplicationCode { get { return (string)base["appCode"]; } set { base["appCode"] = value; } } 

因为它工作正常,但只要我添加这个:

  [StringValidator(MinLength=1)] 

它轰炸了以下错误:

属性“appCode”的值无效。 错误是:字符串长度必须至少为1个字符。

即使我的web.config文件中有一个有效的appCode值,我也会收到此错误。 如果我删除validation器,它可以完美地工作。 有谁知道怎么解决这个问题?

我能够通过使用显式ConfigurationProperty作为我的属性集合的关键而不是字符串来解决此问题,如以下实现:

 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; } } } 

(这段代码是在从AssemblyInfo配置元素类反映的代码之后严格建模的。我仍然希望我不必复制我的validation,但至少这段代码允许我指定一个空白的默认值,同时仍然需要一个值进入。)

似乎答案确实是因为它们没有默认值。 看起来很奇怪,所以如果有人有更好的答案让我知道,我会接受他们的。

我有一段时间遇到这个问题,然后我意识到validation器不是用于制作所需的属性或元素,而是用于validation它们。

要创建所需的属性,您需要使用IsRequired和ConfigrationPropertyOptions.IsRequired,例如

 [ConfigurationProperty("casLogoutUrl", DefaultValue = null, IsRequired = true, Options = ConfigurationPropertyOptions.IsRequired)] [StringValidator(MinLength=10)] 

或者(如果使用api)

 ConfigurationProperty casLoginUrl = new ConfigurationProperty("casLoginUrl", typeof(string), null, null, new StringValidator(1), ConfigurationPropertyOptions.IsRequired); 

这样做,Configuration框架将自己处理所需的属性,validation器处理validation值中的内容。 validation器不是用于制作所需的东西。

这也适用于需要子元素的元素。 例如,如果您使用子元素创建自定义ConfigSection并且需要子元素。 但是,如果您创建一个inheritance自ConfigurationValidatorBase的CustomValidator,则需要使用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个字符长。

将validation器更改为

 [ConfigurationProperty("appCode", IsRequired = true, Options=ConfigurationPropertyOptions.IsRequired)] 

然后抛弃字符串validation器。

StringValidator的解析可以通过以下任何一种方式完成:

  • 删除MinLength参数
  • 设置MinLength = 0
  • 删除StringValidator属性
  • DefaultValue添加到ConfigurationProperty属性

该物业的理想定义如下:

 [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; } }