2011-05-31 1055 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; 
    } 

而且一切順利!