使用 Windows.Web.Http.HttpClient 类 PATCH 异步请求

Posted

技术标签:

【中文标题】使用 Windows.Web.Http.HttpClient 类 PATCH 异步请求【英文标题】:PATCH Async requests with Windows.Web.Http.HttpClient class 【发布时间】:2014-11-30 20:41:44 【问题描述】:

我需要使用Windows.Web.Http.HttpClient 类执行PATCH 请求,并且没有关于如何执行此操作的官方文档。我该怎么做?

【问题讨论】:

【参考方案1】:

我找到了如何使用之前的 System.Net.Http.HttpClient 类 here 来执行“自定义”PATCH 请求,然后一直在摆弄直到我让它在 Windows.Web.Http.HttpClient 类中工作,就像这样:

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;

【讨论】:

而不是``` HttpResponseMessage response = new HttpResponseMessage(); ``` 使用 ``` var response = default(HttpResponseMessage); ```【参考方案2】:

更新:请参阅下面的SSX-SL33PY's answer 以获得更好的解决方案,它的作用相同。

您可以编写与扩展方法完全相同的方法,因此您可以直接在 HttpClient 对象上调用它:

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;
   

用法:

var responseMessage = await httpClient.PatchAsync(new Uri("testUri"), httpContent);

【讨论】:

如何传递内容? 你看到第二个参数了吗?尝试这样的事情:HttpContent httpContent = new StringContent("Your JSON-String", Encoding.UTF8, "application/json"); for String-Contents。 如果我错了,请纠正我,但 PATCH 方法意味着您只修改 JSON 中的特定数据。你如何修改,比方说,只是一个产品的名称?如果“你的 JSON 字符串”是指整个 JSON,那么我很困惑。我尝试添加像 HttpContent content = new StringContent("\"name\":\"John Doe\"", Encoding.UTF8, "application/json"); 这样的单个属性,但内容未添加到请求中。【参考方案3】:

我想扩展@alexander-pacha 的答案,并建议在公共库的某处添加以下扩展类。这是否是项目/客户端/框架/...的通用库,您必须自己弄清楚。

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

通过这种方式,您不会在某个静态扩展类中等待和暂停执行,但您可以像处理 PostAsyncPutAsync 调用一样处理它。您还可以使用相同的重载,并让 HttpClient 处理它设计处理的所有内容。

【讨论】:

这看起来很棒。您应该考虑在 .NET Framework 的官方存储库中的 Github 上创建一个 Pull-Request,因为他们欢迎贡献:github.com/dotnet/corefx/blob/master/src/System.Net.Http/src/… 编辑:有人打败了我,它已被添加到您由其他人链接的存储库中。【参考方案4】:

要让它工作,你需要像这样传递内容:

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

【讨论】:

【参考方案5】:

第 1 步:创建一个静态类(我已创建为扩展)

public static class Extention

    public static Task<HttpResponseMessage> PatchAsJsonAsync<T>(this HttpClient 
    client, string requestUri, T value)
    
        var content = new ObjectContent<T>(value, new JsonMediaTypeFormatter());
        var request = new HttpRequestMessage(new HttpMethod("PATCH"), requestUri) 
         Content = content ;

        return client.SendAsync(request);
    

第 2 步:在您的 api 请求中调用此方法

private static HttpClient client = new HttpClient();
var response = Extention.PatchAsJsonAsync<UserUpdateAPIModel>(client, "https://api.go1.com/v2/users/5886043", data);

问题解决了,这里如果是普通的url,你可以自己练习一下

【讨论】:

以上是关于使用 Windows.Web.Http.HttpClient 类 PATCH 异步请求的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)