2009-12-04 9 views
19

Ho creato un personalizzato ResourceProvider per estrarre le informazioni di localizzazione da un database. Ora desidero utilizzare DataAnnotation per aggiungere la convalida al modello.DataAnnotation con personalizzato ResourceProvider

DataAnnotation ha ErrorMessageResourceType e ErrorMessageResourceName proprietà, ma ErrorMessageResourceType accetta solo System.Type (vale a dire un file di risorse compilato)

Esiste un modo per ottenere DataAnnotation utilizzare il ResourceProvider personalizzato?

risposta

5

Mi rendo conto che questa è una domanda vecchia, ma volevo aggiungere un po '. Mi sono trovato nella stessa situazione e non sembra esserci alcuna documentazione/blogumentation su questo argomento. Tuttavia, ho trovato un modo per utilizzare un fornitore di risorse personalizzate, con un avvertimento. L'avvertenza è che sono in un'applicazione MVC quindi ho ancora HttpContext.GetLocalResourceObject() disponibile. Questo è il metodo che asp.net usa per localizzare gli oggetti. L'assenza dell'oggetto risorsa non ti impedisce di scrivere la nostra soluzione, anche se è una query diretta delle tabelle DB. Tuttavia, ho pensato che valesse la pena segnalarlo.

Anche se non sono molto contento della seguente soluzione, sembra funzionare. Per ogni attributo di convalida che voglio utilizzare, eredito da detto attributo e sovraccarico IsValid(). La decorazione è simile al seguente:

[RequiredLocalized(ErrorMessageResourceType= typeof(ClassBeginValidated), ErrorMessageResourceName="Errors.GenderRequired")] 
public string FirstName { get; set; } 

Il nuovo attributo assomiglia a questo:

public sealed class RequiredLocalized : RequiredAttribute { 

    public override bool IsValid(object value) { 

     if (! (ErrorMessageResourceType == null || String.IsNullOrWhiteSpace(ErrorMessageResourceName)) ) { 
      this.ErrorMessage = MVC_HtmlHelpers.Localize(this.ErrorMessageResourceType, this.ErrorMessageResourceName); 
      this.ErrorMessageResourceType = null; 
      this.ErrorMessageResourceName = null; 
     } 
     return base.IsValid(value); 
    } 
} 

Note

  • Hai bisogno di decorare il vostro codice con l'attributo derivato, non lo standard one
  • Sto utilizzando ErrorMessageResourceType per passare il tipo della classe da convalidare. Con questo intendo che se sono in una classe cliente e convalida la proprietà FirstName, passerò a tipoof (cliente). Lo sto facendo perché nel backend del mio database sto usando il nome completo della classe (namespace + classname) come chiave (allo stesso modo in cui un URL della pagina è usato in asp.net).
    • MVC_HtmlHelpers.Localize è solo un semplice wrapper per il mio fornitore di risorsa personalizzata

Il codice helper (semi-rubato) si presenta così ....

public static string Localize (System.Type theType, string resourceKey) { 
    return Localize (theType, resourceKey, null); 
} 
public static string Localize (System.Type theType, string resourceKey, params object[] args) { 
    string resource = (HttpContext.GetLocalResourceObject(theType.FullName, resourceKey) ?? string.Empty).ToString(); 
    return mergeTokens(resource, args); 
} 

private static string mergeTokens(string resource, object[] args)  { 
    if (resource != null && args != null && args.Length > 0) { 
     return string.Format(resource, args); 
    } else { 
     return resource; 
    } 
} 
3

Ho usato convalida fluente per raggiungere questo obiettivo. Mi fa risparmiare un sacco di tempo. Questo è il mio validatore globalizzato. Significa che non si utilizzano le anotations di dati, ma a volte le anotations di dati diventano un po 'grandi e disordinate.

Ecco un esempio:

(errors.required, Labels.Email e Errors.AlreadyRegistered sono nella mia cartella delle risorse blobal.)

public class CreateEmployerValidator : AbstractValidator<CreateEmployerModel> { 
    public RegisterUserValidator() { 
     RuleFor(m => m.Email) 
      .NotEmpty() 
      .WithMessage(String.Format(Errors.Required, new object[] { Labels.Email })) 
      .EmailAddress() 
      .WithMessage(String.Format(Errors.Invalid, new object[] { Labels.Email })) 
      .Must(this.BeUniqueEmail) 
      .WithMessage(String.Format(Errors.AlreadyRegistered, new object[] { Labels.Email })); 
    } 

    public bool BeUniqueEmail(this IValidator validator, string email) { 
     //Database request to check if email already there? 
     ... 
    }  
} 

Come ho detto, si tratta di un allontanamento annotazioni di dati modulo, solo perché ho già troppe annotazioni sui miei metodi già!

2

Aggiungerò le mie scoperte da quando ho dovuto combattere con questo. Forse aiuterà qualcuno.

Quando si deriva da RequiredAttribute, sembra interrompere la convalida del lato client. Quindi per risolvere questo problema ho implementato IClientValidatable e implementato il metodo GetClientValidationRules. Resources.GetResources è il metodo di supporto statico che ho che include HttpContext.GetGlobalResourceObject.

L'attributo richiesto abitudine:

public class LocalizedRequiredAttribute : RequiredAttribute, IClientValidatable 
{ 
    public LocalizedRequiredAttribute(string resourceName) 
    { 
     this.ErrorMessage = Resources.GetResource(resourceName); 
    } 

    public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context) 
    { 
     yield return new ModelClientValidationRule 
     { 
      ErrorMessage = this.ErrorMessage, 
      ValidationType= "required" 
     }; 
    } 
} 

Usage:

[LocalizedRequired("SomeResourceName")] 
public string SomeProperty { get; set; } 

E il mio aiuto risorse se qualcuno è interessato:

public class Resources 
{ 
    public static string GetResource(string resourceName) 
    { 
     string text = resourceName; 
     if (System.Web.HttpContext.Current != null) 
     { 
      var context = new HttpContextWrapper(System.Web.HttpContext.Current); 
      var globalResourceObject = context.GetGlobalResourceObject(null, resourceName); 
      if (globalResourceObject != null) 
       text = globalResourceObject.ToString(); 
     } 

     return text; 
    } 
} 
Problemi correlati