【问题标题】:HttpWebRequest times out if Thread.CurrentThread.CurrentCulture is changed如果 Thread.CurrentThread.CurrentCulture 更改,则 HttpWebRequest 超时
【发布时间】:2011-12-06 15:32:57
【问题描述】:

如果您将 Thread.CurrentThread.CurrentCulture 更改为不同于已安装的内容(操作系统文化),则对 HttpWebRequest.GetResponse() 的调用将始终超时。

为了澄清,这里是我的实用程序类的内容,它正在做脏活:

private static void ReplicateCookies(HttpWebRequest request)
{
    if (HttpContext.Current == null)
        return;
    if (request.CookieContainer == null)
        request.CookieContainer = new CookieContainer();
    foreach (var cookie in from object key in HttpContext.Current.Request.Cookies.Keys select HttpContext.Current.Request.Cookies[key.ToString()])
        request.CookieContainer.Add(new Cookie(cookie.Name, cookie.Value, cookie.Path, string.IsNullOrEmpty(cookie.Domain) 
            ? HttpContext.Current.Request.Url.Host
            : cookie.Domain));
}

private HttpWebRequest CreateRequest(string url, string method = null)
{
    var httpRequest = WebRequest.Create(url) as HttpWebRequest;
    ReplicateCookies(httpRequest);
    httpRequest.KeepAlive = false;
    httpRequest.Method = method ?? "GET";
    httpRequest.Timeout = 20000;
    httpRequest.Proxy = null;
    httpRequest.ServicePoint.ConnectionLeaseTimeout = 20000;
    httpRequest.ServicePoint.MaxIdleTime = 10000;
    return httpRequest;
}

public string ReadWebPage(string url)
{
    var oldCulture = Thread.CurrentThread.CurrentCulture.Name;
    Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-GB");
    string result;
    var httpRequest = CreateRequest(url);
    httpRequest.Headers.Add("Accept-Language", oldCulture);
    try
    {
        using (var httpResponse = httpRequest.GetResponse())
        {
            using (var stream = httpResponse.GetResponseStream())
            {
                using (var reader = new StreamReader(stream, Encoding.UTF8))
                {
                    result = reader.ReadToEnd();
                    reader.Close();
                }
                stream.Flush();
                stream.Close();
            }
            httpResponse.Close();
        }
    }
    finally
    {
        httpRequest.Abort();
    }
    Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = new CultureInfo(oldCulture);
    return result;
}

如果你想知道:

  • 在 ReplicateCookies 中,如果您使用 null 作为域调用 CookieCONtainer.Add,它将在运行时失败
  • 代码已经包含解决 CurrentCulture 问题的修复程序。继续,取出所有改变文化的代码,将你的线程文化设置为某种东西(例如“fr-FR”)并给代码一个旋转。

我已经确定:

  • 没有代理干扰请求
  • 没有防火墙设置阻止这样的请求

也许值得一提的是,它在 MVC3 Web 应用程序内部用于生成模板化消息 - 其中模板就是网页本身。应用程序将其文化设置为这样 (Global.asax.cs):

protected void Application_AcquireRequestState()
{
    if (HttpContext.Current == null)
        return;
    if (HttpContext.Current.Session == null)
        return;
    if (HttpContext.Current.Session["Culture"] != null)
        CultureHelper.SetCulture(HttpContext.Current.Session["Culture"].ToString());
}

还有助手类:

public static class CultureHelper
{
    public static void SetCulture(string culture)
    {
        if (string.IsNullOrEmpty(culture))
            return;
        var cultureInfo = new CultureInfo(culture);
        if (culture.ToLower().Equals("fr-fr") || culture.ToLower().Equals("fr"))
            cultureInfo.NumberFormat.NumberGroupSeparator = cultureInfo.NumberFormat.CurrencyGroupSeparator = ".";
        Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = cultureInfo;
    }
}

出于某种原因,法语默认使用空格作为千​​位分隔符 - 因此是 if 语句。

ReplicateCookies 方法会将会话 cookie 和身份验证 cookie 复制到内部请求,以便会话/身份验证保留在生成的内部请求中。

该网站显然有办法改变当前的文化(改变会话值)。在 ReadWebPage 方法中的修复之前,一切都会正常工作,直到文化改变。之后,每个 HttpWebRequest.GetResponse 都会超时,直到文化变回 - 在我的情况下 - en-GB。

任何想法为什么会发生这种情况?我可能在某个地方做错了什么。正如我所说,它在当前状态下工作。只是不是很漂亮。

【问题讨论】:

    标签: c# http httpwebrequest timeout cultureinfo


    【解决方案1】:

    由于在任何人看到它之前快速删除此帖子的所有尝试都失败了,因此这是解决方案。像往常一样,这是你从未想过的一件事——会话。当我画出“在这里砸你的头!”一张纸上的黑点,这里是更正的代码:

    private static void ReplicateCookies(HttpWebRequest request)
    {
        if (HttpContext.Current == null)
            return;
        if (request.CookieContainer == null)
            request.CookieContainer = new CookieContainer();
        foreach (var cookieKey in HttpContext.Current.Request.Cookies.Keys)
        {
            if (!cookieKey.ToString().Equals("ASP.NET_SessionId"))
            {
                var cookie = HttpContext.Current.Request.Cookies[cookieKey.ToString()];
                request.CookieContainer.Add(new Cookie(cookie.Name, cookie.Value, cookie.Path, string.IsNullOrEmpty(cookie.Domain)
                    ? HttpContext.Current.Request.Url.Host
                    : cookie.Domain));
            }
    
        }
    }
    
    private HttpWebRequest CreateRequest(string url, string method = null)
    {
        var httpRequest = WebRequest.Create(url) as HttpWebRequest;
        ReplicateCookies(httpRequest);
        httpRequest.KeepAlive = false;
        httpRequest.Method = method ?? "GET";
        httpRequest.Timeout = 20000;
        httpRequest.Proxy = null;
        httpRequest.ServicePoint.ConnectionLeaseTimeout = 20000;
        httpRequest.ServicePoint.MaxIdleTime = 10000;
        httpRequest.Headers.Add("Accept-Language", Thread.CurrentThread.CurrentCulture.Name);
        return httpRequest;
    }
    
    public string ReadWebPage(string url)
    {
        string result;
        var httpRequest = CreateRequest(url);
        try
        {
            using (var httpResponse = httpRequest.GetResponse())
            {
                using (var stream = httpResponse.GetResponseStream())
                {
                    using (var reader = new StreamReader(stream, Encoding.UTF8))
                    {
                        result = reader.ReadToEnd();
                        reader.Close();
                    }
                    stream.Flush();
                    stream.Close();
                }
                httpResponse.Close();
            }
        }
        finally
        {
            httpRequest.Abort();
        }
        return result;
    }
    

    说明:问题出在 ReplicateCookies 方法中。其中包括重写 ASP 会话 cookie。由于它正在调用同一个进程,因此后来挂起(并最终超时),因为来自初始请求的会话被锁定 - 并且传入的请求试图使用同一个会话。

    现在把这个头磁铁的大黑点挂在墙上...

    【讨论】:

      猜你喜欢
      • 2011-03-21
      • 2019-11-24
      • 1970-01-01
      • 2019-07-22
      • 1970-01-01
      • 2011-06-15
      • 1970-01-01
      • 2015-01-28
      相关资源
      最近更新 更多