Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to force the currency for an MVC3 field with DataType as DataType.Currency

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.

like image 477
growse Avatar asked Sep 13 '12 14:09

growse


1 Answers

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.

like image 131
simonlchilds Avatar answered Oct 31 '22 23:10

simonlchilds