Contact   •   Products   •   Search

Rick Strahl's Web Log

Wind, waves, code and everything in between...
ASP.NET • C# • HTML5 • JavaScript • AngularJs

Updated ASP.NET Database Resource Provider


A few years back I wrote an article on creating a custom ASP.NET Localization Resource Provider that described how to create a custom ASP.NET ResourceProvider and ResourceManger that get resources from a database. It’s an older article but it’s been one of the more popular ones on this site, and the resource provider described has been picked up (based on feedback received) by quite a good number of developers.

In the last month I put a bit of effort into cleaning up the original provider and the result is a more formal Westwind.Globalization library that I hope more people will check out and take advantage of.

In the process I added better documentation, set up a new home page, created a GitHub project for the source code (moved from the old Westwind Web Toolkit project) and created a NuGet package that makes it easy to integrate the provider into your own applications.

I also created a new Getting Started video:

that takes you through installing and setting up the provider, adding some resources using the resource editor, and then demonstrate a variety of ways that you can use the localized resources. It’s a combo Getting Started and basic features overview – check it out if you have a few minutes to spare.

Why now?

The provider’s been around for a number of years, and it’s been updated and bug fixes have been made based on user submissions and bug reports. But the project has been off the beaten track. There was the article with the download, and the library was embedded as part of the Westwind West Wind Toolkit that’s now been broken up into its smaller component parts as separate projects. Westwind.Globalization was one of the last small projects left mainly because some work was required to clean up some of the samples and go the final mile to create a redistributable version of the online Web Resource Editor.

Additionally, in the last year or so I’ve been involved in several apps that have made fairly heavy use of this provider and as part of those project I was able to add a number of enhancements that came up in the process. I found some time to smooth out some of the rough edges in the provider and front end integration pieces.

Among the enhancements:

  • Better support for resources in MVC/WebAPI – or any .NET app really (console, service, desktop)
    (you can use DbRest.T() anywhere, or generate strongly typed resources that work either with ResX or Db resources)
  • Improved standard ResourceManger implementation for any .NET application
  • New DbRes helper class that allows direct access to resources bypassing ResourceProviders
    (ie. no resource provider config required in ASP.NET)
  • Improved strongly typed resource generation
  • Much improved Db Resource –> Resx export capabilities
  • Updated JavaScript resource generation handler
  • Update online Web Resource Editor
  • NuGet Package

Database Resources?

A lot of times when I mention Database resources for localization I get: “Isn’t that really slow?” The answer to that is – nope, not really. Yes, resources *are* loaded from a database, but they are loaded only once per ResourceSet per locale. This means once resources are loaded and in memory, they stay there – the process is identical to using Resx resources except that the initial read of a resource set is done from a database rather than from assembly ResX resources. So while there’s a small db hit for first time resource load on each ResourceSet, over the lifetime of an ASP.NET/.NET application there’s not a significant performance difference.

Additionally this library has the ability to import and export resources from Resx resources, so you can pull in existing resources, edit them in the database while your application is in development, then when complete export the resources back out to Resx and use them that way. You can even generate strongly typed resources that work with either database or Resx resources simply by switching the ASP.NET ResourceProvider. However, I’ve found although a number of clients had the intention of doing this, they actually preferred running with the Db resources because it allowed them to change the resources on the fly in the application as needed, without having to recompile the app.

Database resources are incredibly useful in localized applications as it’s much easier to modify resources interactively. This resource provider includes an interactive ASP.NET Web based resource editor that allows editing and updating of resources in a running application. The ability to manage resources interactively and update them however, adds a ton of flexibility which is a big sticking point in many a localized application I’ve worked on in the past.

Additionally if you use this provider, it has the optional capability to automatically add new resource keys to the database as keys are accessed. So if you use a resource that doesn’t exist, the value of the key is used, but also the key can automatically be added to the database. You can then lookup all missing ‘values’ and localize those.

DbResource Provider Support

The DbResourceProvider works with standard ASP.NET localization schemes so everything that works with ResX resources also works with the database provider. The DbResourceManager also works in any .NET application including services, console apps and even desktop applications.

