Saturday, October 01, 2005

Handling currency formatting in ASP.Net

Someone asked on the aus-dotnet list (http://www.stillhq.com/aus-dotnet/archives2/msg09751.html ) how to handle formatting of currency information in an ASP.Net application. This is something that's commonly misunderstood, so I thought I'd put something together to point people at in future.

By default all of the ASP.Net formatting takes the culture setup for the service user (ASPNET or Network Service under IIS6) - typically en-US :-(. You can explicitly override this in your web.config (or machine.config), and this is great because it centralises the configuration of how you application is going to localise. All you've got to do in the application is date.ToString("d") or decimal.ToString("C") and you're away...

... if a single deployment of your application only serves a market with a single locale, and uses that locale's currency.

However if your app always works in a set currency - say AUD - then you need to hard-code into your application so that currencies don't appear with the wrong currency symbol (that is to say, appear with the default currency symbol for the deployment local, rather than a dollar sign). The simplest way to achieve this is to override just the currency format on the thread's culture. I do this by cloning the current culture, overwriting the bits I want to and then assigning it to the thread. That way I'm not locking the app into using other settings (eg date format) purely to display a given currency symbol.

Additionally, if a single deployment of your application caters to users in multiple locales, you should probably set the culture on each thread to the end-user's culture, rather than using a single server / app.config setting. You can query the browser's settings using Request.UserLanguages. You still need to override the currency symbol as suggested above, because your app uses a single currency.

All fairly straightforward. However if a single deployment of your application has to deal in multiple currencies, then you've got a bit more work to do. You can't ever just perform a decimal.ToString("C"), because ever time an amount is formatted it has to use the currency symbol and decimal precision that's relevant for that amount's currency. The usual object-based approach is to make sure all your amounts are some kind of Money type that combines a decimal with a currency type, and implements IFormattable to format the amount appropriately. I normally provide a Registry-style lookup singleton that converts currency codes into CultureInfo's - this can be used both in the .ToString() of a Money type and when providing custom formatting during the binding cycle for a datagrid.

I make the destinction between your application and a given deployment of it because for many of these localisation issues, just flicking a setting in web.config's not going to cut it anyway - someone's got to translate the copy, remove all the culturally-specific idioms, vet that images or product names are still unoffensive etc...

Incidentally, working in a WinForms (er... 'SmartClient') environment doesn't absolve you from thinking about these issues, it just makes it easier to detect your user's settings. You still might not want to use them as is.

PS: Don't mix up Thread.CurrentCulture (sets up the formatting information), and Thread.CurrentUICulture (for localized resources (strings etc...))

2 comments:

Anonymous said...

http://msconline.maconstate.edu/tutorials/ASPNET2/ASPNET07/aspnet07-01.aspx

Anonymous said...

you can use this

Bind("OrpCost","{0,c0}")

will work

Popular Posts