ASP.Net验证文化名称

时间:2009-01-26 16:36:02

标签: c# .net asp.net culture

我们有一个多语言网站,利用asp.net 2.0文化。通过将url重写为查询字符串来设置当前文化。 (〜/ es / blah.aspx是〜/ blah.aspx的西班牙语版本 - 改写为〜/ blah.aspx?lang = es)

测试文化的代码如下:

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

如果没有文化集,则默认为英语,127。当有文化时,该页面上的所有链接都会预先填入正确的文化名称。

一些蜘蛛如何以〜/ www.test.com / blah.aspx的形式抓住一些链接,并用www.test.com的文化锤击我们的网站并充斥我们的​​错误日志记录。

除了捕获异常之外,有没有办法测试文化名称是否有效?

5 个答案:

答案 0 :(得分:10)

我以为我可以快速测量一下,这样可以打开一个快速的控制台应用程序。

它基本上使用所有3个方法(构造函数,LINQ和foreach)在循环中从字符串中获取CultureInfo 10000次。为简洁起见,我删除了秒表和控制台输出。

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;
    }
}

结果如下......

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

如果删除culture变量并在每次迭代时调用它,那么LINQ和ForEach循环大约需要2.5秒。

因此,如果您希望获得大量有效输入并且只有奇数无效输入,那么使用构造函数是有利的。但是,如果您在en-GBTEST的输入时更改了值,那么事情会发生巨大变化。

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

显然我的测试应用程序不是一个真实的场景,但由于OP表示这是基于每个请求调用的,我可以想象在大型Web应用程序中,这个代码可能被调用很多。它可能是一个拒绝或服务向量,通过向所有具有无效文化参数的请求发送垃圾邮件来占用所有CPU。

答案 1 :(得分:6)

几乎与已经陈述的答案相同,只有更紧凑的linq表达式:

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

答案 2 :(得分:5)

你没有 使用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;
}

这可能相当昂贵,但可能仍然比处理非常昂贵的异常更便宜 - 但是在接受我的话之前衡量差异。

我认为定义的文化列表不会在.NET版本之间发生变化,所以你应该在启动时获取列表并将其缓存到某个地方。

答案 3 :(得分:2)

This site有一个使用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
}
但是,看起来有点沉重。我可能会坚持你拥有的东西。

答案 4 :(得分:1)

这是我最终为我的Action Filter做的事情。 我们只检查语言,而不是语言环境。

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);
        }
    }
}

使用散列集,这将在O(1)中运行。

干杯!