7

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!?

Andras Zoltan
  • 41,961
  • 13
  • 104
  • 160

3 Answers3

10

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

Daniel Liuzzi
  • 16,807
  • 8
  • 52
  • 57
  • Nevermind my answer. I just noticed the drop-down is enabled just for local resources, not global ones. My apologies. – Daniel Liuzzi Mar 09 '11 at 15:41
  • Oh yeah, absolutely. I have no idea why they force global resources to be internal. – Daniel Liuzzi Mar 09 '11 at 18:21
  • +1 & answer - I haven't done this in the end, I just went back to my own attribute, which worked. However this is probably the easiest way if using `DisplayAttribute` is absolutely required. – Andras Zoltan Mar 10 '11 at 09:04
3

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)

René
  • 9,880
  • 4
  • 43
  • 49
0

You can choose to generate as public see more details here

Community
  • 1
  • 1
DATEx2
  • 3,585
  • 1
  • 24
  • 26
  • no you can't - you can do this on 'normal' resx files that are compiled as embedded resources; but you cannot do this on Asp.Net App_GlobalResource resource files. For some very odd reason they are fixed at internal and you also cannot change the namespace they are compiled into. – Andras Zoltan Mar 12 '11 at 22:57