I'm writing an MVC3 application that reads in a bunch of monetary data from a database. The issue I have is that these amounts are all in different currencies.
If I set the type of a field like this:
[DataType(DataType.Currency)]
public Amount{ get; set;}
I get the decimal places and a currency symbol, which looks nice, but it defaults to the user's local currency. A US user sees $423.29
whereas a GB user sees £423.29
. I can override the currency by using a <globalization culture="{something}">
in the Web.config, but this sets all currency fields globally.
What would be the easiest way of marking up a field so that it renders with the correct decimal places and currency symbol?
In an ideal world, I'd like to be able to do something like this (for USD):
[DataType(DataType.Currency, culture="en-us")]
public Amount{ get; set; }
and have that always render as $439.38
, but that's not possible with the built-in annotations.
The way I would do this is to create a custom attribute that extends the DataType
attribute and a custom html helper. It's not necessarily the easiest way of doing it but it would save time in the future.
EDIT
Incorporated CultureInfo.CreateSpecificCulture(cultureName)
instead of a switch
Custom Attribute
public class CurrencyDisplayAttribute : DataTypeAttribute
{
public string Culture { get; set; }
public CurrencyDisplayAttribute(string culture)
: base(DataType.Currency)
{
Culture = culture;
}
}
Html Helper
public static class Helpers
{
public static IHtmlString CurrencyDisplayFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression)
{
double value = double.Parse(expression.Compile().Invoke(helper.ViewData.Model).ToString());
var metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
var prop = typeof (TModel).GetProperty(metadata.PropertyName);
var attribute = prop.GetCustomAttribute(typeof (CurrencyDisplayAttribute)) as CurrencyDisplayAttribute;
// this should be whatever html element you want to create
TagBuilder tagBuilder = new TagBuilder("span");
tagBuilder.SetInnerText(value.ToString("c", CultureInfo.CreateSpecificCulture(attribute.Culture));
return MvcHtmlString.Create(tagBuilder.ToString());
}
}
You can use the attribute in your model
[CurrencyDisplay("en-us")]
public double Amount { get; set; }
Then in your view you can use the helper by
@Html.CurrencyDisplayFor(x => x.Amount);
Provided your model is passed in correctly.
Obviously, you'd need to do error checking and so on.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With