【问题标题】:Why does StringValidator always fail for custom configuration section?为什么自定义配置部分的 StringValidator 总是失败?
【发布时间】:2011-04-04 20:46:24
【问题描述】:

我通过继承 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 值,我也会收到此错误。如果我删除验证器,它会完美运行。有谁知道如何解决这个问题?

【问题讨论】:

  • 我已经阅读了整个系列,不幸的是它没有解释我收到错误的原因。
  • 您是否尝试过使用(有效)默认值初始化 ApplicationCode 属性?似乎验证规则在从配置文件中读取值之前的某个时间点失败。
  • 是的,默认情况下也能正常工作。并非所有字段都具有有效/合理的默认值,尤其是可选字段,因此它似乎无法从配置初始化,这很烦人。

标签: c# asp.net configuration


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 你说得对,我希望我也不必这样做。不过我试过了,它可以工作,所以谢谢。
    • 我花了一整天的时间来解决这个问题。太棒了——这对我有用。
    【解决方案3】:

    我有一段时间遇到这个问题,然后我意识到验证器不是为了使属性或元素成为必需的,它们是为了验证它们。

    要使属性成为必需,您需要使用 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);
    

    这样做,配置框架将自己处理需要的属性,验证器处理验证值中的内容。验证器并不意味着需要做一些事情。

    这也适用于需要子元素的元素。例如。如果您正在使用子元素制作自定义 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)]
    

    然后放弃字符串验证器。

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        猜你喜欢
        • 2019-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-25
        • 1970-01-01
        • 1970-01-01
        • 2010-12-18
        相关资源
        最近更新 更多