This question applies to all projects really, however my demonstrating environment is an MVC3 app, hence that tag.
I wrote a DisplayNameAttribute
-derived class for our MVC2 projects, like so many people have, so I could localise display names in MVC editors and display templates. I lifted the ValidationAttribute
localisation code used for the error message so that it behaved in a 'standard' way.
Then I noticed that in MVC3 we have the DisplayAttribute
, so I dutifully obsoleted my attribute class in the .Net 4 version of my MVC extension framework and changed the model properties in my current project to use this, e.g:
[Display(ResourceType = typeof(Resources.MyResources), Name = "ResourceName")]
public string ModelProperty { get; set; }
Then I run the web app and I get an error similar to this:
System.InvalidOperationException: Cannot retrieve property 'Name' because localization failed. Type '[Resource Type Here]' is not public or does not contain a public static string property with the name '[Resource Name Here]'.
I use localisation in various places of course, and in class libraries such resources will be typically be marked public. In web applications, however, I will use the App_GlobalResources
folder because, well, that's what it's for!
The problem here is that the resource accessors that are generated for resx files in this folder are always generated as internal access, with no way of changing it.
So, since DisplayAttribute
seems only to look for public members (whereas the localisation code I copied from ValidationAttribute
and applied to my own DisplayNameAttribute
-deriving type simply looks for static members with either public OR internal visibility), it would appear that DisplayAttribute
is off-limits to any MVC web apps that intend to use App_GlobalResources
for the localised strings?
Apart from the fact that this is probably a bug in DisplayAttribute
, has anybody else hit this problem? What did you do to solve it? Should I honour the usage of DisplayAttribute
and change all my resources to be 'properly' embedded as in the class library projects, and set them all as public? Or should I ditch DisplayAttribute in favour of my other class that I know works!?
You should be able to change the access modifier. In Solution Explorer, double-click your .resx file, then near the top-right of the managed resource editor, change the Access Modifier drop-down from Internal
to Public
.
Update
This might work: Making global resources public
This post explains a bit more about the issues with using App_GlobalResources or App_Localresources in MVC applications.
It seems there is no reason to use App_GlobalResources or App_Localresources in MVC applications, and it's better not to use them to avoid problems like the one you are experiencing. (Another problem you can run into, according to the previous link, is failing unit tests. This is because the resources are only available when the ASP.NET runtime is running your website)
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