18

¿Hay alguna manera de establecer el recurso predeterminado para las validaciones de las anotaciones de datos?Recurso predeterminado para anotaciones de datos en ASP.NET MVC

no quiero hacer algo como esto:

[Required(ErrorMessage="Name required.", ErrorMessageResourceType=typeof(CustomDataAnnotationsResources)] 
public string Name { get; set; } 

me gustaría algo como esto:

Global.asax

DataAnnotations.DefaultResources = typeof(CustomDataAnnotationsResources); 

continuación

[Required] 
public string Name { get; set; } 

¡alguien dame una luz!

gracias de antemano

EDITAR

Mi verdadero problema es resultado de Código EF Primera CTP4. CTP5 arreglarlo. Gracias por todo.

+0

¿Alguien puede arrojar luz sobre si esto es posible y cómo? para acercarse a esto Gracias. –

+0

eche un vistazo a http://adamyan.blogspot.be/2010/02/aspnet-mvc-2-localization-complete.html Puede encontrar la lista de mensajes predeterminados aquí: http://stackoverflow.com/a/24186038/187650 – juFo

Respuesta

13

usted podría intentar hacer esto:

Añadir esta clase en algún lugar de su proyecto:

public class ExternalResourceDataAnnotationsValidator : DataAnnotationsModelValidator<ValidationAttribute> 
{ 
    /// <summary> 
    /// The type of the resource which holds the error messqages 
    /// </summary> 
    public static Type ResourceType { get; set; } 

    /// <summary> 
    /// Function to get the ErrorMessageResourceName from the Attribute 
    /// </summary> 
    public static Func<ValidationAttribute, string> ResourceNameFunc 
    { 
     get { return _resourceNameFunc; } 
     set { _resourceNameFunc = value; } 
    } 
    private static Func<ValidationAttribute, string> _resourceNameFunc = attr => attr.GetType().Name; 

    public ExternalResourceDataAnnotationsValidator(ModelMetadata metadata, ControllerContext context, ValidationAttribute attribute) 
     : base(metadata, context, attribute) 
    { 
     if (Attribute.ErrorMessageResourceType == null) 
     { 
      this.Attribute.ErrorMessageResourceType = ResourceType; 
     } 

     if (Attribute.ErrorMessageResourceName == null) 
     { 
      this.Attribute.ErrorMessageResourceName = ResourceNameFunc(this.Attribute); 
     } 
    } 
} 

y en su Global.asax, añada lo siguiente:

// Add once 
ExternalResourceDataAnnotationsValidator.ResourceType = typeof(CustomDataAnnotationsResources); 

// Add one line for every attribute you want their ErrorMessageResourceType replaced. 
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RangeAttribute), typeof(ExternalResourceDataAnnotationsValidator)); 

que se verá para una propiedad con el mismo nombre que el tipo de validador para el mensaje de error. Puede cambiar eso a través de la propiedad ResourceNameFunc.

EDITAR: AFAIK esto funciona desde MVC2 en adelante, ya que DataAnnotationsModelValidatorProvider se introdujo en MVC2.

+0

@CGK: Por favor, eche un vistazo a esta pregunta.http: //stackoverflow.com/questions/4301218/decorate-model-fields-with-metadata-from-resource-file. He explicado mis requisitos allí aunque he colocado una recompensa en esta pregunta. –

+0

@conqenator: Contestado allí también – CGK

+0

esto resolvió perfectamente mi problema, gracias. –

12

Para lograr esto, he creado una nueva clase que hereda de RequiredAttribute, y el mensaje de error está incrustado dentro de esta nueva clase:

public class RequiredWithMessageAttribute : RequiredAttribute 
{ 
    public RequiredWithMessageAttribute() 
    { 
     ErrorMessageResourceType = typeof(ValidationResource); 
     ErrorMessageResourceName = "RequiredErrorMessage"; 
    } 
} 

El mensaje de error se toma del archivo ValidationResource.resx, donde enumere el mensaje de error de la siguiente manera:

