Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.Net Core Multi Currency Application

I am converting an application from ASP.NET MVC to .NET Core where I used to handle currency types for different invoices.

 Thread.CurrentThread.CurrentCulture = CustomCulture.GetCultureInfo(Invoice.Vendor.VendorCurrency);

CustomCulture.GetCultureInfo(string CountryCode) took the vendors currency and created a custom culture with some default formatting and the current currency type.

I have a model which has a currency type where we would pull the country code of the Vendor from the database and use that to set the currency type for the current view.

The same does not work for ASP.Net Core from my understanding as the views run on different threads.

Essentially it is the currency type which will change e.g. $ or R or €.

Any ideas on how to handle this?

like image 392
user2806570 Avatar asked Jun 25 '19 09:06

user2806570


2 Answers

Handling currency in multi-culture environment is bit tricky. There are some valuable suggestions in comments; I will recommend go through them.

The same does not work for ASP.Net Core from my understanding as the views run on different threads.

You are setting culture of current thread only using:

Thread.CurrentThread.CurrentCulture = CustomCulture.GetCultureInfo(Invoice.Vendor.VendorCurrency);

When new thread is forked in your application, you have to set this again for it.

Instead, you can set the culture for any thread by default using DefaultThreadCurrentCulture and DefaultThreadCurrentUICulture (at application startup) as below:

CultureInfo.DefaultThreadCurrentCulture = CustomCulture.GetCultureInfo(Invoice.Vendor.VendorCurrency);
CultureInfo.DefaultThreadCurrentUICulture = CustomCulture.GetCultureInfo(Invoice.Vendor.VendorCurrency);

I generally use following code (at application startup) which handles culture setting:

CultureInfo cultureInfo = CultureInfo.CreateSpecificCulture("MyCultureValue");
//Setup things here for `cultureInfo` like currency in your case....

Thread.CurrentThread.CurrentCulture = cultureInfo;
Thread.CurrentThread.CurrentUICulture = cultureInfo;
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;

Type type = typeof(CultureInfo);
type.InvokeMember("s_userDefaultCulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    cultureInfo,
                    new object[] { cultureInfo });

type.InvokeMember("s_userDefaultUICulture",
                    BindingFlags.SetField | BindingFlags.NonPublic | BindingFlags.Static,
                    null,
                    cultureInfo,
                    new object[] { cultureInfo });

These properties are available in .NET Framework 4.5 onward and .NET Core 1.0 onward.

In the .NET Framework 4 and previous versions, by default, the culture of all threads is set to the Windows system culture. For applications whose current culture differs from the default system culture, this behavior is often undesirable. In the .NET Framework 4.5, the DefaultThreadCurrentCulture property enables an application to define the default culture of all threads in an application domain.

If you have not explicitly set the culture of any existing threads executing in an application domain, setting the DefaultThreadCurrentCulture property also changes the culture of these threads. However, if these threads execute in another application domain, their culture is defined by the DefaultThreadCurrentCulture property in that application domain or, if no default value is defined, by the default system culture. Because of this, we recommend that you always explicitly set the culture of your main application thread, and not rely on the DefaultThreadCurrentCulture property to define the culture of the main application thread.

Unless it is set explicitly, the value of the DefaultThreadCurrentCulture property is null, and the culture of threads in an application domain that have not been assigned an explicit culture is defined by the default Windows system culture.

like image 129
Amit Joshi Avatar answered Oct 14 '22 07:10

Amit Joshi


If you already have the wanted it culture which it looks like you have already then you could just use string.Format like this:

string.Format(Invoice.Vendor.VendorCurrency, "{0:C}", amount);

This will also allow you to specify different cultures in different places which could be advantageous in some situations.

like image 33
Tom Dee Avatar answered Oct 14 '22 07:10

Tom Dee