I am trying to roll my own DBResourceProviderFactory based on this MSDN article.
I downloaded the code and opened the solution. For a start I do not want a seperate solution. The resource provider should be in my web application. So I copied all the code files (DBResourceProviderFactory.cs DBResourceProvider.cs StringResourcesDALC.cs ...) to my project and corrected the namespace, fixed the local resources and edited the connectionstring in the DALC accordingly.
In the web.config I addes this gloablization configuration:
<system.web>
<!--If MyApllicationNamespace is ommited, exception is thrown at runtime.-->
<globalization culture="auto" uiCulture="auto" resourceProviderFactoryType="MyApplicationNamespace.DBResourceProviderFactory" />
</system.web>
In the default.aspx I added this label:
<asp:Label ID="lblHello" runat="server" Text="not translated" meta:resourceKey="lblHello"></asp:Label>
The database table contains 3 rows of data for this resource.
Upon building the application and running it in the browser, the label keeps its initial text "not translated" and all breakpoints, which I set in the DBResourceProdivder classes are never hit, hence the code is never called.
My question is: Why is it never called?
Additional Information: There are 2 labels present, which have the corresponding resourceKeys in the database
<asp:Label ID="lblHello" runat="server" Text="HelloDefault" meta:resourcekey="lblHello" />
<asp:Label ID="lblGoodbye" runat="server" Text="GoodByeDefault" meta:resourcekey="lblGoodbye" />
ResourceType | CultureCode | ResourceKey | ResourceValue
---------------------------------------------------------------
Default.aspx | de-DE |lblHello.Text | Hallo (de-DE)
Default.aspx | en-US |lblHello.Text | Hello (en-US)
Default.aspx | fr-FR |lblHello.Text | Bonjour (fr-FR)
Default.aspx | en |lblHello.Text | Hello (en)
Default.aspx | de-DE |lblGoodbye.Text | Tschüss (de-DE)
Default.aspx | en-US |lblGoodbye.Text | good bye(en-US)
For some reason (I don't know why) lblHello gets localized correctly, while lblGoodbye does not.
I could also write <asp:label id="lblhello" runat="server" text="<%$ resources: default.aspx, lblhello.text %>" />
. This does work too.
In the GetObject method, there is a line for the debugger:
Debug.WriteLine(String.Format(CultureInfo.InvariantCulture, "DBResourceProvider.GetObject({0}, {1}) - type:{2}", resourceKey, culture, this.m_classKey));
If Default.aspx is called by the client this line appears in the output window:
DBResourceProvider.GetObject(lblhello.Text, ) - type:Default.aspx
But there is no call to the DBResourceProvider for lblGoodbye, which is totally weird. As if the new label was not registered, or the meta tag is not been read.
UPDATE: I've read some more into the topic. Apparently, the resources get cached and do not get released until the app shuts down. In my book, this means the AppDomain gets recycled. Every resource I've read offers the same ways to reload the AppDomain:
Bin
folder (add a txt file f.e.)system.web
or trust
sectionHttpRuntime.UnloadAppDomain()
I've tried everything, but with no way I can force the environment to dump every temp file / cached bit it has to reload the resources and display them correctly. My problem is not the Resourceprovider not getting called, but the resources being cached infinitly and not being refreshed corectly.
You problem likely has to do with the two phases involved when using implicit local resources. For the page you linked to:
During the page-parsing step, providers are used to retrieve all local resources for a page; explicit expressions are validated; and, during compilation, code is also generated for the page. For local resources, the resource reader is used to generate code for implicit expressions. Explicit expressions for local and global resources are validated individually with a call to GetObject() on the appropriate provider.
At run time, the parser-generated code triggers calls to GetObject() to retrieve local and global resources as the page is initialized.
As part of the parsing phase, the DBResourceProviderFactory.CreateLocalResourceProvider
method is called, which in turn causes DBResourceProvider
constructor to be called. After that the framework 'calls' the ResourceReader
property on the DBResourceProvider
instance which in turn causes the following line to execute:
ListDictionary resourceDictionary = this.m_dalc.GetResourcesByCulture(CultureInfo.InvariantCulture);
This, it seems, is then used by the framework to somehow build a dictionary (or something) of resource keys.
Later on in the page cycle, the call to DBResourceProvider.GetObject
is skipped for keys that were not added to the dictionary.
But if you check the implementation of the StringResourcesDALC
class, it will actually replace the InvariantCulture
with an invariant English culture in the GetResourcesByCulture
method.
This means that you must have a row in your database table with en
as the CultureCode
if you want this to work.
In your sample data, you have this row:
Default.aspx | en |lblHello.Text | Hello (en)
but you don't have:
Default.aspx | en |lblGoodbye.Text | Goodbye (en)
So to fix the issue, add that line. Then for good measure, rebuild the solution and test what happens.