2012-06-08 11 views
6

Ho un thread di lavoro in background che sincronizza costantemente i dati su/da un server remoto. Quando eseguo per la prima volta l'app, tutto sembra funzionare correttamente. Effettua la richiesta web ogni 30 secondi e i dati vengono restituiti correttamente.HTTPWebRequest & Dopo un po 'di tempo, 400 (Richiesta non valida) inizia

Se lascio il simulatore in esecuzione per un lungo periodo, alla fine la richiesta non riuscirà con una (400) richiesta errata. E tutte le richieste successive fanno la stessa cosa. Se uccido l'app e la riavvio ... tutto va bene.

Qualcuno ha qualche idea? Il codice è sotto

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

Fallisce su questa linea:

httpResponse = (HttpWebResponse)httpRequest.GetResponse(); 

dello stack:

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 

La richiesta non è mai sempre al server remoto.

+0

Il ** 400 ** proviene dal server. Sarebbe utile se tu potessi eseguire uno sniffer (ad esempio wirehark) e scoprire cosa è stato trasmesso in quel caso (e confrontarlo con la normale risposta che hai ottenuto prima). – poupou

+0

Questa è la cosa strana, non viene dal server. IIS non vede mai la richiesta entrare. –

+0

Molto strano - ma un bel indizio! – poupou

risposta

2

Il problema era nella collezione clientHeaders. Questa classe RESTClient viene istanziata una volta durante il ciclo di vita dell'applicazione. Stavo aggiungendo le intestazioni più e più volte e non cancellandole prima. Dopo un po ', le intestazioni sono diventate troppo grandi e una richiesta errata è stata emessa.

+1

Non è stato facile capirlo guardando il codice fornito :) –

0

Presumo che si esauriscano le connessioni. Si può cercare di aumentare la loro:

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

+0

potresti provare comunque ad aumentare le connessioni. – NickD

+0

Come si fa in MonoTouch? –

+0

System.Net.ServicePointManager.DefaultConnectionLimit = 65535; – NickD