为啥自定义配置部分的 StringValidator 总是失败?
Posted
技术标签:
【中文标题】为啥自定义配置部分的 StringValidator 总是失败?【英文标题】: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 属性?似乎验证规则在从配置文件中读取值之前的某个时间点失败。 是的,默认情况下也能正常工作。并非所有字段都具有有效/合理的默认值,尤其是可选字段,因此它似乎无法从配置初始化,这很烦人。 【参考方案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;
【讨论】:
以上是关于为啥自定义配置部分的 StringValidator 总是失败?的主要内容,如果未能解决你的问题,请参考以下文章