ASP.Net Crop Name Checker

We have a multilingual site that uses asp.net 2.0 cultures. The current culture is specified through a URL rewritten as a query string. (~ / es / blah.aspx - Spanish version ~ / blah.aspx - rewritten as ~ / blah.aspx? lang = es)

The code that tests the culture is as follows:

System.Globalization.CultureInfo ci; try { ci = new System.Globalization.CultureInfo(Request.QueryString["lang"] ?? string.Empty); } catch { ci = new System.Globalization.CultureInfo(string.Empty); } 

If the culture set is not installed, the default is English, 127. When there is a culture, all links on this page are pre-registered in the correct culture name.

Some other spider lacked some links in the form ~ / www.test.com / blah.aspx and clogs our site with the culture www.test.com, which floods our logging error.

Is there a way to check if the name of the culture is valid, except for an exception exception?

+4
source share
5 answers

It seemed to me that I would quickly realize that the console application worked so quickly.

It mainly uses all 3 methods (constructor, LINQ and foreach) to get CultureInfo from a string 10,000 times in a loop. For brevity, I deleted the stopwatch and console output.

 string culture = "en-GB"; CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures); for (int i = 0; i < 10000; i++) { try { CultureInfo c = new CultureInfo(culture); } catch { } } for (int i = 0; i < 10000; i++) { CultureInfo c = cultures.FirstOrDefault((x) => x.Name == culture); } for (int i = 0; i < 10000; i++) { foreach (CultureInfo c in cultures) { if (c.Name == culture) break; } } 

The results are as follows:

 Try Catch: 00:00:00.0023860 LINQ: 00:00:00.0542459 ForEach: 00:00:00.0238937 

If you delete a culture variable and call it each iteration, then LINQ and ForEach loops take about 2.5 seconds.

Thus, using the constructor is beneficial if you expect to get a lot of valid input and only an odd invalid. But if you change the value, if the input is from en-GB to TEST , then everything will change in bulk.

 Invalid Culture Try Catch: 00:00:39.7163513 Invalid Culture LINQ: 00:00:00.0791752 Invalid Culture ForEach: 00:00:00.0291480 

Obviously, my test application is not a real scenario, but since the OP said that it was called for each request, I can imagine that there is a lot of code to call this code in a large web application. It can be a negative or service vector, process the entire processor by sending a web server with requests that have an invalid culture parameter.

+10
source

A fairly similar answer, as already mentioned, only with a more compact linq expression:

 private static bool IsValidCultureInfoName(string name) { return CultureInfo .GetCultures(CultureTypes.SpecificCultures) .Any(c => c.Name == name); } 
+6
source

You do not need to use LINQ:

 private static bool IsValidCultureName(string cultureName) { CultureInfo[] cultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures); foreach (CultureInfo culture in cultures) { if (culture.Name == cultureName) return true; } return false; } 

This can be quite expensive, but perhaps even cheaper than dealing with exceptions, which are quite expensive, to measure the difference before taking the floor for it.

I don’t think that the list of certain cultures will change between versions of .NET, so you should probably get the list at startup and cache it somewhere.

+5
source

This site provides an example of using LINQ:

 CultureInfo[] cultures = System.Globalization.CultureInfo.GetCultures (CultureTypes.SpecificCultures); var selectCulture = from p in cultures where p.Name == value select p; if (selectCulture.Count() == 1) { // your culture is good } 

It seems a little hard. I probably stick with what you have.

+2
source

Here is what I did for my action filter. We check only the language, not the language.

 public class HttpInternationalizationAttribute : ActionFilterAttribute { private static readonly HashSet<string> Langs = new HashSet<string>(CultureInfo.GetCultures(CultureTypes.NeutralCultures) .Select(x => x.TwoLetterISOLanguageName.ToUpper())); public override void OnActionExecuting(HttpActionContext actionContext) { var language = (string)actionContext.ControllerContext.RouteData.Values["language"]; if (!string.IsNullOrEmpty(language) && Langs.Contains(language.ToUpper())) { Thread.CurrentThread.CurrentCulture = CultureInfo.GetCultureInfo(language); Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo(language); } } } 

Using hashset, this will work in O (1).

Greetings!

+1
source

All Articles