Search code examples
c#performancevalidationcultureinfo

Web.API - how to validate performant list of languages based on CultureInfo


I'm working with Web.API/.Net 7 and need to validate and conform a list of language ranges coming from Accept-Language header. The langauge ranges should be checked against the list of possible CultureInfo.Name options. Language ranges must not adhere to lower and upper case writings. So in case of a match the correctly formatted CultureInfo.Name should be used.

In Is there a way to "try parse" a string to System.Globalization.CultureInfo the recommended option for validation is to use CultureInfo.GetCultures(CultureTypes.AllCultures).

One can use LINQ Find() to find a matching element. Even CultureInfo.GetCultures(CultureTypes.AllCultures) returns a sorted list of names already, it won't help much for Find().

I think that there is a more performant solution than to scan 800+ entries of CultureInfos for each language in the Accept-Language header on each request.

In the above post it was recommended to put all elements in a dictionary and search that.

static readonly Dictionary<string, CultureInfo> CultureDict = 
    CultureInfo.GetCultures(CultureTypes.AllCultures).ToDictionary(c => c.Name);

Would a SortedList with BinarySearch also be an option?

How can I load that Dictionary or SortedList into memory only one time and access it from all requests? Do I need a Singleton? Are there any issues with parallel read access?

I only have basic understanding of those specifics, but what are the options?


Solution

  • The dictionary you have is the best option:

    1. It is a constant O(1) operation to do a lookup
    2. It is already declared as a static variable so it gets reused as a singleton

    You could declare the dictionary via an interface and inject the dependency so it is available in your validation classes.

    For example:

    public interface ISingleton {
        Dictionary<string, CultureInfo> Instance { get; }
    }
    
    service.AddSingleton<ISingleton>(() => new Singleton {Instance = CultureInfo.GetCultures(CultureTypes.AllCultures).ToDictionary(c => c.Name)});
    

    The one benefit with using dependency injection is your classes no longer depend on static properties and this makes things more reusable and testable.