64

I have this line in my razor view.

@String.Format("{0:C}", @price)

I want it to display a dollar sign in front of the price but instead it display a pound sign.

How do I achieve this?

Newton Yuan
  • 148
  • 1
  • 17
Sachin Kainth
  • 45,256
  • 81
  • 201
  • 304
  • 5
    When you say "pound sign" what exactly do you mean? # or £? – Jon Skeet May 02 '12 at 15:13
  • 7
    Hi Jon, big fan of yours. Being British I do mean £. – Sachin Kainth May 02 '12 at 15:16
  • 2
    @JonSkeet Very interesting, never seen # in reference to "pound sign", but a quick google brings up some good info. – Tim B James May 02 '12 at 15:18
  • 1
    @TimBJames - that's what we call it in the states (although I do hear it referred to as 'hash sign' more often nowadays like the British have always done). – William May 10 '14 at 19:45
  • 1
    @JonSkeet - you may remember from our time at TDWTF that it's also called Octothorp (at least in italics). There was a commenter there named C-Octothorp (from the music symbol). – hoodaticus May 03 '16 at 16:19

8 Answers8

92

I strongly suspect the problem is simply that the current culture of the thread handling the request isn't set appropriately.

You can either set it for the whole request, or specify the culture while formatting. Either way, I would suggest not use string.Format with a composite format unless you really have more than one thing to format (or a wider message). Instead, I'd use:

@price.ToString("C", culture)

It just makes it somewhat simpler.

EDIT: Given your comment, it sounds like you may well want to use a UK culture regardless of the culture of the user. So again, either set the UK culture as the thread culture for the whole request, or possibly introduce your own helper class with a "constant":

public static class Cultures
{
    public static readonly CultureInfo UnitedKingdom = 
        CultureInfo.GetCultureInfo("en-GB");
}

Then:

@price.ToString("C", Cultures.UnitedKingdom)

In my experience, having a "named" set of cultures like this makes the code using it considerably simpler to read, and you don't need to get the string right in multiple places.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • 3
    Hardcoding a CultureInfo in order to get a certain currency symbol is throwing out the baby with the bath water. Also there is no guarantee that a certain CultureInfo will keep the currency symbol you expect it to have. But the main issue is that you introduce a globalization bug by losing the adequate culture formatting (decimal symbol, positioning of the currency symbol). Please see my answer for an explanation. – Clafou May 03 '12 at 09:39
  • 3
    @Clafou: Sometimes it's throwing the baby out with the bathwater; sometimes it's the right thing to do. I agree it's a complex topic though. It's a pain (IMO) that there is a "currency format" which includes the currency, rather than there being a "Money" type with both amount and currency, which could then be formatted according to local culture. – Jon Skeet May 03 '12 at 11:06
  • I agree, it's awkward to say the least (I think currency formatting is the globalization topic that confuses the most people). Luckily there are 3rd-party libraries such as [NMoneys](http://code.google.com/p/nmoneys/) that do this well. – Clafou May 03 '12 at 12:27
  • It might be an extremely stupid question, but why does this "price" identifier starts with @? – Max Yankov Dec 26 '13 at 10:45
  • 1
    @golergka: Just because it does in the question. I don't know enough about razor to say for sure whether it's needed or not - it wouldn't be within normal C#. – Jon Skeet Dec 26 '13 at 12:33
  • 1
    @golergka: it's simply razor syntax telling us price is a c# variable, and not html markup. – MissRaphie Dec 27 '13 at 01:18
  • My understanding is that the system already maintains a cache of read-only `CultureInfo` objects, so it's preferable to use it: `public static readonly CultureInfo UnitedKingdom = CultureInfo.GetCultureInfo("en-GB");`. In any case, see Clafou's answer, which I also think is best. – tne Oct 08 '14 at 10:05
  • @tne: Have changed the code sample. Unfortunately, the OP never came back to say what their real scenario was. If it's "always treat the user as if they're in the UK" then my answer is appropriate; if it's "display the price in pounds, but in the culture of the user" then Clafou's answer is appropriate. – Jon Skeet Oct 08 '14 at 10:10
47

As others have said, you can achieve this through an IFormatProvider. But bear in mind that currency formatting goes well beyond the currency symbol.

For example a correctly-formatted price in the US may be "$ 12.50" but in France this would be written "12,50 $" (the decimal point is different as is the position of the currency symbol). You don't want to lose this culture-appropriate formatting just for the sake of changing the currency symbol.

The good news is that you don't have to, as this code demonstrates:

var cultureInfo = Thread.CurrentThread.CurrentCulture;   // You can also hardcode the culture, e.g. var cultureInfo = new CultureInfo("fr-FR"), but then you lose culture-specific formatting such as decimal point (. or ,) or the position of the currency symbol (before or after)
var numberFormatInfo = (NumberFormatInfo)cultureInfo.NumberFormat.Clone();
numberFormatInfo.CurrencySymbol = "€"; // Replace with "$" or "£" or whatever you need

