使用 HttpClient PostAsJsonAsync 在 ASP.NET Core 中发送 HTTP POST 消息

Posted

技术标签:

【中文标题】使用 HttpClient PostAsJsonAsync 在 ASP.NET Core 中发送 HTTP POST 消息【英文标题】:Send HTTP POST message in ASP.NET Core using HttpClient PostAsJsonAsync 【发布时间】:2016-06-10 14:12:11 【问题描述】:

我想发送动态对象

new  x = 1, y = 2 ;

作为 HTTP POST 消息的正文。所以我试着写

var client = new HttpClient();

但我找不到方法

client.PostAsJsonAsync()

所以我尝试将 Microsoft.AspNetCore.Http.Extensions 包添加到 project.json 并添加

using Microsoft.AspNetCore.Http.Extensions; 

使用子句。但是它对我没有帮助。

那么在 ASP.NET Core 中使用 JSON 正文发送 POST 请求的最简单方法是什么?

【问题讨论】:

想知道为什么这篇文章不包含 POST docs.microsoft.com/en-us/dotnet/csharp/tutorials/… 的示例 【参考方案1】:

您应该添加对“Microsoft.AspNet.WebApi.Client”包的引用(请阅读this article 以获取示例)。

无需任何额外扩展,您可以使用标准的PostAsync 方法:

client.PostAsync(uri, new StringContent(jsonInString, Encoding.UTF8, "application/json"));

你可以通过调用JsonConvert.SerializeObject(<your object>);获得jsonInString的值

【讨论】:

