Skip to content

Instantly share code, notes, and snippets.

@tugberkugurlu
Created June 2, 2012 20:25
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tugberkugurlu/2859825 to your computer and use it in GitHub Desktop.
Save tugberkugurlu/2859825 to your computer and use it in GitHub Desktop.
public class HomeController : Controller {
[AsyncTimeout(1000)]
[HandleError(ExceptionType = typeof(TimeoutException), View = "TimeoutError")]
public async Task<ActionResult> Foo(CancellationToken cancellationToken) {
using (HttpClient client = new HttpClient()) {
await client.GetStringAsync("http://localhost:2098/Home/Wait", cancellationToken);
}
return View();
}
public string Wait() {
Thread.Sleep(3000);
return "Foo";
}
}
public static class HttpClientExtensions {
public static Task<string> GetStringAsync(this HttpClient httpClient, Uri requestUri, CancellationToken cancellationToken) {
return httpClient.GetContentAsync<string>(
requestUri, HttpCompletionOption.ResponseContentRead, string.Empty,
(HttpContent content) => content.ReadAsStringAsync(), cancellationToken);
}
public static Task<string> GetStringAsync(this HttpClient httpClient, string requestUri, CancellationToken cancellationToken) {
return httpClient.GetContentAsync<string>(
requestUri, HttpCompletionOption.ResponseContentRead, string.Empty,
(HttpContent content) => content.ReadAsStringAsync(), cancellationToken);
}
public static Task<T> GetContentAsync<T>(this HttpClient httpClient, string requestUri, HttpCompletionOption completionOption, T defaultValue, Func<HttpContent, Task<T>> readAs) {
return httpClient.GetContentAsync<T>(requestUri, completionOption, defaultValue, readAs, CancellationToken.None);
}
public static Task<T> GetContentAsync<T>(this HttpClient httpClient, string requestUri, HttpCompletionOption completionOption, T defaultValue, Func<HttpContent, Task<T>> readAs, CancellationToken cancellationToken) {
return httpClient.GetContentAsync<T>(createUri(requestUri), completionOption, defaultValue, readAs, cancellationToken);
}
public static Task<T> GetContentAsync<T>(this HttpClient httpClient, Uri requestUri, HttpCompletionOption completionOption, T defaultValue, Func<HttpContent, Task<T>> readAs) {
return httpClient.GetContentAsync<T>(requestUri, completionOption, defaultValue, readAs, CancellationToken.None);
}
public static Task<T> GetContentAsync<T>(this HttpClient httpClient, Uri requestUri, HttpCompletionOption completionOption, T defaultValue, Func<HttpContent, Task<T>> readAs, CancellationToken cancellationToken) {
TaskCompletionSource<T> tcs = new TaskCompletionSource<T>();
httpClient.GetAsync(requestUri, completionOption, cancellationToken).ContinueWithStandard(requestTask => {
if (HandleRequestFaultsAndCancelation<T>(requestTask, tcs)) {
return;
}
HttpResponseMessage result = requestTask.Result;
if (result.Content == null) {
tcs.TrySetResult(defaultValue);
return;
}
try {
readAs(result.Content).ContinueWithStandard(contentTask => {
if (!HandleFaultsAndCancelation<T>(contentTask, tcs)) {
tcs.TrySetResult(contentTask.Result);
}
});
}
catch (Exception exception) {
tcs.TrySetException(exception);
}
});
return tcs.Task;
}
// System.Net.Http.HttpClient
private static Uri createUri(string uri) {
if (string.IsNullOrEmpty(uri)) {
return null;
}
return new Uri(uri, UriKind.RelativeOrAbsolute);
}
// System.Net.Http.HttpClient
private static bool HandleRequestFaultsAndCancelation<T>(Task<HttpResponseMessage> task, TaskCompletionSource<T> tcs) {
if (HandleFaultsAndCancelation<T>(task, tcs)) {
return true;
}
HttpResponseMessage result = task.Result;
if (!result.IsSuccessStatusCode) {
if (result.Content != null) {
result.Content.Dispose();
}
tcs.TrySetException(
new HttpRequestException(
string.Format(
CultureInfo.InvariantCulture,
"Request is not a success",
new object[] {
(int)result.StatusCode, result.ReasonPhrase })));
return true;
}
return false;
}
// System.Net.Http.HttpUtilities
private static bool HandleFaultsAndCancelation<T>(Task task, TaskCompletionSource<T> tcs) {
if (task.IsFaulted) {
tcs.TrySetException(task.Exception.GetBaseException());
return true;
}
if (task.IsCanceled) {
tcs.TrySetCanceled();
return true;
}
return false;
}
}
public static class TaskExtensions {
internal static Task ContinueWithStandard<T>(this Task<T> task, Action<Task<T>> continuation) {
return task.ContinueWith(continuation, CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment