In a Controller action these variables:
var foo = Request.HttpContext.Features.Get<IRequestCultureFeature>()
.RequestCulture.Culture;
var bar = Thread.CurrentThread.CurrentCulture;
Both return "en". What's the difference between them and which is better to use in terms of determining the language of the user viewing the site??
According to the source code of RequestLocalizationMiddleware
public async Task Invoke(HttpContext context)
{
//..
context.Features.Set<IRequestCultureFeature>(new RequestCultureFeature(requestCulture, winningProvider));
SetCurrentThreadCulture(requestCulture);
await _next(context);
}
private static void SetCurrentThreadCulture(RequestCulture requestCulture)
{
CultureInfo.CurrentCulture = requestCulture.Culture;
CultureInfo.CurrentUICulture = requestCulture.UICulture;
}
the current request culture is set both for IRequestCultureFeature and current CultureInfo (CultureInfo.CurrentCulture gets/sets Thread.CurrentThread.CurrentCulture and therefore they are the same). So effectively there is no difference between these methods in terms of getting current culture.
The main difference is that IRequestCultureFeature is bound to the current HttContext (http request). And in my opinion when you are getting culture using IRequestCultureFeature you are explicitly saying you need current request culture. And when you are using Thread.CurrentThread.CurrentCulture it's not that clear that your intention is getting request culture. So I would prefer using IRequestCultureFeature because of better readability. And one can say this is better for testing purposes as well.
But setting the culture, on the other hand, has different effect for each scenario. If you replace IRequestCultureFeature by the following code
context.Features.Set<IRequestCultureFeature>(some request culture);
it will only replace the feature and won't affect anything else (afaik after researching some source code of the framework). But changing culture like this
CultureInfo.CurrentCulture = culture;
CultureInfo.CurrentUICulture = culture; //namely this line has effect described bellow
will directly affect resource manager and fetching localizations. Browsing source code shows the dependency on CultureInfo.CurrentUICulture
protected string GetStringSafely(string name, CultureInfo culture)
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
var keyCulture = culture ?? CultureInfo.CurrentUICulture;
//..
}
And simple tests confirm this
Res.culture1.resx
Value - First value
Res.culture2.resx
Value - Second value
//request culture is "culture1"
LocalizedString res = _stringLocalizer["Value"]; //"First value"
CultureInfo.CurrentUICulture = new CultureInfo("culture2");
LocalizedString res2 = _stringLocalizer["Value"]; //"Second value"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With