All of the following are supported in ASP.NET:

  • DbRes Helper (part of Westwind.Globalization)
    Say Hello: @DbRes.T("HelloWorld", "Resources")
  • HttpContext.GetGlobalResourceObject()
    Say Hello: @HttpContext.GetGlobalResourceObject("Resources", "HelloWorld")
  • Page.GetLocalResourceObject() (WebForms only)
    Say Hello: <%= GetLocalResourceObject("lblHelloWorldLabel.Text") %>
  • WebForms Control meta:resource tags (WebForms only)
    <asp:Label ID="lblHelloLabel" runat="server" meta:resourcekey="lblHelloWorldLabel"></asp:Label>
  • WebForms Control Resource expressions (WebForms only)
    <asp:Label ID="Label1" runat="server" Text="<%$ Resources:Resources,HelloWorld %>"></asp:Label>
  • You can also generate strongly typed resources (once generated)
    Say Hello: @Resources.Helloworld

Alternate Localization Scheme

ASP.NET localization is based on ResourceID localization. The idea is that you have a resource ID value and that value is then matched in a ResX file for each of the locales you want to localize for. Typically using this approach you create keys that are more like Ids, rather than values, which in a lot of ways can be limiting.

More and more customers I’ve worked with though prefer using direct translation – ie. rather than embedding resource Ids, they want to embed actual resource string values in the default language and then translate those values later.

For example imagine I have a resource embedded like this in an MVC application:

<legend>@DbRes.T("Your Details","Account")</legend>
<label>@DbRes.T("First Name")</label>
@Html.TextBoxFor(mdl => mdl.User.FirstName, 
new { @class = "input-block-level", placeholder = DbRes.T("First Name") }) <label>@DbRes.T("Last Name","Account")</label> @Html.TextBoxFor(mdl => mdl.User.LastName,
new { @class = "input-block-level", placeholder = DbRes.T("Last Name") })

For example Last Name is a Resource Id here, which is the default text used. Even if there’s no resource named "Last Name" in the resource set, Last Name will be returned. Later when you translate to other languages those values can then be added and the translated values will be returned instead.

DbRes.T(resourceid,resourceSet,localeId) for translate is a small helper method directly accesses the Db Resource manager to retrieve values and it’s an easy way to use the

Unlike the standard ASP.NET ResourceProvider and ResourceManager, DbRes.T() and also the ASP.NET DbResourceProvider and DbResourceManager all automatically return the resource key if the resource Id was not found, so that when there’s no match at the very least you get the resource key value, rather than an empty string which sucks! If you’ve ever loaded an application with missing ResX resources you know what I’m talking about – it’s no fun to have empty labels and buttons and other UI controls without any content :-) This ResourceProvider will always return something…

Using actual translated default values for ResourceIds makes it easy to get default content into a page.

Further, If I add

addMissingResources="true" 

to the provider configuration resources are automatically added if they are not found. This adds resources in the Resource Editor for easy later translation simply by running the app rather than having to manually add the resources.

This works surprisingly well as resources are added to the application as you run it and you access the actual values on pages.

There is a caveat here however, if you change a resource string in your markup you potentially break the link to your resources in the database. So you have to be aware to either leave the original resource key intact and add an actual default text value, or you can rename the resource name in the Web editor which is actually very easy (advantage database :-)).

Although I was resistant to work with this approach initially I’ve come to appreciate how easy it is to work with this setup. You get default resources always, and with keys added automatically you can easily localize and add new language later. The database manager also includes a method to cleanup resources that have entries with null values and no localization, so when you’re done localizing you can clear out any clutter in the db of resource values that don’t have any actual translated data.

Anyway – it’s something to consider when setting up a new localization project.

Check it out

If you are doing localization in your application and you’re looking to do it a little more dynamically then what you can do with Resx, check out the database resource provider described here. It’s easy to get started and it provides a ton of flexibility to get resources added easily interactively or under program control.

Resources

Make Donation
Posted in ASP.NET  Localization  


Feedback for this Post

 
# re: Updated ASP.NET Database Resource Provider
by Doug Dodge April 07, 2014 @ 8:40pm
Rick,

