HTTPWebRequest и через некоторое время запускается 400 (неверный запрос)

У меня есть фоновый рабочий поток, который постоянно синхронизирует данные с / с удаленного сервера. Когда я впервые запускаю приложение, все работает нормально. Он делает веб-запрос каждые 30 секунд, и данные успешно возвращаются.

Если я оставлю симулятор включенным на долгое время, в конечном итоге запрос завершится ошибкой с ошибкой (400). И все последующие запросы делают то же самое. Если я убью приложение и перезапущу его ... все будет хорошо.

У кого-нибудь есть идеи? Код ниже.

public RestResponse<T> Execute<T>(RestRequest request) {
    var restResponse = new RestResponse<T>();
    var serializer = new JavaScriptSerializer();
    var urlPath = baseUrl + "/" + request.Resource;
    Console.WriteLine("Requesting: " + urlPath);
    var httpRequest = (HttpWebRequest)HttpWebRequest.Create(new Uri(urlPath));

    httpRequest.Headers = request.Headers;
    foreach (string key in clientHeaders.Keys)
        httpRequest.Headers.Add(key, clientHeaders[key]);
    httpRequest.Headers.Add("Accept-Encoding", "gzip,deflate");

    Authenticator.Authenticate(httpRequest);
    httpRequest.Method = request.Method.ToString();       
    HttpWebResponse httpResponse = null;
    try {
        if ((request.Method == Method.POST) && (!request.IsJsonPost))
            SetPostData(httpRequest, request);

        if ((request.Method == Method.POST) && (request.IsJsonPost)){
            SetJsonPostData(httpRequest, request);
        }

        httpResponse = (HttpWebResponse)httpRequest.GetResponse();
        var reader = new StreamReader(GetStreamForResponse(httpResponse));
        var responseString = reader.ReadToEnd();
        Console.WriteLine(responseString);
        reader.Close();
        restResponse.StatusCode = httpResponse.StatusCode;
        restResponse.Headers = httpResponse.Headers;
        restResponse.Data = serializer.Deserialize<T>(responseString);
        restResponse.ResponseStatus = ResponseStatus.Completed;
        httpResponse.Close();
    } catch (WebException e) {
        restResponse.ResponseStatus = ResponseStatus.Error;
        restResponse.ErrorMessage = e.Message;
        restResponse.ErrorException = e;
        var webResponse = (HttpWebResponse)e.Response;
        if (webResponse != null) {
            restResponse.StatusCode = webResponse.StatusCode;
            restResponse.Headers = webResponse.Headers;
        }
        if (restResponse.StatusCode != HttpStatusCode.NotModified)
            Console.WriteLine("An exception occured:\r\n " + request.Resource + "\r\n" + e + "\r\n");
    } catch (Exception ex) {
        restResponse.ResponseStatus = ResponseStatus.Error;
        restResponse.ErrorMessage = ex.Message;
        restResponse.ErrorException = ex;
    }

    if (httpResponse != null)
        httpResponse.Close();

    return restResponse;
}

Он не работает в этой строке:

httpResponse = (HttpWebResponse)httpRequest.GetResponse();

Трассировки стека:

System.Net.WebException: The remote server returned an error: (400) Bad Request.
  at System.Net.HttpWebRequest.CheckFinalStatus (System.Net.WebAsyncResult result) [0x002f2] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1477 
  at System.Net.HttpWebRequest.SetResponseData (System.Net.WebConnectionData data) [0x00141] in /Developer/MonoTouch/Source/mono/mcs/class/System/System.Net/HttpWebRequest.cs:1300 

Запрос никогда не попадает на удаленный сервер.


person Chris Kooken    schedule 08.06.2012    source источник
comment
400 поступает с сервера. Было бы полезно, если бы вы могли запустить сниффер (например, wirehark) и выяснить, что было передано в этом случае (и сравнить его с обычным ответом, который вы получили до этого).   -  person poupou    schedule 08.06.2012
comment
Это странно, это не с сервера. IIS никогда не видит входящего запроса.   -  person Chris Kooken    schedule 08.06.2012
comment
Очень странно - но хорошая подсказка!   -  person poupou    schedule 08.06.2012
comment
Есть ли причина, по которой ваш запрос создается таким образом? Я бы предпочел (HttpWebRequest)WebRequest.Create(new Uri(urlPath));. Вы пробовали использовать свой код в службе, не требующей аутентификации? Вы пробовали не устанавливать данные публикации?   -  person Cheesebaron    schedule 12.06.2012
comment
Есть ли какие-то длительные запросы (сервер долго не отвечает)? Что произойдет, если эта проблема возникнет, если вы перезапустите удаленный сервер вместо собственного приложения? У вас есть возможность попробовать это? Причина, по которой я спрашиваю, заключается в том, что я думаю, что ОС предотвращает слишком много одновременных исходящих запросов к одному и тому же месту назначения ...   -  person user1429080    schedule 26.06.2012
comment
Просто предположение, но в HttpWebRequest может быть регресс, который приведет к тому же поведению, которое описано в этой ошибке: bugzilla.novell.com/show_bug.cgi?id=648862 Поэтому просто ради этого попробуйте установить httpRequest.KeepAlive = false; и посмотрите, поможет ли это. В противном случае я бы рекомендовал создать новый отчет об ошибке в xamarins bugzilla и предоставить тестовый пример, который можно воспроизвести на их стороне. Еще одно надуманное предложение - попробовать сделать код асинхронным, но я не понимаю, почему это должно вести себя по-другому.   -  person Cheesebaron    schedule 26.06.2012
comment
У вас есть экранированный символ / (% 2f) в URI (request.Resource)? Или появляется спустя время? Возникла проблема с конструктором Uri: stackoverflow.com/questions/10413795/   -  person Ivan Nikitin    schedule 28.06.2012


Ответы (2)


Проблема была в коллекции clientHeaders. Этот RESTClient класс создается один раз в течение жизненного цикла приложения. Я добавлял заголовки снова и снова, а не очищал их сначала. Через некоторое время заголовки стали слишком большими, и был выдан неверный запрос.

person Chris Kooken    schedule 28.06.2012
comment
Понять это, взглянув на предоставленный код, было непросто :) - person Ivan Nikitin; 30.06.2012

Я предполагаю, что у вас закончились соединения. Вы можете попробовать их увеличить:

<configuration> <system.net> <connectionManagement> <add address="*" maxconnection="65535" /> </connectionManagement> </system.net> </configuration>

person NickD    schedule 23.06.2012
comment
в любом случае вы можете попробовать увеличить количество подключений. - person NickD; 23.06.2012
comment
Как мне это сделать в MonoTouch? - person Chris Kooken; 23.06.2012
comment
System.Net.ServicePointManager.DefaultConnectionLimit = 65535; - person NickD; 23.06.2012
comment
Я просто смотрю в system.web.dll с помощью отражателя, что может вызвать http 400. - person NickD; 23.06.2012
comment
if (this.QueryStringText.Length ›httpRuntime.MaxQueryStringLength) {выбросить новое исключение HttpException (400, System.Web.SR.GetString (QueryString_too_long)); } - person NickD; 23.06.2012
comment
Не строка запроса. Мой URL-адрес очень короткий. - person Chris Kooken; 23.06.2012
comment
хм, вы меняете baseUrl? может это связано с резьбой? что произойдет, если вы запустите 1000 запросов последовательно? - person NickD; 23.06.2012