views:

114

answers:

4

I need to display a currency in my ASP.NET MVC application but when the currency is 0 I would like it to display "Free" (localized of course!) instead of $0.00.

So when I have something like this...

Decimal priceFree = 0.00;
Decimal priceNotFree = 100.00;

priceFree.ToString("C");
priceNotFree.ToString("C");

The output is "$0.00" "$100.00"

I would like it to be "Free" "$100.00"

I imagine I can use the .ToString(string format, IFormatProvider formatProvider) method to accomplish this but I'm not sure how to go about it. Obvious I want to reuse as much of the NumberFormatInfo as possible and only override it when the input is 0. In that case I can simple return a localized resource that contains my "Free" string.

So how do I do this?

Thanks

+2  A: 

How about an extension method:

public static string FreeString(this decimal dec)
{
   if(dec == 0M)
   {
      return "Free";
   }
   else
   {
      return dec.ToString("C");
   }
}

Then

priceFree.FreeString();
priceNotFree.FreeString();
Robaticus
+4  A: 

I think the easiest way to go would be an extension method:

public static string ToPriceString(this decimal value) 
{
    if (value <= 0m) 
        return "Free"; // Your localized resource
    else 
        return value.ToString("C");
}

If you want to go with the IFormatProvider, there is a good example on MSDN.

driis
I'm not a huge fan of extension methods is my primary reason. But in this case it might be a poor excuse. Simplest solution is often the best and in this case the Extension method is very simple.
Justin
BTW: Any chance you can provide more information about value <= 0m. I'm not super family with the 0m syntax. Thanks!
Justin
Ok... so <a href="http://msdn.microsoft.com/en-us/library/364x0z75(VS.71).aspx">decimal</a> explains the m. I was curious what value <= 0m would return for a negative number. But I guess in this case there is no such thing as a negative price.
Justin
Even though it represents a price, a decimal can be negative. If you used a custom class for currency instead, you could disallow that.
Chris Missal
A: 

Instead of using a custom IFormatProvider and passing it each time, how about this:

 public static class MyFormatter
    {
        public static string ToFreeString(this decimal d)
        {
            return d == 0 ? "Free" : d.ToString("d");
        }
    }
Aliostad
+9  A: 

Use

.ToString("$###.00;;Free")
Vivek
+1, nice. For anyone else who hasn't seen this before: [The ";" Section Separator](http://msdn.microsoft.com/en-us/library/0c899ak8.aspx#SectionSeparator).
adrift
Seems interesting. Can you provide a reference or perhaps describe your answer a bit more? I'm not exactly sure whats going on there with the format string.It doesn't seem very Localization friendly.
Justin
This approach isn't good while localization
Sadegh
Thanks to adrift for the reference. I like the idea but unless you can make it localization friendly I think the extension method is the way to go for this one.
Justin
@Justin: You can localize the format string, just as easily as your "free" string... (or compose it from a localized "Free" string).
Reed Copsey
Hi Reed. I do agree I could localize the rules but that requires knowledge of how other cultures localize their currency. Since this behavior is built into the framework using .ToString("C") I'd favour it. I am a fan of this particular solution its a neat one and great to have in the toolbelt!
Justin