2011-05-31 1058 views
2

(.NET 4.0 /的WebForms/EF 4.1 POCO)MetadataType属性被忽略了在自定义验证

嗨,使用自定义验证使用具有的WebForms DataAnnotations(

I'm源代码是波纹管)。

当我在生成的类中直接使用DataAnnotations时,一切都很顺利。但是,当我在具有部分类的元数据类中使用DataAnnotations时,DataAnnotations属性似乎在验证中被绕过。我知道元数据已被正确识别,因为当我将数据保存在DbContext中时,它将得到验证,并且EntityValidationErrors将返回验证的错误。

我做了一些搜索,发现这个:(http://stackoverflow.com/questions/2657358/net-4-rtm-metadatatype-attribute-ignored-when-using-validator/2657644#2657644)。不幸的是,我的实施没有奏效。可能我不知道该把它叫到哪里。我试图在元数据类的构造函数中调用它,但它没有工作。

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

谢谢!

回答

1

我在这里找到了解决方案(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; 
    } 

而且一切顺利!