It has to do with the culture of the thread that is running. If you want to get the string formatted in en-US regardless of the thread then you need to pass in a specific culture to ToString. If its running under a web server and you want to ignore the culture of the requsting browser/client you can also specify a static culture in the web.config.
How to specify culture in ToString
var formatted1 = total.ToString("F02", System.Globalization.CultureInfo.InvariantCulture);
// or
var formatted2 = total.ToString("F02", new System.Globalization.CultureInfo("en-US"));
See Decimal.ToString Method (String,IFormatProvider)
How to configure web.config
<globalization uiCulture="en" culture="en-US" />
See also How to: Set the Culture and UI Culture for ASP.NET Web Page Globalization
Why? decimal is just a value, right?
No, you are converting the decimal to a string and depending on the culture that string representing the decimal might be displayed differently. For example: in the Netherlands a comma is used to separate a whole value from the partial/fractional part of the value and a period (.) is used to segregate groupings like thousands,millions,billions,trillians etc. In the USA these symbols have the exact opposite meaning.
Detecting the culture of the caller is usually a good thing and returning the data formatted based on the callers culture is usually also desired behavior. If not though then see above for 2 ways to ensure that the code can always return a consistent formatted data.