Is it possible to force the currency for an MVC3 f

2019-04-23 16:09发布

问题:

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.

回答1:

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.



回答2:

Make string the amount

public string Amount{ get; set;}

Create a method that converts to string with currency exact

private string LocalizedAmount(decimal theAmount, string cultureName)
{
      return theAmount.ToString("c",CultureInfo.CreateSpecificCulture(cultureName));
}

If you are stored in your database two fields or columns one for value and one for culture.

And in the Repository or the controller:

Amount = LocalizedAmount(Convert.ToDecimal(reader[0]),reader[1].ToString());


回答3:

You need to assing the culture:

Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName);
Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName);

Inside this Controller overrided methods:

 protected override void OnActionExecuted(ActionExecutedContext filterContext)
 protected override void ExecuteCore()

Read the whole technique in this NadeemAfana's blog ASP.NET MVC 3 Internationalization