private void FetcherAsynch_OnError(DroidRequestState state, NetworkResponse postNetworkResponse) { string message; switch (state.StatusCode) { case HttpStatusCode.RequestTimeout: message = "FetcherAsynch call to FetchAsynch timed out. uri " + state.AbsoluteUri; Device.Log.Metric(string.Format("FetchAsynch timed out: Uri: {0} Time: {1} milliseconds ", state.AbsoluteUri, DateTime.UtcNow.Subtract(_dtMetric).TotalMilliseconds)); postNetworkResponse.URI = state.AbsoluteUri; postNetworkResponse.StatusCode = HttpStatusCode.RequestTimeout; postNetworkResponse.ResponseString = string.Empty; postNetworkResponse.Expiration = DateTime.MinValue.ToUniversalTime(); postNetworkResponse.AttemptToRefresh = DateTime.MinValue.ToUniversalTime(); state.WebExceptionStatusCode = WebExceptionStatus.Timeout; state.Downloaded = DateTime.UtcNow; break; default: message = "FetcherAsynch call to FetchAsynch threw an exception"; state.WebExceptionStatusCode = WebExceptionStatus.ProtocolError; postNetworkResponse.StatusCode = state.StatusCode; postNetworkResponse.Message = message; postNetworkResponse.ResponseString = null; postNetworkResponse.ResponseBytes = null; postNetworkResponse.Verb = state.Verb; break; } var exc = new Exception(message, state.Exception); Device.Log.Error(exc); postNetworkResponse.WebExceptionStatusCode = state.WebExceptionStatusCode; postNetworkResponse.Exception = exc; postNetworkResponse.Downloaded = state.Downloaded; Device.PostNetworkResponse(postNetworkResponse); }
private void FetcherAsynch_OnDownloadComplete(DroidRequestState state, NetworkResponse postNetworkResponse) { postNetworkResponse.StatusCode = state.StatusCode; postNetworkResponse.WebExceptionStatusCode = state.WebExceptionStatusCode; postNetworkResponse.URI = state.AbsoluteUri; postNetworkResponse.Verb = state.Verb; postNetworkResponse.ResponseString = state.ResponseString; postNetworkResponse.ResponseBytes = state.ResponseBytes; postNetworkResponse.Expiration = state.Expiration; postNetworkResponse.Downloaded = state.Downloaded; postNetworkResponse.AttemptToRefresh = state.AttemptToRefresh; postNetworkResponse.Message = state.ErrorMessage; switch (postNetworkResponse.StatusCode) { case HttpStatusCode.OK: case HttpStatusCode.Created: case HttpStatusCode.Accepted: // things are ok, no event required break; case HttpStatusCode.NoContent: // return when an object is not found case HttpStatusCode.Unauthorized: // return when session expires case HttpStatusCode.InternalServerError: // return when an exception happens case HttpStatusCode.ServiceUnavailable: // return when the database or siteminder are unavailable postNetworkResponse.Message = string.Format("Network Service responded with status code {0}", state.StatusCode); Device.PostNetworkResponse(postNetworkResponse); break; default: postNetworkResponse.Message = string.Format("FetcherAsynch completed but received HTTP {0}", state.StatusCode); Device.Log.Error(postNetworkResponse.Message); Device.PostNetworkResponse(postNetworkResponse); return; } }
public void FetchSync(object param) { DisableConnectionReuseIfNecessary(); _dtMetric = DateTime.UtcNow; var fetchParameters = (DroidFetchParameters)param; var state = new DroidRequestState { AbsoluteUri = fetchParameters.Uri, FileName = fetchParameters.FileName, Downloaded = DateTime.UtcNow, Verb = "GET", }; var tokenSource2 = new CancellationTokenSource(); CancellationToken token = tokenSource2.Token; var t = Task.Factory.StartNew(() => { token.ThrowIfCancellationRequested(); var currThread = Thread.CurrentThread; using (token.Register(currThread.Abort)) { var url = new URL(fetchParameters.Uri); state.Connection = (HttpURLConnection)url.OpenConnection(); url.Dispose(); state.Connection.ConnectTimeout = fetchParameters.Timeout; state.Connection.ReadTimeout = fetchParameters.Timeout; if (fetchParameters.Headers != null && fetchParameters.Headers.Any()) { foreach (var key in fetchParameters.Headers.Keys) { state.Connection.SetRequestProperty(key, fetchParameters.Headers[key]); } } // End the Asynchronous response and get the actual response object state.Expiration = state.Connection.GetHeaderField("Expires").TryParseDateTimeUtc(); state.AttemptToRefresh = state.Connection.GetHeaderField("MonoCross-Attempt-Refresh").TryParseDateTimeUtc(); // apply web response headers to data collection. foreach (string key in state.Connection.HeaderFields.Keys.Where(k => k != null)) { state.Data[key] = state.Connection.GetHeaderField(key); } state.StatusCode = (HttpStatusCode)state.Connection.ResponseCode; switch (state.StatusCode) { case HttpStatusCode.OK: case HttpStatusCode.Created: case HttpStatusCode.Accepted: try { // extract response into bytes and string. byte[] bytes; var webResponse = new WebResponse { ResponseBytes = bytes = NetworkUtils.StreamToByteArray(state.Connection.InputStream), ResponseString = NetworkUtils.ByteArrayToStr(bytes), }; if (!string.IsNullOrEmpty(state.FileName)) { Device.File.Save(state.FileName, bytes); } state.ResponseBytes = bytes; state.ResponseString = webResponse.ResponseString; FetcherAsynch_OnDownloadComplete(state, fetchParameters.NetworkResponse); } catch (Exception ex) { string StatusDescription = string.Empty; ex.Data.Add("Uri", state.Connection.URL.ToString()); ex.Data.Add("Verb", state.Connection.RequestMethod); if (state.Connection != null) { state.StatusCode = (HttpStatusCode)state.Connection.ResponseCode; StatusDescription = state.Connection.ResponseMessage; } else { state.StatusCode = (HttpStatusCode)(-2); } if (string.IsNullOrEmpty(StatusDescription)) { ex.Data.Add("StatusDescription", StatusDescription); state.ErrorMessage = string.Format("Call to {0} had an Exception. {1}", state.Connection.URL, ex.Message); state.WebExceptionStatusCode = (WebExceptionStatus)(-1); } else { state.ErrorMessage = string.Format("Call to {0} had a web exception. {1} Desc: {2}", state.Connection.URL, ex.Message, StatusDescription); state.StatusCode = (HttpStatusCode)(-1); } ex.Data.Add("StatusCode", state.StatusCode); state.Exception = ex; state.Expiration = DateTime.UtcNow; state.AttemptToRefresh = DateTime.UtcNow; Device.Log.Error(state.ErrorMessage); Device.Log.Error(ex); FetcherAsynch_OnError(state, fetchParameters.NetworkResponse); } finally { //if (state.Response != null) // ((IDisposable)state.Response).Dispose(); state.Connection.Disconnect(); state.Connection = null; } break; case HttpStatusCode.NoContent: state.ErrorMessage = string.Format("No Content returned: Result {0} for {1}", state.StatusCode, state.AbsoluteUri); Device.Log.Warn(state.ErrorMessage); state.Expiration = DateTime.UtcNow; state.AttemptToRefresh = DateTime.UtcNow; state.Downloaded = DateTime.UtcNow; FetcherAsynch_OnDownloadComplete(state, fetchParameters.NetworkResponse); break; default: state.Expiration = DateTime.UtcNow; state.AttemptToRefresh = DateTime.UtcNow; state.Downloaded = DateTime.UtcNow; FetcherAsynch_OnError(state, fetchParameters.NetworkResponse); break; } } }, token); try { t.Wait(fetchParameters.Timeout + 5); } catch (Exception e) { state.Exception = e; state.Expiration = DateTime.UtcNow; state.AttemptToRefresh = DateTime.UtcNow; state.Downloaded = DateTime.UtcNow; FetcherAsynch_OnError(state, fetchParameters.NetworkResponse); } finally { if (state.Connection != null) { Task.Factory.StartNew(() => { state.Connection.Disconnect(); state.Connection = null; }); } } if (tokenSource2 != null && !t.IsCompleted) { tokenSource2.Cancel(); state.StatusCode = HttpStatusCode.RequestTimeout; state.Expiration = DateTime.UtcNow; state.AttemptToRefresh = DateTime.UtcNow; state.Downloaded = DateTime.UtcNow; FetcherAsynch_OnError(state, fetchParameters.NetworkResponse); } Device.Log.Metric(string.Format("FetchAsynch Completed: Uri: {0} Time: {1} milliseconds Size: {2} ", state.AbsoluteUri, DateTime.UtcNow.Subtract(_dtMetric).TotalMilliseconds, (fetchParameters.NetworkResponse.ResponseBytes != null ? fetchParameters.NetworkResponse.ResponseBytes.Length : -1))); }