问题描述
|
(.NET 4.0 / WebForms / EF 4.1 POCO)
你好
我正在使用自定义验证程序将DataAnnotations与WebForms一起使用(源代码在下面)。
当我直接在生成的类中使用DataAnnotations时,一切都会很好。但是,当我在带有部分类的Metadata类中使用DataAnnotations时,DataAnnotations属性似乎在验证中被绕过。我知道已正确识别了元数据,因为当我将数据保存在DbContext中时,它正在被验证,而EntityValidationErrors返回已验证的错误。
我进行了一些搜索,发现了这一点:(http://stackoverflow.com/questions/2657358/net-4-rtm-Metadatatype-attribute-ignored-when-using-validator/2657644#2657644)。不幸的是我的实现没有用。可能是我不知道在哪里打电话。我尝试在Metadata类的构造函数中调用它,但没有用。
public static class MetadataTypesRegister
{
static bool installed = false;
static object installedLock = new object();
public static void Install()
{
if (installed)
{
return;
}
lock (installedLock)
{
if (installed)
{
return;
}
// Todo: for debug purposes only (please remove in production)
Assembly assembly = Assembly.GetExecutingAssembly();
Type[] types = assembly.GetTypes();
//------
foreach (Type type in Assembly.GetExecutingAssembly().GetTypes())
{
foreach (MetadataTypeAttribute attrib in type.GetCustomAttributes(typeof(MetadataTypeAttribute),true))
{
TypeDescriptor.AddProviderTransparent(
new AssociatedMetadataTypeTypeDescriptionProvider(type,attrib.MetadataClasstype),type);
}
}
installed = true;
}
}
}
要验证的模型位于DataLayer.dll中,而DataAnnotationsValidator类位于Common.dll中。
这是我的DataAnnotationsValidator类:
[ToolBoxData(\"<{0}:DataAnnotationsValidator runat=server></{0}:DataAnnotationsValidator>\")]
public class DataAnnotationsValidator : BaseValidator
{
private string _propertyName = string.Empty;
public string PropertyName
{
get { return _propertyName; }
set { _propertyName = value; }
}
public string _sourceType = string.Empty;
public string SourceType
{
get { return _sourceType; }
set { _sourceType = value; }
}
public ValidationDataType _type = ValidationDataType.String;
public ValidationDataType Type
{
get { return _type; }
set { _type = value; }
}
public string _cssError = string.Empty;
public string CssError
{
get { return _cssError; }
set { _cssError = value; }
}
protected override bool EvaluateIsValid()
{
// get specified type for reflection
Type objectType = System.Type.GetType(_sourceType,true,true);
// get a property to validate
PropertyInfo prop = objectType.GetProperty(_propertyName);
// get the control to validate
TextBox control = this.FindControl(this.ControlTovalidate) as TextBox;
object valueTovalidate = null;
if (control.Text != String.Empty)
{
if (Type == ValidationDataType.Double)
valueTovalidate = double.Parse(control.Text);
else if (Type == ValidationDataType.Integer)
valueTovalidate = int.Parse(control.Text);
else if (Type == ValidationDataType.Date)
valueTovalidate = DateTime.Parse(control.Text);
else if (Type == ValidationDataType.Currency)
valueTovalidate = decimal.Parse(control.Text);
else
valueTovalidate = control.Text;
}
CultureInfo currentCulture = Thread.CurrentThread.CurrentCulture;
bool result = true;
try
{
Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
// The custom validator can return only one error message. Because the field model being validated can have more than
// one DataAnnotation validation (required,Range,RegularExpression,etc.) the DataAnnotationsValidator will return only the first
// error message that it evaluates.
foreach (ValidationAttribute attr in prop.GetCustomAttributes(typeof(ValidationAttribute),true).OfType<ValidationAttribute>())
{
Thread.CurrentThread.CurrentCulture = currentCulture;
if (!attr.IsValid(valueTovalidate))
{
result = false;
var displayNameAttr = prop.GetCustomAttributes(typeof(displayNameAttribute),true).OfType<displayNameAttribute>().FirstOrDefault();
string displayName = displayNameAttr == null ? prop.Name : displayNameAttr.displayName;
ErrorMessage = attr.FormatErrorMessage(displayName);
break;
}
}
}
finally
{
Thread.CurrentThread.CurrentCulture = currentCulture;
if (result)
{
if (!string.IsNullOrEmpty(CssError))
control.RemoveCssClass(CssError);
}
else
{
if (!string.IsNullOrEmpty(CssError))
control.AddCssClass(CssError);
}
}
return result;
}
}
谢谢!!
解决方法
我在这里找到了解决方案(http://stackoverflow.com/questions/5600707/how-do-you-do-web-forms-model-validation)。
我修改了EvaluateIsValid方法的代码,以包括下面的代码以查找元数据属性:
// get specified type for reflection
Type objectType = System.Type.GetType(_sourceType,true,true);
// check for the types that have MetadataType attribute because
// it is they who have the DataAnnotations attributes
IEnumerable<MetadataTypeAttribute> mt = objectType.GetCustomAttributes(typeof(MetadataTypeAttribute),false).OfType<MetadataTypeAttribute>();
if (mt.Count() > 0)
{
objectType = mt.First().MetadataClassType;
}
一切顺利!