如果将Thread.CurrentThread.CurrentCulture更改为不同于安装的(OS文化),则对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;
}
如果你想知道:
我已经确定:
也许值得一提的是,这是在内部使用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。
为什么会发生这种情况?我可能在某处做了一些严重错误的事情。正如我所说,它正处于目前的状态。它不是很漂亮。
答案 0 :(得分:2)
由于所有尝试在任何人看到它之前快速删除此帖子失败,这是解决方案。像往常一样,这是你从未想到的一件事 - 会议。当我画“粉碎你的头在这里!”在一张纸上的黑点,这是更正后的代码:
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。并且因为它正在调用同一个进程,后来挂起(并最终超时)因为初始请求的会话被锁定 - 并且传入的请求试图使用相同的会话。
现在把这个磁铁的黑色大点挂在墙上......