HttpClient PostAsJsonAsync 在 .NET Core 和 Classic .NET 中的行为不同

2023-11-21

我在 IIS 中托管一个经典 .NET WebAPI 端点,它接受上传文档的 POST 请求。

我创建了两个控制台应用程序,用于连接到 WebAPI 并上传文档:一个是经典的 .NET (v4.6.2) 控制台应用程序,另一个是 .NET Core 控制台应用程序。代码是完全相同的,但服务对每个的响应不同。 WebAPI 似乎无法读取 .NET Core POST 请求的请求正文,但可以使用经典 .NET POST 请求来读取请求正文。

我有什么遗漏的吗?

WebAPI端点

http://localhost/WebApi/Library/api/Documents

[Route("api/Documents")]
public class DocumentsController : ApiController
{
    [HttpPost()]
    public void Create([FromBody] Document document)
    {
        if (document == null)
        {
            Debug.WriteLine("Posted document is null.");
        }
        else
        {
            Debug.WriteLine($"Document text: {document.Text}");
        }
    }
}

public class Document
{
    public string Text { get; set; }
}

.NET Core/经典 .NET 控制台应用程序

class Program
{
    static void Main(string[] args)
    {
        RunAsAsync().Wait();
    }

    static async Task RunAsAsync()
    {
        var httpClient = new HttpClient()
        {
            BaseAddress = new Uri("http://api-localhost"),
        };

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

        await httpClient.PostAsJsonAsync("/library/api/documents", new Document() { Text = "The document text" });
    }
}

public class Document
{
    public string Text { get; set; }
}

事情是这样的:当我将调试器附加到 WebAPI 时,会输出以下内容:

来自经典 .NET 控制台应用程序的 POST 请求:

文档文本:文档文本

来自 .NET Core 控制台应用程序的 POST 请求:

发布的文档为空。

我无法解释行为上的差异。

一些额外的信息:

.NET Core 控制台应用程序的project.json 文件:

{
  "version": "1.0.0-*",
  "buildOptions": {
    "emitEntryPoint": true
  },

  "dependencies": {
    "Microsoft.AspNet.WebApi.Client": "5.2.3",
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.0.1"
    },
    "System.Net.Http": "4.3.0",
    "System.Runtime.Serialization.Xml": "4.3.0"

  },

  "frameworks": {
    "netcoreapp1.0": {
      "imports": [
        "dnxcore50",
        "portable-net451+win8"
      ]
    }
  }
}

经典.NET packages.config:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net462" />
  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net462" />
</packages>

来自 Fiddler 的原始 .NET Core 帖子:

POST http://localhost/library/api/documents HTTP/1.1
Transfer-Encoding: chunked
Content-Type: application/json; charset=utf-8
Accept: application/json
Accept-Encoding: gzip, deflate
Connection: Keep-Alive
Host: api-localhost

1c
{"Text":"The document text"}
0

这是原始的经典 .NET POST:

POST http://localhost/library/api/documents HTTP/1.1 Accept:
application/json Content-Type: application/json; charset=utf-8 Host:
api-localhost Content-Length: 28 Expect: 100-continue Connection:
Keep-Alive

{"Text":"The document text"}

在我看来,奇怪的“1c”和“0”可能与我的问题有关。但我不明白他们如何/为什么应该在那里。

更新:一些观察

我还创建了一个非常基本的 .NET Core WebAPI 端点,其本质上与上面描述的经典 .NET 执行相同的操作。事实证明,这能够接受来自两个控制台应用程序的 POST 请求。

我还为 .NET Core 创建了第三个控制台应用程序,其中我跳过使用 PostAsJsonAsync,而是将 PostAsync 与 StringContent 结合使用:

public class Program
{
    static void Main(string[] args)
    {
        RunAsAsync().Wait();
    }

    static async Task RunAsAsync()
    {
        var httpClient = new HttpClient()
        {
            BaseAddress = new Uri("http://localhost"),
        };

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

        var document = new Document() { Text = "The document text." };

        var content = JsonConvert.SerializeObject(document);

        HttpContent httpContent = new StringContent(content, Encoding.UTF8, "application/json");

        await httpClient.PostAsync("/library2/api/documents", httpContent);
    }
}

public class Document
{
    public string Text { get; set; }
}

在 /library/... 和 /library2/... 之间交替,来自此应用程序的 POST 请求会被 .NET Core 和 Classic .NET WebAPI 接受。

Summary

在服务器端我有两个 WebAPI

  • /library - 经典.NET
  • /library2 - .NET Core

在客户端,我有同一控制台应用程序的三个变体:

  • ConsoleApplication1 - Classic .NET using PostAsJsonAsync
    • 与两种 WebAPI 都能正常工作
  • ConsoleApp1 - .NET Core using PostAsJsonAsync
    • 使用 /library(经典 .NET)失败,使用 /library2(.NET Core)运行良好
  • ConsoleApp2 - .NET Core using PostAsync
    • 与两种 WebAPI 都能正常工作