RequiredErrorMessage -> "{0} es obligatorio."

donde {0} = nombre para mostrar.

que luego anotar mis modelos de este tipo, por lo que nunca tenga que repetir mis errores de mensajes declaraciones:

[RequiredWithMessage] 
public string Name { get; set; } 

Una vez hecho esto, un mensaje de error ("El nombre es necesario") aparecerá siempre que la validación falla

Esto funciona correctamente con la validación del lado del servidor de ASP.NET MVC y la validación del lado del cliente.

+0

¡No funciona! Este método funciona para "DisplayNameAttribute" por ejemplo, pero no funciona para "RequiredAttribute". Eso me vuelve loco :(No sé qué hacer. –

+0

amkh, eso es muy extraño. Parece que funciona para mí. –

+0

Funciona solo en el lado del servidor porque no genera el atributo html data-val-required en MVC5 –

3

Hice otro enfoque. Todavía necesita que herede los atributos DataAnnotation, pero puede obtener una solución de traducción más flexible.

Código de my blog post (leerlo Para mayor detalles)

El resultado final

public class User 
{ 
    [Required] 
    [LocalizedDisplayNameAttribute("User_Id")] 
    public int Id { get; set; } 

    [Required] 
    [StringLength(40)] 
    [LocalizedDisplayNameAttribute("User_FirstName")] 
    public string FirstName { get; set; } 

    [Required] 
    [StringLength(40)] 
    [LocalizedDisplayNameAttribute("User_LastName")] 
    public string LastName { get; set; } 
} 

1 Heredar todos los atributos de anotación de datos como éste

public class RequiredAttribute : System.ComponentModel.DataAnnotations.RequiredAttribute 
{ 
    private string _displayName; 

    public RequiredAttribute() 
    { 
     ErrorMessageResourceName = "Validation_Required"; 
    } 

    protected override ValidationResult IsValid(object value, ValidationContext validationContext) 
    { 
     _displayName = validationContext.DisplayName; 
     return base.IsValid(value, validationContext); 
    } 

    public override string FormatErrorMessage(string name) 
    { 
     var msg = LanguageService.Instance.Translate(ErrorMessageResourceName); 
     return string.Format(msg, _displayName); 
    } 
} 

2 Heredar DisplayNameAttribute

public class LocalizedDisplayNameAttribute : DisplayNameAttribute 
{ 
    private PropertyInfo _nameProperty; 
    private Type _resourceType; 

    public LocalizedDisplayNameAttribute(string className, string propertyName) 
     : base(className + (propertyName == null ? "_Class" : ("_" + propertyName))) 
    { 

    } 

    public override string DisplayName 
    { 
     get 
     { 
      return LanguageService.Instance.Translate(base.DisplayName) ?? "**" + base.DisplayName + "**"; 
     } 
    } 
} 

3. Crear el servicio lingüístico (se puede cambiar a cualquier idioma de origen en ella)

public class LanguageService 
{ 
    private static LanguageService _instance = new LanguageService(); 
    private List<ResourceManager> _resourceManagers = new List<ResourceManager>(); 

    private LanguageService() 
    { 
    } 

    public static LanguageService Instance { get { return _instance; } } 

    public void Add(ResourceManager mgr) 
    { 
     _resourceManagers.Add(mgr); 
    } 

    public string Translate(string key) 
    { 
     foreach (var item in _resourceManagers) 
     { 
      var value = item.GetString(key); 
      if (value != null) 
       return value; 
     } 

     return null; 
    } 
} 

Por último es necesario registrar las tablas de cadenas que se utiliza para traducir los mensajes de validación y sus modelos

LanguageService.Instance.Add(MyNameSpace.ModelResource.ResourceManager); 
LanguageService.Instance.Add(MyNameSpace.ValidationResources.ResourceManager); 
+0

+1 para compartir todo ese código. Todavía tengo que averiguar cómo usarlo (LoL), pero parece que va a resolver mi problema – ekkis

Cuestiones relacionadas