var price = 12.3m;
var formattedPrice = price.ToString("C", numberFormatInfo); // Output: "€ 12.30" if the CurrentCulture is "en-US", "12,30 €" if the CurrentCulture is "fr-FR".
Charles Lambert
  • 5,042
  • 26
  • 47
Clafou
  • 15,250
  • 7
  • 58
  • 89
  • 3
    In 99% of the cases, this is the only correct answer. Jon Skeet may have more fans, and he's right in saying that the `CultureInfo`/`NumberFormatInfo` model is not optimal (to say the least), but in this case his answer simply isn't the most appropriate. By the way, I initially created a new `CultureInfo` object based on the current culture only to change the currency symbol (so you can do this also), but cloning just the `NumberFormatInfo` object is definitely better. – tne Oct 08 '14 at 09:10
  • I've used your solution for Persian currency and it worked and my numbers are properly arranged. Thanks – Mehdi Nourollah May 07 '19 at 05:42
  • This is the right solution in every aspect. The format of output look natural to the user and the currency symbol also correct. – UltimaWeapon Jan 24 '22 at 19:32
31

You need to provide an IFormatProvider:

@String.Format(new CultureInfo("en-US"), "{0:C}", @price)
dtb
  • 213,145
  • 36
  • 401
  • 431
13

Personally i'm against using culture specific code, i suggest doing:

@String.Format(CultureInfo.CurrentCulture, "{0:C}", @price)

and in your web.config do:

<system.web>
    <globalization culture="en-GB" uiCulture="en-US" />
</system.web>

Additional info: https://msdn.microsoft.com/en-us/library/syy068tk(v=vs.90).aspx

Sam Jones
  • 4,443
  • 2
  • 40
  • 45
5
decimal value = 0.00M;
value = Convert.ToDecimal(12345.12345);
Console.WriteLine(".ToString(\"C\") Formates With Currency $ Sign");
Console.WriteLine(value.ToString("C"));
//OutPut : $12345.12
Console.WriteLine(value.ToString("C1"));
//OutPut : $12345.1
Console.WriteLine(value.ToString("C2"));
//OutPut : $12345.12
Console.WriteLine(value.ToString("C3"));
//OutPut : $12345.123
Console.WriteLine(value.ToString("C4"));
//OutPut : $12345.1234
Console.WriteLine(value.ToString("C5"));
//OutPut : $12345.12345
Console.WriteLine(value.ToString("C6"));
//OutPut : $12345.123450
Console.WriteLine();
Console.WriteLine(".ToString(\"F\") Formates With out Currency Sign");
Console.WriteLine(value.ToString("F"));
//OutPut : 12345.12
Console.WriteLine(value.ToString("F1"));
//OutPut : 12345.1
Console.WriteLine(value.ToString("F2"));
//OutPut : 12345.12
Console.WriteLine(value.ToString("F3"));
//OutPut : 12345.123
Console.WriteLine(value.ToString("F4"));
//OutPut : 12345.1234
Console.WriteLine(value.ToString("F5"));
//OutPut : 12345.12345
Console.WriteLine(value.ToString("F6"));
//OutPut : 12345.123450
Console.Read();

Output console screen:

Pang
  • 9,564
  • 146
  • 81
  • 122
Bhanu Pratap
  • 1,635
  • 17
  • 17
  • 1
    I would suggest reducing the answer to the question asked. While this might be right, only about 10% of the answer has to do anything with the question. In addition I also think that the poster uses the right format already but has some locale-issues. So this answer is not very helpful – Ole Albers Jul 25 '16 at 12:21
4

For razor you can use: culture, value

@String.Format(new CultureInfo("sv-SE"), @Model.value)
Luke Alderton
  • 3,198
  • 1
  • 23
  • 34
1

Use this it works and so simple :

  var price=22.5m;
  Console.WriteLine(
     "the price: {0}",price.ToString("C", new System.Globalization.CultureInfo("en-US")));
Coder992
  • 248
  • 3
  • 11
1

For those using the C# 6.0 string interpolation syntax: e.g: $"The price is {price:C}", the documentation suggests a few ways of applying different a CultureInfo.

I've adapted the examples to use currency:

decimal price = 12345.67M;
FormattableString message = $"The price is {price:C}";

System.Globalization.CultureInfo.CurrentCulture = System.Globalization.CultureInfo.GetCultureInfo("nl-NL");
string messageInCurrentCulture = message.ToString();

var specificCulture = System.Globalization.CultureInfo.GetCultureInfo("en-IN");
string messageInSpecificCulture = message.ToString(specificCulture);

string messageInInvariantCulture = FormattableString.Invariant(message);

Console.WriteLine($"{System.Globalization.CultureInfo.CurrentCulture,-10} {messageInCurrentCulture}");
Console.WriteLine($"{specificCulture,-10} {messageInSpecificCulture}");
Console.WriteLine($"{"Invariant",-10} {messageInInvariantCulture}");
// Expected output is:
// nl-NL      The price is € 12.345,67
// en-IN      The price is ₹ 12,345.67
// Invariant  The price is ¤12,345.67
Andrew
  • 12,991
  • 15
  • 55
  • 85