Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PATCH Async requests with Windows.Web.Http.HttpClient class

I need to do a PATCH request with the Windows.Web.Http.HttpClient class and there is no official documentation on how to do it. How can I do this?

like image 606
Schrödinger's Box Avatar asked Oct 06 '14 14:10

Schrödinger's Box


3 Answers

I found how to do a "custom" PATCH request with the previous System.Net.Http.HttpClient class here, and then fiddled with until I made it work in the Windows.Web.Http.HttpClient class, like so:

public async Task<HttpResponseMessage> PatchAsync(HttpClient client, Uri requestUri, IHttpContent iContent) {
    var method = new HttpMethod("PATCH");

    var request = new HttpRequestMessage(method, requestUri) {
        Content = iContent
    };

    HttpResponseMessage response = new HttpResponseMessage();
    // In case you want to set a timeout
    //CancellationToken cancellationToken = new CancellationTokenSource(60).Token;

    try {
         response = await client.SendRequestAsync(request);
         // If you want to use the timeout you set
         //response = await client.SendRequestAsync(request).AsTask(cancellationToken);
    } catch(TaskCanceledException e) {
        Debug.WriteLine("ERROR: " + e.ToString());
    }

    return response;
}
like image 177
Schrödinger's Box Avatar answered Oct 15 '22 12:10

Schrödinger's Box


Update: See SSX-SL33PY's answer below for an even better solution, that does the same thing.

You can write the very same method as extension method, so you can invoke it directly on the HttpClient object:

public static class HttpClientExtensions
{
   public static async Task<HttpResponseMessage> PatchAsync(this HttpClient client, Uri requestUri, HttpContent iContent)
   {
       var method = new HttpMethod("PATCH");
       var request = new HttpRequestMessage(method, requestUri)
       {
           Content = iContent
       };

       HttpResponseMessage response = new HttpResponseMessage();
       try
       {
           response = await client.SendAsync(request);
       }
       catch (TaskCanceledException e)
       {
           Debug.WriteLine("ERROR: " + e.ToString());
       }

       return response;
   }
}

Usage:

var responseMessage = await httpClient.PatchAsync(new Uri("testUri"), httpContent);
like image 59
Alexander Pacha Avatar answered Oct 15 '22 12:10

Alexander Pacha


I'd like to extend on @alexander-pacha's answer and suggest adding following extension class somewhere in a common library. Wether this be a common library for a project / client / framework/... is something you'll have to make out on your own.

    public static class HttpClientExtensions
    {
        /// <summary>
        /// Send a PATCH request to the specified Uri as an asynchronous operation.
        /// </summary>
        /// 
        /// <returns>
        /// Returns <see cref="T:System.Threading.Tasks.Task`1"/>.The task object representing the asynchronous operation.
        /// </returns>
        /// <param name="client">The instantiated Http Client <see cref="HttpClient"/></param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="content">The HTTP request content sent to the server.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="client"/> was null.</exception>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="requestUri"/> was null.</exception>
        public static Task<HttpResponseMessage> PatchAsync(this HttpClient client, string requestUri, HttpContent content)
        {
            return client.PatchAsync(CreateUri(requestUri), content);
        }

        /// <summary>
        /// Send a PATCH request to the specified Uri as an asynchronous operation.
        /// </summary>
        /// 
        /// <returns>
        /// Returns <see cref="T:System.Threading.Tasks.Task`1"/>.The task object representing the asynchronous operation.
        /// </returns>
        /// <param name="client">The instantiated Http Client <see cref="HttpClient"/></param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="content">The HTTP request content sent to the server.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="client"/> was null.</exception>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="requestUri"/> was null.</exception>
        public static Task<HttpResponseMessage> PatchAsync(this HttpClient client, Uri requestUri, HttpContent content)
        {
            return client.PatchAsync(requestUri, content, CancellationToken.None);
        }
        /// <summary>
        /// Send a PATCH request with a cancellation token as an asynchronous operation.
        /// </summary>
        /// 
        /// <returns>
        /// Returns <see cref="T:System.Threading.Tasks.Task`1"/>.The task object representing the asynchronous operation.
        /// </returns>
        /// <param name="client">The instantiated Http Client <see cref="HttpClient"/></param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="content">The HTTP request content sent to the server.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="client"/> was null.</exception>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="requestUri"/> was null.</exception>
        public static Task<HttpResponseMessage> PatchAsync(this HttpClient client, string requestUri, HttpContent content, CancellationToken cancellationToken)
        {
            return client.PatchAsync(CreateUri(requestUri), content, cancellationToken);
        }

        /// <summary>
        /// Send a PATCH request with a cancellation token as an asynchronous operation.
        /// </summary>
        /// 
        /// <returns>
        /// Returns <see cref="T:System.Threading.Tasks.Task`1"/>.The task object representing the asynchronous operation.
        /// </returns>
        /// <param name="client">The instantiated Http Client <see cref="HttpClient"/></param>
        /// <param name="requestUri">The Uri the request is sent to.</param>
        /// <param name="content">The HTTP request content sent to the server.</param>
        /// <param name="cancellationToken">A cancellation token that can be used by other objects or threads to receive notice of cancellation.</param>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="client"/> was null.</exception>
        /// <exception cref="T:System.ArgumentNullException">The <paramref name="requestUri"/> was null.</exception>
        public static Task<HttpResponseMessage> PatchAsync(this HttpClient client, Uri requestUri, HttpContent content, CancellationToken cancellationToken)
        {
            return client.SendAsync(new HttpRequestMessage(new HttpMethod("PATCH"), requestUri)
            {
                Content = content
            }, cancellationToken);
        }

        private static Uri CreateUri(string uri)
        {
            return string.IsNullOrEmpty(uri) ? null : new Uri(uri, UriKind.RelativeOrAbsolute);
        }
    }

This way you're not awaiting and holding up execution in some static extension class, but you handle that as if you were really doing a PostAsync or a PutAsync call. You also have the same overloads at your disposal and you're letting the HttpClient handle everything it was designed to handle.

like image 42
Jif Avatar answered Oct 15 '22 13:10

Jif