This small article shows how to extend the ASP.NET
Label Control, so it reads resource strings from an XML file, which is stored in memory as a Cached
DataSet with cache-dependency to the XML-file. Each web page has its own XML-file where texts are stored.
A control like this might come in handy if you need to translate your web application into other languages, or if the owner of the web site wants to change the “static” texts in the web pages by just editing the XML-files.
The program could easily be extended so the resource texts are read from another source, like a database, Web Service or a resource file, but I wanted to keep this article fairly small and easy, just to show the general idea.
I’ve used this technique in production, but since we use a web farm in production, having the resource strings in files isn’t that convenient, so instead I keep all strings in a database. Its also a good idea to give the web application owner, a nice interface for changing the texts. I might write another article to show you how to do this.
Some of the .NET features used in the sample project:
- Custom controls
The Control is called
TextControl because it handles texts from a resource of strings. Perhaps a name like Text or StringResource is better, but
TextControl will have to do. Feel free to change it :)
The central part of the code is made up from a single custom control, which inherits from, and extends the ASP.NET
Label control. The control also uses a helper class called
XMLResource, which will be explained later.
public class TextControl : System.Web.UI.WebControls.Label
The reason I wanted to inherit from the
Label control instead of the base Control class is that I want to use the rendering functions that are already implemented in the
Label control for different fonts, colors and stuff. I’m lazy ;)
TextControl needs to know what text string it should get from its resource of texts, so therefore I added a new property to it called
Key. I might as well have re-used the inherited
Text property that is already in there, but I had better use for that
Text property (shown later).
private string key;
Description("ID/Key of the resource text to get")]
public string Key
key = value;
There really isn’t much to say about the code snippet above. Its important to have the right attributes or the property might not show up in the property dialog in VisualStudio.NET.
The final (and interesting part) of the control is the code that renders the output in both run-time and design-time. To do this you must override the
Render() method of the
Label class. When the ASPX page renders content, the page calls this
Render() method for each control on the page.
protected override void Render(HtmlTextWriter output)
Text = new XMLResource().GetValueFromKey(Key, Text);
String tmpText = Text;
Text = "[" + Text + "]";
Text = tmpText;
As you can see in the code above, I’m using a
catch block to handle errors, that might happen when we’re getting the text from the resource. I’m getting the texts from an XML-file with the same name as the ASPX file (as described in the introduction), so if the
TextControl sits in an ASPX page called Default.aspx, the resource XML file for that page is called Default.xml and located in the same directory as the ASPX page.
To get the name of the ASPX file, I use the
CurrentExecutionFilePath property of the
Request object. The
Request object is accessed via the current
HttpContext, which isn’t available at design-time, so therefore I catch the exception thrown and show the default text within square brackets. You might as well prevent the exception in the
XMLResource class (shown below) but this works fine for me.
If the requested string (based on the
Key) isn’t found or if an exception occurs, I show the default text, which I get from the re-used
Text property of the parent
So, how do we get the text from the resource file? All is done in the
XMLResource class, which I’ll try to explain below. The
XMLResource class has two methods; one public to get the requested text string and one private, which get the XML file from a cached
DataSet. First the public method:
public String GetValueFromKey(String key, String defaultValue)
DataSet ds = GetResourceDS();
DataView dv = ds.Tables.DefaultView;
dv.RowFilter = "key = '" + key + "'";
if(dv.Count > 0) return dv["value"].ToString();
else return defaultValue;
It’s pretty simple. Get a
DataSet, which contains all the resource strings for this ASPX page. Then filter out our text string based on the key. If the key isn’t found, the default value is returned.
private DataSet GetResourceDS()
DataSet ds = (DataSet)HttpContext.Current.Cache[HttpContext.Current.
if(ds == null)
ds = new DataSet("resourceStrings");
String fileName = HttpContext.Current.
fileName = fileName.Substring(0, fileName.LastIndexOf("."))
ds, new CacheDependency(HttpContext.Current.
GetResourceDS method is longer, but not too complicated. First it tries to get the
DataSet from the built in .NET
Cache object, which is very cool. As a Cache-key I use the name of the ASPX page. If the
DataSet wasn’t in the
Cache, I create a new
DataSet and read in the content from the XML file, which should have the same name as the ASPX page where the
TextControl is used (as explained earlier).
DataSet should expire whenever someone updates the XML file, right? So, therefore I add a cache-dependency, which points at the XML file. So now, when the file is updated, the
Cache object detects this and removes the cached
DataSet from its memory.
Cache might be even more useful if you decide to put all your texts into one big, single XML file. There is no reason to read that XML file every time a
TextControl is rendered, right?
Using the code
To use the
TextControl from VisualStudio.NET, you need to add the assembly containing the control to the toolbox. Load up VisualStudio.NET and create a new ASP.NET application. Then add a WebForm and bring it up in design view. Now right click in the Toolbox containing all the other built-in server controls and select “Customize Toolbox...” from the popup menu. Now select the tab named “.NET Framework Components” and use the “Browse...” button to find the DLL containing the
TextControl. The sample project has the
TextControl in the MyControls.dll assembly.
VS.NET will automatically find and activate the
TextControl inside the MyControls DLL. You can put the control on any of the different tabs in the Toolbox, but I prefer to have it together with the other server controls.
TextControl is now ready for use on a web page. Create a WebForm called WebForm1.aspx and drag/drop the
TextControl from the Toolbox on it in design view. Select the
TextControl on the ASPX page and look at the property dialog. Change the
Key property to “key1” (for example) and optionally put some text in the
Text property. It should look similar to this in the HTML view:
<form id="Form1" method="post" runat="server">
<cc1:TextControl id="TextControl1" runat="server" Key="key1">
Note that VS.NET automatically added a reference to MyControls in the project view and also added code at the top of the file for registering the custom control:
<%@ Register TagPrefix="cc1" Namespace="MyControls" Assembly="MyControls" %>
The only thing to do now is to create the XML file containing the resource strings. Just add a new XML file called WebForm1.xml in the same directory as your newly created ASPX page. The XML file is pretty simple and looks like this:
string node in the XML file makes up a key/value pair in the resource file.
The web page is ready for testing and should show a plain web page with the text “sampleValue 1” on it. If you change the text “sampleValue 1” in the XML file into something else and reload the page, it should show the new value at once.
XMLResource class can also be used from code behind to get and set texts at run-time. Just call the public method
GetValueFromKey() from the code behind:
Label1.Text = new MyControls.XMLResource().GetValueFromKey("key2",
As I wrote earlier, there are lots of things you could (and should) do with this code to use it in production, but I hope this little article can get some of you into making your own controls, which is very fun and really, really useful. I recommend doing similar controls for Buttons, Hyperlinks and so on, the owner of the web site might want to change the texts of all the submit buttons to SAVE or DO IT...
Some things that I’ve added to this control in a production site:
- XML Schema for validating the XML resource file (never trust a customer to write perfect XML ;)
- Password protected web form for updating the XML texts