2011-08-11 82 views
3

我有一個DateTime TemplateEditor,我想向它添加正則表達式驗證。我有一個RegularExpression屬性可以用來裝飾模型,但是我不想用正則表達式來裝飾我所有模型中的每個日期時間屬性。如何在MVC3的TemplateEditor中將驗證屬性添加到模型屬性中

有沒有辦法讓我的自定義TemplateEditor添加適當的unobstrusive標籤時,它呈現文本框?

回答

3

您應該使用自定義ModelMetadataValidatorProvider插入驗證程序,而不是在模板中添加驗證程序。首先,創建您的ModelMetadataProvider類:

public class MyModelMetadataValidatorProvider : DataAnnotationsModelValidatorProvider 
{ 

    internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory = Create; 
    internal static Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories = new Dictionary<Type, DataAnnotationsModelValidationFactory>() { 
     { 
      typeof(RegularExpressionAttribute), 
      (metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute) 
     } 
    }; 

    internal static ModelValidator Create(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) 
    { 
     return new DataAnnotationsModelValidator(metadata, context, attribute); 
    } 

    protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes) 
    { 
     List<ModelValidator> vals = base.GetValidators(metadata, context, attributes).ToList(); 

     // inject our new validator 
     if (metadata.ModelType.Name == "DateTime") 
     { 
      DataAnnotationsModelValidationFactory factory; 

      RegularExpressionAttribute regex = new RegularExpressionAttribute(
       "^(((0?[1-9]|1[012])/(0?[1-9]|1\\d|2[0-8])|(0?[13456789]|1[012])/(29|30)|(0?[13578]|1[02])/31)/(19|[2-9]\\d)\\d{2}|0?2/29/((19|[2-9]\\d)(0[48]|[2468][048]|[13579][26])|(([2468][048]|[3579][26])00)))$"); 
      regex.ErrorMessage = "Invalid date format"; 
      if (!AttributeFactories.TryGetValue(regex.GetType(), out factory)) 
       factory = DefaultAttributeFactory; 

      vals.Add(factory(metadata, context, regex)); 
     } 

     return vals.AsEnumerable(); 
    } 
} 

接下來,註冊您的ModelMetadataValidatorProvider在Global.asax.csApplication_Start

ModelValidatorProviders.Providers.Clear(); 
    ModelValidatorProviders.Providers.Add(new MyModelMetadataValidatorProvider()); 

現在,當你訪問一個模型,RegularExpressionAttribte將被連接到每個DateTime字段。您也可以擴展它以提供本地化的DateTime正則表達式和消息。

counsellorben

+0

那是kickass。謝謝。 –

0

這只是闡述(和固定幾個小問題)上Consellorben的回答

public class ExtendedDataAnnotationsModelValidatorProvider : DataAnnotationsModelValidatorProvider 
{ 
    internal static DataAnnotationsModelValidationFactory DefaultAttributeFactory = Create; 
    internal static Dictionary<Type, DataAnnotationsModelValidationFactory> AttributeFactories = new Dictionary<Type, DataAnnotationsModelValidationFactory>() 
    { 
     { 
      typeof(RegularExpressionAttribute), 
      (metadata, context, attribute) => new RegularExpressionAttributeAdapter(metadata, context, (RegularExpressionAttribute)attribute) 
     } 
    }; 

    internal static ModelValidator Create(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) 
    { 
     return new DataAnnotationsModelValidator(metadata, context, attribute); 
    } 

    protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes) 
    { 
     if(!attributes.Any(i => i is RegularExpressionAttribute)) 
     { 
      if (typeof(DateTime).Equals(metadata.ModelType) || (metadata.ModelType.IsGenericType && typeof(DateTime).Equals(metadata.ModelType.GetGenericArguments()[0]))) 
      { 
       DataAnnotationsModelValidationFactory factory; 
       RegularExpressionAttribute regex = null; 
       switch (metadata.DataTypeName) 
       { 
        case "Date": 
         regex = new RegularExpressionAttribute(RegExPatterns.Date) { ErrorMessage = "Invalid date. Please use a m/d/yyyy format" }; 
         break; 
        case "Time": 
         regex = new RegularExpressionAttribute(RegExPatterns.Time) { ErrorMessage = "Invalid time. Please use a h:mm format" }; 
         break; 
        default: //DateTime 
         regex = new RegularExpressionAttribute(RegExPatterns.DateAndTime) { ErrorMessage = "Invalid date/time. Please use a m/d/yyyy h:mm format" }; 
         break; 
       } 

       if (!AttributeFactories.TryGetValue(regex.GetType(), out factory)) 
        factory = DefaultAttributeFactory; 

       yield return factory(metadata, context, regex); 
      } 
     } 
    } 
} 

,然後註冊它在Global.asax像這樣:

ModelValidatorProviders.Providers.Add(new ExtendedDataAnnotationsModelValidatorProvider()); 
+0

我喜歡這些修訂版本,我將其保存以供將來使用。我的代碼是一個注入器類,我不需要擔心與預先存在的屬性可能發生衝突,因爲所有屬性都是在注入器類中創建的。另外,爲什麼要運行標準DataAnnotationsModelValidator提供程序和您的自定義提供程序? – counsellorben