Skip to content
Browse files

Add ability to cancel Async calls

HttpWebRequest supports Abort() to cancel Async Calls when any of the
underlying Async methods are called.
  • Loading branch information...
1 parent 4b50fff commit 7a8cc9c82b429d3b8edb036649dc7943f8d121b4 @pseabury committed Jul 3, 2012
View
46 src/ServiceStack.Common/ServiceClient.Web/AsyncServiceClient.cs
@@ -19,6 +19,7 @@ public class AsyncServiceClient
{
private static readonly ILog Log = LogManager.GetLogger(typeof(AsyncServiceClient));
private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(60);
+ private HttpWebRequest _webRequest = null;
/// <summary>
/// The request filter is called before any request.
@@ -196,6 +197,16 @@ public void SetCredentials(string userName, string password)
SendWebRequest(httpMethod, absoluteUrl, request, onSuccess, onError);
}
+ public void CancelAsync()
+ {
+ if (_webRequest != null)
+ {
+ // Request will be nulled after it throws an exception on its async methods
+ // See - http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.abort
+ _webRequest.Abort();
+ }
+ }
+
internal static void AllowAutoCompression(HttpWebRequest webRequest)
{
webRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
@@ -240,25 +251,25 @@ internal static void AllowAutoCompression(HttpWebRequest webRequest)
}
#else
- var webRequest = (HttpWebRequest)WebRequest.Create(requestUri);
+ _webRequest = (HttpWebRequest)WebRequest.Create(requestUri);
if (StoreCookies)
{
- webRequest.CookieContainer = CookieContainer;
+ _webRequest.CookieContainer = CookieContainer;
}
#endif
if (!DisableAutoCompression)
{
- webRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
- webRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
+ _webRequest.Headers.Add(HttpRequestHeader.AcceptEncoding, "gzip,deflate");
+ _webRequest.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate;
}
var requestState = new RequestState<TResponse>
{
HttpMethod = httpMethod,
Url = requestUri,
- WebRequest = webRequest,
+ WebRequest = _webRequest,
Request = request,
OnSuccess = onSuccess,
OnError = onError,
@@ -268,7 +279,7 @@ internal static void AllowAutoCompression(HttpWebRequest webRequest)
};
requestState.StartTimer(this.Timeout.GetValueOrDefault(DefaultTimeout));
- SendWebRequestAsync(httpMethod, request, requestState, webRequest);
+ SendWebRequestAsync(httpMethod, request, requestState, _webRequest);
return requestState;
}
@@ -303,14 +314,22 @@ internal static void AllowAutoCompression(HttpWebRequest webRequest)
ApplyWebRequestFilters(webRequest);
- if (!httpGetOrDelete && request != null)
+ try
{
- webRequest.ContentType = ContentType;
- webRequest.BeginGetRequestStream(RequestCallback<TResponse>, requestState);
+ if (!httpGetOrDelete && request != null)
+ {
+ webRequest.ContentType = ContentType;
+ webRequest.BeginGetRequestStream(RequestCallback<TResponse>, requestState);
+ }
+ else
+ {
+ requestState.WebRequest.BeginGetResponse(ResponseCallback<TResponse>, requestState);
+ }
}
- else
+ catch (Exception ex)
{
- requestState.WebRequest.BeginGetResponse(ResponseCallback<TResponse>, requestState);
+ // BeginGetRequestStream can throw if request was aborted
+ HandleResponseError(ex, requestState);
}
}
@@ -391,7 +410,6 @@ private void ReadCallBack<T>(IAsyncResult asyncResult)
if (read > 0)
{
-
requestState.BytesData.Write(requestState.BufferRead, 0, read);
responseStream.BeginRead(
requestState.BufferRead, 0, BufferSize, ReadCallBack<T>, requestState);
@@ -433,6 +451,7 @@ private void ReadCallBack<T>(IAsyncResult asyncResult)
finally
{
responseStream.Close();
+ _webRequest = null;
}
}
catch (Exception ex)
@@ -496,7 +515,10 @@ private void HandleResponseError<TResponse>(Exception exception, RequestState<TR
Log.Debug(string.Format("Exception Reading Response Error: {0}", exception.Message), exception);
requestState.HandleError(default(TResponse), exception);
+
+ _webRequest = null;
}
+
private void ApplyWebResponseFilters(WebResponse webResponse)
{
if (!(webResponse is HttpWebResponse)) return;
View
5 src/ServiceStack.Common/ServiceClient.Web/ServiceClientBase.cs
@@ -660,6 +660,11 @@ public virtual void PutAsync<TResponse>(string relativeOrAbsoluteUrl, object req
asyncClient.SendAsync(Web.HttpMethod.Put, GetUrl(relativeOrAbsoluteUrl), request, onSuccess, onError);
}
+ public virtual void CancelAsync()
+ {
+ asyncClient.CancelAsync();
+ }
+
#if !SILVERLIGHT
public virtual TResponse Send<TResponse>(string httpMethod, string relativeOrAbsoluteUrl, object request)
{

0 comments on commit 7a8cc9c

Please sign in to comment.
Something went wrong with that request. Please try again.