This is pure gold. I don't have time to fool around with it but have forwarded a link to a local fellow who's big into internationalization by the name of Adam Wooten. Hopefully this will drive some work and traffic your way.
# re: Updated ASP.NET Database Resource Provider
by Bill Poiter April 10, 2014 @ 9:52pm
Rick - this looks really promising. We've built our own implementation that's somewhat similar but we didn't take the time to put in all the embellishments that I see in this library. The Resource Editor and Resource Handler to serve JavaScript resources are things we didn't even consider. Will be checking this out in the next couple of days. Cheers.
# re: Updated ASP.NET Database Resource Provider
by James Mallard April 14, 2014 @ 9:43pm
Nice work Rick! We're just starting to add localization to an existing app and this looks like it will make life a lot easier.

FWIW, the resource editor is a great idea, but it could need a little polishing. There are a few things that feel inconsistent - I think I might take a stab at cleaning those up on a fork.

Keep up the good work, man and thanks for making this available.
# re: Updated ASP.NET Database Resource Provider
by Rick Strahl April 14, 2014 @ 9:47pm
@James - thanks for the kind words.

Re: Resource Editor - yes I know. The code base is pretty old. I cleaned it up a bit recently for better standalone operation and as a drop in for existing projects when I created the NuGet package. It works and is functional but it could definitely be done better, I agree. I've started a re-write a couple of weeks back on a local branch here - removing much of the WebForms related stuff reducing one of the dependencies and greatly cleaning up the WebForms based HTML to just plain HTML. But it'll take some time to hook up all the functionality again so it might take a bit. But it's coming...
# re: Updated ASP.NET Database Resource Provider
by Billl Yoergensen April 14, 2014 @ 10:31pm
Does the JavaScript resource handler work without having to use the database provider? This looks really useful, but we have to use Resx resources and it would be nice to serve our server resources to JavaScript.
# re: Updated ASP.NET Database Resource Provider
by Rick Strahl April 15, 2014 @ 8:58am
@Bill - The Resource handler works with either the DbResource or Resx providers. There's a flag (on the helper method or the actual URL sent to retrieve the resources) that can be set to determine how the resources are retrieved and served.
# Localized strings to Html
by Developer June 30, 2014 @ 4:59am
Hi Rick, thanks for this great direction, whats your thoughts on applying the localized strings to HTML using javascript plugin or using some generic handler?

I mean Dres.T version in javascript which will detect all applicable controls and replace in one shot.
# re: Updated ASP.NET Database Resource Provider
by Rick Strahl June 30, 2014 @ 11:28am
@Developer - for the client side I tend to generate strongly typed resources (part of the globalization toolkit)

https://github.com/RickStrahl/Westwind.Globalization#javascript-resource-handler

and just use those directly using object names. This works as long as the resource IDs are safe JavaScript names.

var hw = Resources.HelloWorld;
 
// non type-safe name
var hw2 = Resources["Hello World 2"];


I also tend to create a DbRes.T() function in my apps that matches the behavior of the server class - where you can specify the name of the resource and resources set. This has been valuable when server side MVC style localization expressions to the client side

// server expression
Text: @DbRes.T("HelloWorld","Resources")
 
// client expression
Text: {{DbRes.T("HelloWorld","Resources")


The client side version simply exposes a global object/function that looks at the resources and objects that I've attached to a fixed location.

As to auto-assigning stuff - not a fan of that myself. There are too many things you need to consider such as naming coinventions, properties/attributes that values get assigned to etc. plus it won't really work if you use dynamic controls with things like Angular. I think it's simply better to be explicit about resource assignment.
# re: Updated ASP.NET Database Resource Provider
by john October 01, 2014 @ 12:58pm
Would it be possible to use a MySQL database?
# re: Updated ASP.NET Database Resource Provider
by Rick Strahl October 01, 2014 @ 5:33pm
The provider was designed for SQL Server, but it'd be fairly easy to modify the db access code to work with MySql. The SQL is very standard so if you provide the MySql provider it might just work.

Next update will have better provider support (Mongo and other SQL dialects) but for now you'd have to customize the DB access code.
# re: Updated ASP.NET Database Resource Provider
by Mike October 22, 2014 @ 3:08am
Could you please le us know where to start in order to change to a mySQL database? Thanks
 


West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2014