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

时间:2010-08-27 14:55:02

标签: c# asp.net configuration

我通过继承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个字符。

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

4 个答案:

答案 0 :(得分:4)

根据以下实现,我能够使用显式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配置元素类反映的代码之后的密切建模。我仍然希望我不必复制我的验证,但至少这段代码允许我指定一个空白的默认值同时仍然需要输入一个值。)

答案 1 :(得分:3)

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

答案 2 :(得分:2)

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

要创建所需的属性,您需要使用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框架将自己处理所需的属性,验证器处理验证值中的内容。验证器不适用于制作所需的东西。

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

将验证器更改为

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

然后抛弃字符串验证器。

答案 3 :(得分:1)

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