这里明显的解决方法是never在 .NET Core 客户端应用程序中使用 PostAsJsonAsync,这很遗憾,因为它确实很方便。 :(

-S


根本问题似乎是 Classic .NET WebAPI 无法在当前最新版本 (v5.2.3) 中处理分块请求。我假设这是一个错误,并作为暂时降级到 v5.0 的解决方法。

特别感谢@Developer 提供的有用意见。

-S

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

HttpClient PostAsJsonAsync 在 .NET Core 和 Classic .NET 中的行为不同 的相关文章

  • 将集合项复制到 .NET 中的另一个集合

    在 NET VB 中 如何获取一个集合中的所有项目 并将它们添加到第二个集合中 而不丢失第二个集合中预先存在的项目 我正在寻找比这更有效的东西 For Each item As Host In hostCollection1 hostCol
  • Web Api - Swagger 文档错误 500

    当我访问 swagger url 时 http localhost 28483 swagger ui index 它会生成此错误 500 undefined http localhost 28483 swagger docs v1 有任何想
  • 如果我使用带有表单身份验证的 WCF,php 或 java 客户端将如何进行身份验证?

    我有一个通用的概念验证 WCF 服务 它使用表单身份验证来保护访问 当我的客户端是 NET 时 一切都很好 vb 代码如下 Dim client As SupplierServiceClient New SupplierServiceCli
  • 使用 TFS API 在单个查询中检索工作项及其链接的工作项

    有谁知道是否可以检索工作项目及其列表链接的工作项使用 TFS API Web 服务从 TFS 进行一趟 目前 我们必须对第一次调用期间进行的每个工作项进行第二次调用 并且引入了性能问题 如果这不可能 是否有办法查看链接工作项的类型而不检索它
  • DateTime.Ticks 没有 100 ns 的分辨率? [复制]

    这个问题在这里已经有答案了 可能的重复 C DateTime Now 精度 https stackoverflow com questions 2143140 c sharp datetime now precision SO 有一些关于
  • 使用 HttpClient 从 webapi 消费 xml

    我使用 WebClient 从 Restfull 服务 net web api 获取 Xml 对象 一切都运行良好 using WebClient client new WebClient client Encoding UTF8Encod
  • ASP.NET Web Api 的事件发布者

    我已经开始使用微服务 我需要创建一个事件发布机制 我计划使用 Amazon SQS 这个想法很简单 我将事件存储在与聚合相同的事务中的数据库中 如果用户更改他的电子邮件 事件UserChangedEmail将被存储在数据库中 我还有事件处理
  • 在Python3.6中调用C#代码

    由于完全不了解 C 编码 我希望在我的 python 代码中调用 C 函数 我知道有很多关于同一问题的问答 但由于一些奇怪的原因 我无法从示例 python 模块导入简单的 c 类库 以下是我所做的事情 C 类库设置 我使用的是 VS 20
  • *.tlb 文件在运行时使用过吗?

    我正在开发一个通过 COM 互操作公开一些 NET API 的产品 作为构建的一部分 我们为所有此类程序集生成 tlb 文件 并将它们作为单独 SDK 包的一部分提供 我们的客户可以在我们的产品之上安装 SDK 并创建使用我们的 COM A
  • 在 ASP.NET 中将事件冒泡为父级

    我已经说过 ASP NET 中的层次结构 page user control 1 user control 2 control 3 我想要做的是 当控件 3 它可以是任何类型的控件 我一般都想这样做 让用户用它做一些触发回发的事情时 它会向
  • “反序列化操作回复消息正文时出错...” - 对于我调用的每个方法

    我正在尝试为我们的波兰拍卖服务 Allegro 创建非常简单的客户端应用程序 他们提供 SOAP 架构中的 API 问题是 每次我尝试调用任何方法时 我都会收到 反序列化操作 方法名称 的回复消息正文时出错 一般来说 我对网络服务不熟悉 所
  • 在.NET Core RC2中构建.exe文件

    每次我使用新的 NET Core RC2 模板构建项目时not提供了一个可运行的 EXE文件 如果我按 F5 来调试我的控制台应用程序 它可以通过 C Program Files dotnet dotnet exe 应用 如果我使用 dot
  • 是否需要连续编号?

    我正在开发一个 winform NET 应用程序 其中包括订单 发票 服务订单 票务等 这些实体在对其 ID 进行编号时是否必须按顺序排列 国际海事组织没有 以一个订单为例 它只有通过业务层才有效 在此过程中 可能已经创建了另一个订单 批准
  • 绑定 WebForms TextBox 上的千位分隔符的逗号

    我正在尝试如下格式化数据绑定值 但我不断得到一个空格作为千 位分隔符 即显示的文本始终是 12 340 00 而它应该是 12 340 00 我缺少什么
  • 在 C++/CLI 中实现 IEnumerable

    我在实施时遇到问题IEnumerable
  • 使用.NET 访问Windows 注册表?

    我发现一个奇怪的行为 NET http en wikipedia org wiki NET Framework模块访问Windows注册表 http en wikipedia org wiki Windows Registry使用Regis
  • 公共交通错误队列正在消耗,但仍然不为空

    我正在使用 Mastransit 3 5 0 和 RabbitMq 如果队列消费者抛出异常 则默认由 MoveExceptionToTransportFilter 处理异常并移至 error 队列 对于 error 队列 我有单独的消费者
  • C# - OPC-UA 服务器应用程序尚未在 Linux 计算机中创建 PKI 证书

    当我跑步时OPC UA serverWindows 机器中的 C 应用程序 然后 OPC UA 服务器已创建证书路径C ProgramData OPC Foundation pki own 并在此路径中生成一些证书 但是当我在中安装 OPC
  • 关于 .net core 的 csproj 格式的完整文档在哪里?

    是否有关于 net core 项目的 csproj 格式的完整文档 我一直在寻找一种在构建之前复制文件的方法 经过一番搜索后 我找到了解决方案 但我找不到这方面的文档 它会覆盖文件吗 有没有额外的选择
  • 单元测试验证失败

    我正在运行我的单元测试PostMyModel路线 然而 在PostMyModel 我用的是线Validate

随机推荐