tutorial net mvc español asp c# asp.net-mvc asp.net-mvc-3 asp.net-mvc-4

c# - net - Configuración única de DisplayFormatAttribute personalizada una vez



mvc asp.net c# (1)

Estoy configurando NullDisplayText en DisplayFormat desde el recurso a través del siguiente código

public class LocalizedDisplayFormatAttribute : DisplayFormatAttribute { private readonly PropertyInfo _propertyInfo; public LocalizedDisplayFormatAttribute(string resourceKey, Type resourceType) : base() { this._propertyInfo = resourceType.GetProperty(resourceKey, BindingFlags.Static | BindingFlags.Public); if (this._propertyInfo == null) { return; } base.NullDisplayText = (string)this._propertyInfo.GetValue(this._propertyInfo.DeclaringType, null); } public new string NullDisplayText { get { return base.NullDisplayText; } set { base.NullDisplayText = value; } } }

Mi cultura predeterminada utilizada es "en-US", una vez que cambio la cultura a es-AR y cargue las páginas funciona bien, pero cuando cambio la cultura a los campos en-US no vuelvo a convertir.

Cambio la cultura de la siguiente manera

protected void Application_AcquireRequestState(object sender, EventArgs e) { try { HttpCookie cookie = HttpContext.Current.Request.Cookies.Get("CurrentCulture"); string culutureCode = cookie != null && !string.IsNullOrEmpty(cookie.Value) ? cookie.Value : "en"; CultureInfo ci = new CultureInfo(culutureCode); System.Threading.Thread.CurrentThread.CurrentUICulture = ci; System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name); } catch { } }

Yo uso el atributo DisplayFormat en ViewModel como

public class AlarmCodeDetailsViewModel { /// <summary> /// Gets or sets the alarm code ID /// </summary> public int AlarmCodeID { get; set; } /// <summary> /// Gets or sets the alarm code /// </summary> [LocalizedDisplayName("Label_AlarmCode")] [LocalizedDisplayFormatAttribute("Warning_NullDisplayText", typeof(Properties.Resources), HtmlEncode = false)] public string Code { get; set; } /// <summary> /// Gets or sets the Description /// </summary> [LocalizedDisplayName("Label_Description")] [LocalizedDisplayFormatAttribute("Warning_NullDisplayText", typeof(Properties.Resources), HtmlEncode = false)] public string Description { get; set; } /// <summary> /// Gets or sets the Notes /// </summary> [LocalizedDisplayName("Label_Notes")] [LocalizedDisplayFormatAttribute("Warning_NullDisplayText", typeof(Properties.Resources), HtmlEncode = false)] public string Notes { get; set; } }


Aquí hay una idea de lo que está mal.

Mvc está utilizando una forma de TypeDescriptor ( AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type) ) para leer los atributos de sus modelos. Los TypeDescriptors están almacenando en caché información sobre propiedades y atributos. Por lo tanto, su atributo LocalizedDisplayFormatAttribute solo se creará una instancia una vez, en términos de la API de TypeDescriptor, lo que significa que la información del recurso solo se lee una vez (en la construcción). Ver la parte inferior de la respuesta para referencias.

Soluciones que no funcionan

  1. La reacción de parpadeo es simplemente extraer la última información de recursos de su LocalizedDisplayFormatAttribute NullDisplayText cada vez que se accede a través del getter. Desafortunadamente DisplayFormatAttribute NullDisplayText no es virtual, y está sombreando la propiedad con una palabra clave new . Esto no funcionará desde una perspectiva de envío polimórfico (Mvc está llamando al getter como un DisplayFormatAttribute lugar de un LocalizedDisplayFormatAttribute , por lo que nunca se llamará a su propiedad sombreada)

  2. TypeDescriptor.Refresh() sobrecarga https://msdn.microsoft.com/en-us/library/z1ztz056(v=vs.110).aspx y no tuve suerte

Las opciones restantes que conozco no son tan convenientes ni sorprendentes de una manera u otra. Probablemente no recomendado.

  1. Alguna manera de actualizar correctamente los AssociatedMetadataTypeTypeDescriptionProvider TypeDescriptors . No estoy muy familiarizado con estos, por lo que podría haber uno totalmente. Simplemente no estoy viendo uno actualmente.
  2. ModelMetadataProvider a ModelMetadataProvider o cree un ModelMetadataProvider propio. Todo es de código abierto, por lo que es posible, aunque no estoy seguro de que lo recomendaría, excepto como último recurso.
  3. Posiblemente pueda trabajar con las API de TypeDescriptor para forzar una nueva instanciación de su atributo cada vez que se tira de él. Ver https://.com/a/12143653/897291 .
  4. Modele las propiedades necesarias directamente en MVC (como propiedades del modelo, en lugar de atributos). Podrían ser propiedades completamente nuevas, o podría tener algún tipo de lógica dentro de sus propiedades originales, que cuando null devuelva algo más. Difícil de manejar sin embargo.

Nada grandioso, lo sé. Tal vez esto le dará a alguien más suficiente información para llegar a algo mejor?

Para verificar esto usted mismo, consulte https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/DataAnnotationsModelMetadataProvider.cs Método CreateMetaData que llama SetFromDataTypeAndDisplayAttributes método result.NullDisplayText = displayFormatAttribute.NullDisplayText;

DataAnnotationsModelMetadataProvider extiende AssociatedMetadataProvider que es responsable de pasar los atributos. Consulte el método https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/AssociatedMetadataProvider.cs GetMetadataForProperty como ejemplo.