I have multiple projects that need to share resource files (.resx) Suggestions have been made to move resource files to a separate assembly and have web projects reference it. Is there an example of how to do this?
Do I create a new Class Library project and move App_GlobalResource folder inside of that? I don't think that will work because code classes that are generated for resource files are marked as 'internal' which means that they can not be accessed outside of this assembly.
In the properties window of Visual Studio, you should be able to set the access modifier of the resource file to public. You won't, however, be able to access the resources in aspx files using the normal <%$ Resources:... %>
syntax, since it does not support resources in referenced assemblies. I had the same problem and solved it by implementing a custom ExpressionBuilder, but I don't have access to my source code at the moment. If it's still needed then, I can look up the code tonight.
EDIT: OK, here's how I solved that problem:
Step 1: Move the resx files into the class library. They do not need to be in a specific folder. In the visual designer of the resx file, set the "Access Modifier" (upper right-hand corner) to "Public"
You should now be able to
reference the resources in C#/VB code (in the library as well as in the web project), e.g., Dim myMessage As String = [Namespace.]Resources.NameOfResx.NameOfResource
reference the resource as inline code in aspx pages, e.g., <h1><%= [Namespace.]Resources.NameOfResx.MyTitle %></h1>
.
What won't work at this point is to use Resources expression, e.g., <asp:Button runat="server" Text="<%$ Resources:NameOfResx,MyButtonText %>" />
. Unfortunately, you cannot simply replace this with inline code, since it's inside the property of a server side control.
Step 2: Let's make a custom ExpressionBuilder in our library, which interprets arbitrary code expressions. Fortunately, we can let the powerful classes of the .net Framework do all the work for us:
Imports System.Web.Compilation
Imports System.Resources
Imports System.CodeDom
<ExpressionPrefix("Code")> _
Public Class CodeExpressionBuilder
Inherits ExpressionBuilder
Public Overrides Function GetCodeExpression(ByVal entry As System.Web.UI.BoundPropertyEntry, ByVal parsedData As Object, ByVal context As System.Web.Compilation.ExpressionBuilderContext) As System.CodeDom.CodeExpression
Return New CodeSnippetExpression(entry.Expression)
End Function
End Class
Then we need to register this ExpressionBuilder in the web.config:
<system.web>
...
<compilation ...>
<expressionBuilders>
<add expressionPrefix="Code" type="NamespaceOfYourLibrary.CodeExpressionBuilder" />
</expressionBuilders>
</compilation>
</system.web>
Now you should be able to do the following:
<asp:Button runat="server" Text="<%$ Code:[Namespace.]Resources.NameOfResx.MyButtonText %>" />
Credit: I got the idea for the CodeExpressionBuilder from the Infinites Loop blog. If you're more into C# than VB, you can have a look at the code examples there.