简体   繁体   中英

What's the difference between IRequestCultureFeature and CurrentCulture in Asp.Net Core?

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"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM