// This method is the callback for an HTTP request that returns a string (non-json) private static void ProcessVersionString(IAsyncResult result) { WebServiceState state = result.AsyncState as WebServiceState; if (state == null) { TraceLog.TraceError("Web Service State not found"); return; } // get the network operation status delegate Delegate netOpInProgressDel = state.NetworkOperationInProgressDelegate as Delegate; // get the web response and make sure it's not null (failed) HttpWebResponse resp = GetWebResponse(result); if (resp == null) { TraceLog.TraceError("GetWebResponse failed"); // signal that the network operation completed unsuccessfully if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } return; } // get the method-specific delegate Delegate del = state.Delegate as Delegate; if (del == null) { return; // if no delegate was passed, the results can't be processed } // write the result of the GET to a temp file string version = null; using (var inputStream = resp.GetResponseStream()) using (var reader = new StreamReader(inputStream)) { version = reader.ReadToEnd(); } // invoke the delegate with the version try { del.DynamicInvoke(version); } catch (Exception ex) { // signal the operation is done and unsuccessful if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } TraceLog.TraceException("ProcessVersionString: exception from DynamicInvoke", ex); } }
private static HttpWebResponse GetWebResponse(IAsyncResult result) { WebServiceState state = result.AsyncState as WebServiceState; if (state == null) { TraceLog.TraceError("Web Service State not found"); return(null); } var request = state.Request; if (request == null) { TraceLog.TraceError("Web Service Request not found"); return(null); } HttpWebResponse resp = null; // get response and mark request as not in progress try { resp = (HttpWebResponse)request.EndGetResponse(result); if (resp == null) { return(null); } } catch (Exception ex) { TraceLog.TraceException("GetWebResponse: EndGetResponse failed", ex); return(resp); } // put auth cookie in static memory if (resp.Headers[authResponseHeader] != null) { authCookie = resp.Headers[authResponseHeader]; } return(resp); }
private static void GetVersionLoop() { while (loopFlag) { // sleep for timeout Thread.Sleep(timeout); // don't want two concurrent updates if (checkingFlag || updatingFlag) { continue; } try { // locking is overkill here because only one thread that wakes up every <timeout> checkingFlag = true; WebServiceHelper.GetCurrentSoftwareVersion( VersionUrl, new WebServiceHelper.AccountDelegate((version) => { if (string.IsNullOrEmpty(version)) { TraceLog.TraceError("Could not download version file"); checkingFlag = false; return; } try { // compare versions var newVersion = new Version(version); if (newVersion > CurrentVersion) { TraceLog.TraceInfo(string.Format( "New version {0} more recent than current version {1}; downloading new version", newVersion, CurrentVersion)); updatingFlag = true; // download and install new software WebServiceHelper.DownloadCurrentSoftware( DownloadUrl, new WebServiceHelper.AccountDelegate((filename) => { // install the new software TraceLog.TraceInfo(string.Format("Download successful; installing {0}", filename)); Install(filename); }), new WebServiceHelper.NetOpDelegate((inProgress, status) => { // cleanup the checking flag based on network operation status (typically failures) if (inProgress == false) { updatingFlag = false; } })); } checkingFlag = false; } catch (Exception ex) { TraceLog.TraceException("Version check failed", ex); checkingFlag = false; updatingFlag = false; } }), new WebServiceHelper.NetOpDelegate((inProgress, status) => { // cleanup the checking flag based on network operation status (typically failures) if (inProgress == false) { checkingFlag = false; } })); } catch (Exception ex) { TraceLog.TraceException("GetVersionLoop failed", ex); checkingFlag = false; updatingFlag = false; } } }
// Common code to process the response from any web service call. This is invoked from the callback // method for the web service, and passed a Type for deserializing the response body. // This method will also invoke the delegate with the result of the Web Service call private static void ProcessResponse <T>(IAsyncResult result) { WebServiceState state = result.AsyncState as WebServiceState; if (state == null) { TraceLog.TraceError("Web Service State not found"); return; } // get the network operation status delegate Delegate netOpInProgressDel = state.NetworkOperationInProgressDelegate as Delegate; // get the web response and make sure it's not null (failed) //HttpWebResponseWrapper<T> resp = GetWebResponse<T>(result); HttpWebResponse resp = GetWebResponse(result); if (resp == null) { TraceLog.TraceError("GetWebResponse failed"); // signal that the network operation completed unsuccessfully if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } return; } else { OperationStatus status = AsOperationStatus(resp.StatusCode); if (resp.StatusCode == HttpStatusCode.Unauthorized) { // using this status code to indicate cookie has expired or is invalid if (authCookie != null) { // remove cookie and retry with credentials status = OperationStatus.Retry; authCookie = null; } } if (resp.StatusCode == HttpStatusCode.Forbidden) { // remove cookie and force authentication on next request authCookie = null; } if (netOpInProgressDel != null) { // signal the network operation completed and whether it completed successfully netOpInProgressDel.DynamicInvoke(false, status); if (status == OperationStatus.Retry) { // delegate will retry, exit now TraceLog.TraceInfo("Received a Retry response from Service"); return; } } } // get the method-specific delegate Delegate del = state.Delegate as Delegate; //if (del == null) // return; // if no delegate was passed, the results can't be processed // invoke the delegate with the response body try { T resultObject = (T) new DataContractJsonSerializer(typeof(T)).ReadObject(resp.GetResponseStream()); //T resultObject = resp.GetBody(); if (del == null) { return; // if no delegate was passed, the results can't be processed } del.DynamicInvoke(resultObject); } catch (Exception ex) { TraceLog.TraceException("ProcessResponse: exception from GetBody or DynamicInvoke", ex); // signal the operation is done and unsuccessful if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } if (del == null) { return; // if no delegate was passed, the results can't be processed } del.DynamicInvoke(null); } }
// This method is the callback for an HTTP request that returns a file. It will save the // file to a temporary location and invoke the delegate with the location. private static void ProcessFile(IAsyncResult result) { const string updateDir = @"updates"; const string msiname = @"WebTimer.msi"; WebServiceState state = result.AsyncState as WebServiceState; if (state == null) { TraceLog.TraceError("Web Service State not found"); return; } // get the network operation status delegate Delegate netOpInProgressDel = state.NetworkOperationInProgressDelegate as Delegate; // get the web response and make sure it's not null (failed) HttpWebResponse resp = GetWebResponse(result); if (resp == null) { TraceLog.TraceError("GetWebResponse failed"); // signal that the network operation completed unsuccessfully if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } return; } // get the method-specific delegate Delegate del = state.Delegate as Delegate; if (del == null) { return; // if no delegate was passed, the results can't be processed } try { // create directory if it doesn't exist if (!Directory.Exists(updateDir)) { Directory.CreateDirectory(updateDir); } } catch (Exception ex) { TraceLog.TraceException("Could not create updates directory", ex); // signal the operation is done and unsuccessful if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } // can't process further return; } // write the result of the GET to a temp file //string updatepath = Path.GetRandomFileName(); var now = DateTime.Now; string updatepath = Path.Combine(updateDir, string.Format("update-{0}", now.ToString("yyyy-MM-dd-HH-mm-ss"))); string updatefile = Path.Combine(updatepath, msiname); try { TraceLog.TraceInfo(string.Format("Creating update directory {0}", updatepath)); Directory.CreateDirectory(updatepath); TraceLog.TraceInfo(string.Format("Saving MSI in {0}", updatefile)); using (var inputStream = resp.GetResponseStream()) using (var fileStream = File.OpenWrite(updatefile)) { byte[] buffer = new byte[8 * 1024]; int len; while ((len = inputStream.Read(buffer, 0, buffer.Length)) > 0) { fileStream.Write(buffer, 0, len); } } } catch (Exception ex) { TraceLog.TraceException(string.Format("Could not create temporary file {0}", updatefile), ex); // signal the operation is done and unsuccessful if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } return; } // invoke the delegate with the temp file name try { del.DynamicInvoke(updatefile); } catch (Exception ex) { TraceLog.TraceException("ProcessFile: exception from DynamicInvoke", ex); // signal the operation is done and unsuccessful if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } } }
private static void InvokeWebServiceRequest_Inner(IAsyncResult res) { WebInvokeServiceState state = res.AsyncState as WebInvokeServiceState; if (state == null) { TraceLog.TraceError("Web Service State not found"); return; } var request = state.Request; var netOpInProgressDel = state.NetworkOperationInProgressDelegate as Delegate; if (request == null) { TraceLog.TraceError("Web Service Request not found"); // signal the operation is done and unsuccessful if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } return; } Stream stream = null; try { // this will throw if the connection can't be established stream = request.EndGetRequestStream(res); } catch (Exception ex) { TraceLog.TraceException("Can't obtain stream", ex); // signal the operation is done and unsuccessful if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } return; } // serialize a request body if one was passed in (and the verb will take it) if (state.RequestBody != null && request.Method != "GET") { // a null request body means that the caller wants to get the stream back and write to it directly if (state.RequestBody as Delegate != null) { Delegate streamDel = (Delegate)state.RequestBody; // invoke the delegate passed in with the request stream, so that the external caller // can push data into the stream as it becomes available streamDel.DynamicInvoke(stream); } else { // the caller passed the complete object - so just serialize it onto the stream if (state.RequestBody.GetType() == typeof(byte[])) { /* * byte[] bytes = (byte[])state.RequestBody; #if !IOS * stream = new GZipStream(stream, CompressionMode.Compress); * request.ContentType = "application/x-gzip"; #else * stream = new MemoryStream(); * request.ContentType = "application/octet-stream"; #endif * stream.Write(bytes, 0, bytes.Length); */ } else { request.ContentType = "application/json"; DataContractJsonSerializer ser = new DataContractJsonSerializer(state.RequestBody.GetType()); ser.WriteObject(stream, state.RequestBody); } // we got all the data into the stream, so flush/close it stream.Flush(); stream.Close(); } } // complete the invocation (this is not done inline because the InvokeWebServiceRequest_Inner_Complete() method // is reused by external callers that want to write to a stream directly and then invoke the operation) InvokeWebServiceRequest_Invoke(request, state.Delegate, state.NetworkOperationInProgressDelegate, state.Callback); }
// Common code for invoking all the web service calls. // GET requests will be served directly from this method, // POST/PUT/DELETE requests are served from the InvokeWebServiceRequest_Inner method (which is an async callback) private static void InvokeWebServiceRequest(string userCreds, string url, string verb, object obj, Delegate del, Delegate netOpInProgressDel, AsyncCallback callback) { // signal that a network operation is starting if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(true, OperationStatus.Started); } Uri uri = null; if (Uri.TryCreate(url, UriKind.RelativeOrAbsolute, out uri) == false || uri.Scheme != "http" && uri.Scheme != "https") { TraceLog.TraceError("InvokeWebServiceRequest: bad URL: " + url); return; } var request = (HttpWebRequest)WebRequest.Create(uri); request.UserAgent = UserAgentString; request.Accept = "application/json"; request.Method = verb == null ? "GET" : verb; if (authCookie != null) { // send auth cookie request.Headers[authRequestHeader] = authCookie; } else if (userCreds != null) { // send credentials in authorization header // url form encoded //string credentials = string.Format("UserName={0}&Password={1}", user.UserName, user.Password); // basic auth encoded request.Headers[authorizationHeader] = string.Format("Basic {0}", userCreds); request.Headers[HttpApplicationHeaders.RequestedWith] = UserAgents.WebTimerWindows; } // set the session ID header var sessionToken = TraceLog.Session; if (sessionToken != null) { request.Headers[HttpApplicationHeaders.Session] = sessionToken; } // if this is a GET request, we can execute from here if (request.Method == "GET") { // execute the web request and get the response try { WebServiceState reqState = new WebServiceState() { Request = request, Delegate = del, NetworkOperationInProgressDelegate = netOpInProgressDel }; request.BeginGetResponse(callback, reqState); } catch (Exception ex) { TraceLog.TraceException("Exception in BeginGetResponse", ex); // signal that a network operation is done and unsuccessful if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } } } else { // this is a request that contains a body (PUT, POST, DELETE) // need to nest another async call - this time to get the request stream try { request.BeginGetRequestStream( new AsyncCallback(InvokeWebServiceRequest_Inner), new WebInvokeServiceState() { Request = request, Callback = callback, Delegate = del, NetworkOperationInProgressDelegate = netOpInProgressDel, RequestBody = obj }); } catch (Exception ex) { // trace the exception TraceLog.TraceException("Exception in BeginGetResponse", ex); // signal that a network operation is done and unsuccessful if (netOpInProgressDel != null) { netOpInProgressDel.DynamicInvoke(false, OperationStatus.Failed); } } } }