Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implicit localization, strongly typed resources, App_LocalResources and embedded resources

tl;dr Does strongly typed resource code generation work with normal (non-embedded) resources in App_LocalResources?

If not then why, and does the alternative of using embedded resources in satellite assemblies work with implicit localization?

The rest of this post just explains where I currently am in solving these questions, feel free to ignore it if you know the answers.


When using implicit localization (meta:resourceKey="Foo" syntax), I understand that one would need to write their own resource provider if one wants to embed the resources in satellite assemblies. The reason would be that ASP.NET always uses the default provider for these, and that this provider expects resx files in App_LocalResources that can be retrieved at runtime. Also see this question, which has no answer at the time of this writing.

If that assumption is correct, then it doesn't seem possible to use strongly typed generated classes (using ResXFileCodeGenerator) without writing such a provider (which we'd like to avoid doing), as enabling code generation requires the use of embedded resources.

Because the use of generated types appears to work perfectly fine for global resources, I want to question that second assumption:

  • If I can generate strongly typed classes for global resources (in App_GlobalResources using GlobalResourceProxyGenerator) without embedding them in a satellite assembly (Build Action set to Content as opposed to Embedded), then why can't I do the same for local resources? Why can't the generated code find and use the resx files in App_LocalResources?

Note that the exception thrown when attempting to do this is a System.Resources.MissingManifestResourceException containing the following message:

Could not find any resources appropriate for the specified culture or the neutral culture. Make sure "PROJECT.App_LocalResources.PAGE.aspx.resources" was correctly embedded or linked into assembly "PROJECT" at compile time, or that all the satellite assemblies required are loadable and fully signed.

I know that this message is misleading, as it clearly looks up satellite assemblies instead of trying the resx files (or whatever they're compiled to by the runtime, App_LocalResources.dll I guess).

  • If there is a good reason why this is not allowed (and we are thus forced to use embedded resources in satellite assemblies), is there a good implementation of a resource provider that can look up resources in satellite assemblies when doing implicit localization? Surely somebody has tried to do this before, and it doesn't sound like the application developer's job to tackle this kind of plumbing problem.

  • As a sub-question to the previous one, I also assume that when using embedded resources in satellite assemblies, one wouldn't put the resx files in the App_* directories, as these are special directories used by the runtime. Indeed, the resx files aren't even deployed, so the directories would be empty. Is that correct, and are there what would pass as best practices regarding this?


I suppose another way of formulating the question is: Can I make ResXFileCodeGenerator behave like GlobalResourceProxyGenerator when it comes to generating code that can load assemblies compiled by the runtime, as opposed to satellite assemblies compiled at build time?

like image 889
tne Avatar asked Jun 25 '14 16:06

tne


1 Answers

Embedded resources can co-exist with ASP.NET Resource provider resources that live in the App_LocalResources/App_GlobalResources folder. But all the intrinsic WebForms localization features only work with the resources that are fed by the ASP.NET Resource Provider, which means the resources by default come out of the App_ folders only - not from embedded resources.

Embedded strongly typed resources do not use the ASP.NET Resource Provider - they use a stock .NET Resource Manager and when you use them you lose some of the optimizations that the ASP.NET ResourceProvider system uses vis a vis caching and loading of resources. It's more efficient in the ASP.NET scenario.

As you correctly point out it's possible to do this by creating a custom resource provider that reads embedded resources (or resources from another source such as a database), but you have to create this resource provider and hook it up. I wrote about this in an article some time ago (using a SQL database provider): http://www.west-wind.com/presentations/wwDbResourceProvider/

I wouldn't recommend mixing App_ folder resources from the Resource Provider with strongly typed resources because you'll end up with two different sets of resources loaded using different mechanisms. It works and can be done but it's just not very inconsistent. Pick one approach or the other. For Web Forms the resource provider model works better simply because it's the only way you'll be able to use implicit resources.

Note that ASP.NET MVC doesn't use the ASP.NET Resource Provider typically (although it could) and rather relies on strongly typed resources embedded into the code. If your WebForms code is mainly script based then using embedded resources might work well, but if you need to bind control properties the Resource Provider is the only way to go.

like image 55
Rick Strahl Avatar answered Oct 10 '22 02:10

Rick Strahl