但是 Microsoft.AspNet.WebApi.Client 看起来不像 ASP.NET Core RC2 库。而第二种方式真的是代码重复太多了(( @Rem 你为什么不创建一个HttpClient 扩展方法(PostAsJsonAsync)来使用第二种方式。它使您可以避免代码重复。 当然。但我问了这个问题,以便找出我是否遗漏了什么。我不敢相信它还没有在 Core 中实现! 这个库不是核心/.net 标准库,我认为 System.Net.Http.Formatting 还没有被移植 这适用于 .NET Core 2.2 中的 IHttpClientFactory 从 nuget 包 Microsoft.Extensions.Http 创建的 HttpClient。但是,您如何做到这一点,但添加诸如授权密钥之类的标头。【参考方案2】:

我使用这个类:

public class JsonContent : StringContent

    public JsonContent(object obj) :
        base(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json")
     

使用示例:

new HttpClient().PostAsync("http://...", new JsonContent(new  x = 1, y = 2 ));

【讨论】:

为什么不用扩展方法? public static class JsonContent public Task> PostAsJSonAsync(this HttpClient client, object toSerializeAsJson) ... 我喜欢 JsonContent 类方法 这是否设置了Content-Length: HTTP 标头? @VyacheslavNapadovsky 它取决于HttpClient 设置,例如如果一组client.DefaultRequestHeaders.TransferEncodingChunked = true Content-Length 标题不会被设置,而Transfer-Encoding: chunked 将被设置。但是,如果创建像var client = new HttpClient(); 这样的客户端,则默认情况下会为此内容类设置标题Content-Length【参考方案3】:

我将添加到已接受的答案中,您还希望将 Accept 标头添加到 httpClient

httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

【讨论】:

【参考方案4】:

Microsoft 现在建议使用 IHttpClientFactory 具有以下好处:

为命名和配置逻辑提供一个中心位置 HttpClient 实例。例如,一个名为 github 的客户端可能是 注册并配置为访问 GitHub。默认客户端可以是 注册了一般访问权限。 通过委托处理程序编码传出中间件的概念 在HttpClient。为基于 Polly 的中间件提供扩展以采用 在HttpClient 中委派处理程序的优势。 管理底层证券的池化和生命周期 HttpClientMessageHandler 实例。自动管理避免 手动时发生的常见 DNS(域名系统)问题 管理 HttpClient 生命周期。 为所有请求添加可配置的日志记录体验(通过ILogger) 通过工厂创建的客户端发送。

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1

设置:

public class Startup

    public Startup(IConfiguration configuration)
    
        Configuration = configuration;
    

    public IConfiguration Configuration  get; 

    public void ConfigureServices(IServiceCollection services)
    
        services.AddHttpClient();
        // Remaining code deleted for brevity.

POST 示例:

public class BasicUsageModel : PageModel

    private readonly IHttpClientFactory _clientFactory;

    public BasicUsageModel(IHttpClientFactory clientFactory)
    
        _clientFactory = clientFactory;
    
    
    public async Task CreateItemAsync(TodoItem todoItem)
    
        var todoItemJson = new StringContent(
            JsonSerializer.Serialize(todoItem, _jsonSerializerOptions),
            Encoding.UTF8,
            "application/json");
            
        var httpClient = _clientFactory.CreateClient();
        
        using var httpResponse =
            await httpClient.PostAsync("/api/TodoItems", todoItemJson);
    
        httpResponse.EnsureSuccessStatusCode();
    

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-3.1#make-post-put-and-delete-requests

【讨论】:

_jsonSerializerOptions 部分是什么?你知道是否需要设置任何选项吗? @Lukas 请参见此处:docs.microsoft.com/en-us/dotnet/standard/serialization/… Microsoft 在他们的示例代码中包含它,但尝试不使用它,看看会发生什么。 :)【参考方案5】:

如果您使用的是 .NET 5 或更高版本,则可以(并且应该)使用来自 System.Net.Http.Json 的 PostAsJsonAsync 扩展方法:

httpClient.PostAsJsonAsync(url, new  
    x = 1, 
    y = 2 
);

如果您使用的是旧版本的.NET Core,您可以自己实现扩展功能:

public static class HttpClientExtensions

    public static Task<HttpResponseMessage> PostJsonAsync(this HttpClient httpClient, string url, object body)
    
        var bodyJson = JsonSerializer.Serialize(body);
        var stringContent = new StringContent(bodyJson, Encoding.UTF8, "application/json");
        return httpClient.PostAsync(url, stringContent);
    

【讨论】:

【参考方案6】:

你说得对,这早就在 .NET Core 中实现了。

在撰写本文时(2019 年 9 月),NuGet 3.x+ 的 project.json 文件已被 PackageReference 取代(如 https://docs.microsoft.com/en-us/nuget/archive/project-json 所述)。

要访问HttpClient 类的*Async 方法,您的.csproj 文件必须正确配置。

在纯文本编辑器中打开您的.csproj 文件,并确保第一行是&lt;Project Sdk="Microsoft.NET.Sdk.Web"&gt; (正如https://docs.microsoft.com/en-us/dotnet/core/tools/project-json-to-csproj#the-csproj-format 指出的那样)。

要访问HttpClient 类的*Async 方法,您还需要在.csproj 文件中包含正确的包引用,如下所示:

<ItemGroup>
    <!-- ... -->
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <!-- ... -->
</ItemGroup>

(见https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#adding-a-packagereference。 另外:我们建议面向 ASP.NET Core 2.1 及更高版本的应用程序使用 Microsoft.AspNetCore.App 元包,https://docs.microsoft.com/en-us/aspnet/core/fundamentals/metapackage)

PostAsJsonAsyncReadAsAsyncPutAsJsonAsyncDeleteAsync 等方法现在应该可以开箱即用了。 (不需要 using 指令。)

更新: .NET Core 3.0 不再需要 PackageReference 标记。

【讨论】:

我无法让 PostAsJsonAsync 与 .NET Core 3.1 一起使用。谢谢

以上是关于使用 HttpClient PostAsJsonAsync 在 ASP.NET Core 中发送 HTTP POST 消息的主要内容,如果未能解决你的问题,请参考以下文章

HttpClient的使用

HttpClient使用详解

HttpClient使用笔记

HttpClient介绍和简单使用流程

HttpClient使用详解

使用 HttpClient 写入正文请求