FormattedResourceExpressionBuilder: An enhanced resourcing solution for ASP.NET

So we’re in the process of migrating our ASP.NET 1.1 application to 2.0. In 1.1 there was no intrinsic solution to handling resources baked into the ASP.NET runtime. With the advent of 2.0, we now how ResourceExpressionBuilder which allows us to very easily integrate resources into our ASP.NET “code-in-front” using a new expression syntax that looks like this:

<asp:Literal ID=”test” runat=”server” Text=”<%$ Resources: Test %> />

The new <%$ … %> syntax indicates to the ASP.NET code-in-front compiler that this should be evaluated as an expression and then, via a pluggable expression architecture, specific code is emitted by various implementations to assign the value to the property. In the case of the ResourceExpressionBuilder, it pulls the resource from a .resx file in App_LocalResources or App_GlobalResources. I’m not going to go 100% into the details of how to use these features because they’re very well documented right here on MSDN.

What I do want to talk about here is a glaring omission of functionality that I wish I had realized sooner and reported during the beta. That functionality is the ability to do replacements on a resource string. It seems to me like this would be a very common scenario for most people out there, at least it is for me, so I’m surprised it was overlooked.

Long story short, I decided to slap together my own implementation of an ExpressionBuilder that layers on top of the ResourceExpressionBuilder and basically does a String::Format on the resource string using whatever arguments you like. Since I wanted to provide a familiar syntax to the way Resource expressions work, I kept the same [ClassKey, ]ResourceKey syntax and use a semi-color to separate literal expressions to be passed as parameters to the String::Format call. Let’s take a look at how this might actually work. First you’ll need to make an entry in your web.config to enable the expression for your web application:

<compilation>
 
<expressionBuilders>
   
<!– add our custom expression type with a custom prefix –>
    <add expressionPrefix=FormattedResource>” type=Mimeo.Components.Web.Compilation. FormattedResourceExpressionBuilder, Mimeo.Web/>
 
</expressionBuilders>
</compilation>

Next let’s see what it might actually look in an ASPX page:

<%— page level resource —%>
<asp:Literal ID=”myFormattedLiteral” runat=”server” Text=’<%$ FormattedResource: Test; “123”, base.testField %> />

<%— global resource —%>
<asp:Literal ID=”myFormattedGlobalLiteral” runat=”server” Text=’<%$ FormattedResource: GlobalMessages,Test; “XYZ”, base.testField %> />

As you can see, it supports all literal expressions valid in a language (in this case I use C#). You can specify string or numeric literals, but most importantly you can specify variable or method calls. This allows you to do some processing in the code-behind and get replacement values from there. In the above example I just use a protected field off of the base Page class, but basically any C# expression will work. As mentioned earlier, the format replacements are separated from the standard Resource expression by a semi-color and from each other by comas.

Implementation wise I started out initially inheriting from ResourceExpressionBuilder, but decided to go with containment instead since I could theoretically break my depenedency on ResourceExpressionBuilder if I wanted to by calling other APIs directly. The CodeDom work was particularly interesting for me as I’ve never used it for anything “real world” before. I must say that the expression model for ASP.NET 2.0 opens up a world of opportunities to developers and I’ll be looking for more ways to leverage it as we convert our existing architecture over.

If you’re interested in using this expression class, here it is free of charge and licensing. A link back to me if you blog about it is all I ask. 😉 Please note that I didn’t add any support for the designer yet. When/if I do, I’ll be sure to update everyone.

Leave a Reply