PATCH Asynchrone Anforderungen mit der Windows.Web.Http.HttpClient-Klasse

75

Ich muss eine PATCHAnfrage mit der Windows.Web.Http.HttpClientKlasse machen und es gibt keine offizielle Dokumentation darüber, wie es geht. Wie kann ich das machen?

Schrödingers Schachtel
quelle

Antworten:

83

Ich fand , wie man eine „custom“ zu tun PATCHAnfrage mit der vorherige System.Net.Http.HttpClientKlasse hier , und dann spielte mit , bis ich machte es in der Arbeit Windows.Web.Http.HttpClientKlasse, etwa 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;
}
Schrödingers Schachtel
quelle
anstelle von `` `HttpResponseMessage response = new HttpResponseMessage (); `` `use` `` var response = default (HttpResponseMessage); `` `
Wilmer
54

Update: Siehe SSX-SL33PY Antwort unten für eine noch bessere Lösung, die die gleiche Sache tut.

Sie können dieselbe Methode wie die Erweiterungsmethode schreiben, um sie direkt im HttpClient-Objekt aufzurufen:

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;
   }
}

Verwendung:

var responseMessage = await httpClient.PatchAsync(new Uri("testUri"), httpContent);
Alexander Pacha
quelle
Wie geben Sie den Inhalt weiter?
Luis Valencia
4
Sie sehen den zweiten Parameter? Versuchen Sie so etwas: HttpContent httpContent = new StringContent("Your JSON-String", Encoding.UTF8, "application/json");für String-Inhalte.
Alexander Pacha
Korrigieren Sie mich, wenn ich falsch liege, aber die PATCH-Methode bedeutet, dass Sie nur bestimmte Daten innerhalb des JSON ändern. Wie ändern Sie beispielsweise nur den Namen eines Produkts? Wenn mit "Your JSON-String" der gesamte JSON gemeint ist, bin ich verwirrt. Ich habe versucht, eine einzelne Eigenschaft wie hinzuzufügen, HttpContent content = new StringContent("{\"name\":\"John Doe\"", Encoding.UTF8, "application/json");aber der Inhalt wird der Anforderung nicht hinzugefügt.
Caloyski
38

Ich möchte die Antwort von @ alexander-pacha erweitern und vorschlagen, die folgende Erweiterungsklasse irgendwo in einer gemeinsamen Bibliothek hinzuzufügen. Ob dies eine gemeinsame Bibliothek für ein Projekt / einen Client / ein Framework / ... ist, müssen Sie selbst herausfinden.

    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);
        }
    }

Auf diese Weise warten Sie nicht auf die Ausführung in einer statischen Erweiterungsklasse und halten sie auf, aber Sie behandeln dies so, als würden Sie wirklich einen PostAsyncoder einen PutAsyncAnruf tätigen. Sie haben auch die gleichen Überlastungen zur Verfügung und lassen den HttpClientGriff alles handhaben, wofür er entwickelt wurde.

SSX-SL33PY
quelle
3
Das sieht gut aus. Sie sollten in Betracht ziehen, eine Pull-Request damit auf Github im offiziellen Repository von .NET Framework zu erstellen, da sie Beiträge begrüßen: github.com/dotnet/corefx/blob/master/src/System.Net.Http/src/…
Alexander Pacha
Bearbeiten: Jemand hat mich geschlagen, es wurde dem Repo hinzugefügt, das Sie von jemand anderem verlinkt haben.
SSX-SL33PY
5

Damit es funktioniert, müssen Sie den Inhalt folgendermaßen übergeben:

HttpContent httpContent = new StringContent("Your JSON-String", Encoding.UTF8, "application/json-patch+json");
Claire G.
quelle