Если вы измените 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, если вы вызываете CookieCOntainer.Добавить со значением null в качестве домена он завершится с ошибкой во время выполнения
- код уже содержит исправление, устраняющее проблему CurrentCulture. Продолжайте, выньте весь код, который изменяет культуру, установите что-то в вашей культуре потока (например, «fr-FR») и добавьте код.
Я убедился, что:
- прокси не вмешивается в запрос
- никакие настройки брандмауэра не запрещают подобные запросы
Возможно, стоит упомянуть, что это использовалось внутри веб-приложения MVC3 для внутренней генерации шаблонных сообщений, где шаблон сам является веб-страницей. Приложение устанавливает свою культуру следующим образом (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.
Есть идеи, почему это происходит? Я мог бы сделать что-то совершенно неправильно где-то. Как я уже сказал, он работает в своем текущем состоянии. Это просто не очень красиво.