I am setting NullDisplayText in the DisplayFormat from resource through the following code
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; } } }
My default culture used is "en-US",Once I change the culture to es-AR and load the pages its working fine, but when I change the culture back to en-US fields are not getting converted back.
I change the culture throught the following way
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 { } }
I use DisplayFormat attribute in ViewModel as
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; } }
Here's some insight into what's wrong.
Mvc is using a form of TypeDescriptor (AssociatedMetadataTypeTypeDescriptionProvider(type).GetTypeDescriptor(type)
) to read attributes off your models. The TypeDescriptors are caching information about properties and attributes. So your LocalizedDisplayFormatAttribute
attribute is only getting instantiated once, in terms of the TypeDescriptor api's, which means that the resource information is only read once (at construction). See the bottom of the answer for references.
Solutions that dont work
The blink reaction is to just pull the latest resource information from your LocalizedDisplayFormatAttribute NullDisplayText
every time it is accessed via the getter. Unfortunately DisplayFormatAttribute
NullDisplayText
is not virtual, and you are shadowing the property with a new
keyword. This won't work from a polymorphic dispatch perspective (Mvc is calling the getter as a DisplayFormatAttribute
instead of a LocalizedDisplayFormatAttribute
, so your shadowed property is never being called)
I tried TypeDescriptor.Refresh()
overloads https://msdn.microsoft.com/en-us/library/z1ztz056(v=vs.110).aspx and had no luck
The remaining options that I'm aware of are not as convenient or not amazing in one way or another. Probably not recommended.
AssociatedMetadataTypeTypeDescriptionProvider TypeDescriptors
. I'm not too familiar with these, so there could totally be one. I'm just not seeing one currently.ModelMetadataProvider
of your own. Everything is open source, so its possible, though I'm not sure I would recommend it except as a last resort.Nothing great, I know. Maybe this will give someone else enough insight to come up with something better?
To verify this yourself, see https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/DataAnnotationsModelMetadataProvider.cs CreateMetaData
method which calls SetFromDataTypeAndDisplayAttributes
method setting result.NullDisplayText = displayFormatAttribute.NullDisplayText;
DataAnnotationsModelMetadataProvider
extends AssociatedMetadataProvider
which is repsonsible for passing in the attributes. See https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/AssociatedMetadataProvider.cs GetMetadataForProperty
method as an example.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With