【问题标题】:Can not deserialize HttpContent from POST request无法从 POST 请求反序列化 HttpContent
【发布时间】:2019-06-27 01:39:37
【问题描述】:

我正在尝试向服务器发送POST 请求。该请求进入Middleware 的Invoke 方法。

但是Content 始终为空,无论对象的类型如何。

发件人

public async Task<string> RunTestAsync(string request)
{
    try
    {
        var content = new StringContent(JsonConvert.SerializeObject(request),Encoding.UTF8,"application/json");

       var response=await this.client.PostAsync("http://localhost:8500/mat",
                              content);

        string str=await response.Content.ReadAsStringAsync();
        stringdata = JsonConvert.DeserializeObject<string>(str);
        return data;     
    }
    catch (Exception ex)
    {
        Console.WriteLine("Threw in client" + ex.Message);
        throw;
    }
}

服务器

服务器没有定义service,只是一个普通的middleware,它响应route。 (请求进入Invoke 方法!)

启动

 public class Startup
   {
        public void ConfigureServices(IServiceCollection services) {

        }
        public void Configure(IApplicationBuilder app, IHostingEnvironment env) {

            app.UseDeveloperExceptionPage();
            app.UseBlazor<Client.Startup>();

            app.Map("/mid", a => {
                     a.UseMiddleware<Mware>();
                });
            });
        }
   }

中间件

public class Mware
{
    public RequestDelegate next{get;set;}

    public Mware(RequestDelegate del)
    {
      this.next=del;
    }
    public async Task Invoke(HttpContext context)
    {

            using (var sr = new StreamReader(context.Request.Body))
            {
                string content = await sr.ReadToEndAsync();//null ,tried other types too , still null ,and the ContentLength is null too
                var request=JsonConvert.DeserializeObject<string>(content);
                if (request == null)
                {
                    return;
                }
            }
    }
}

我已经检查了我的序列化,并且对象序列化很好。

尽管如此,我总是在另一边收到null。

附言

我也试过不使用middleware,只是一个普通的委托,如下所示:

 public void Configure(IApplicationBuilder app, IHostingEnvironment env) {

        app.UseDeveloperExceptionPage();
        app.UseBlazor<Client.Startup>();

        app.Map("/mid",x=>{
            x.Use(async(context,del)=>{
                using (var sr = new StreamReader(context.Request.Body))
                {
                  string content = await sr.ReadToEndAsync();//null ,tried other types too , still null ,and the ContentLength is null too
                  var request=JsonConvert.DeserializeObject<string>(content);
                  if (request == null)
                  {
                    return;
                  }
                }
        });
    }

即使没有专门的middleware,问题仍然存在。

问题不在于middleware,它的请求在客户端被正确序列化,发送到服务器,不知何故它的body 显示为null。

如果它未能deserialize 对象,我会理解,但HttpContext.Request.Body 作为字符串被接收null 并且它的length 是null !!

【问题讨论】:

  • @BercoviciAdrian string request 在发帖前应该代表什么?控制器上的Invoke 方法是什么?动作还是局部方法?您所问的内容有太多未知数。
  • @BercoviciAdrian 如果您想吸引注意力来解决这个问题,您真的需要将其更新为minimal reproducible example。您最初没有得到它,因为缺少关于如何设置和配置、正在使用的平台版本等的太多细节。
  • @BercoviciAdrian RunTestAsync 中的 string request 参数假设包含什么以及为什么要序列化字符串?
  • 为了帮助我们更好地理解问题,首先,当你调用await this.client.PostAsync("http://localhost:8500/mat", content);时,那么是直接调用中间件的Invoke方法吗?您是否尝试过调试它以实际查看整个 HttpContext 对象以及它包含什么?
  • @BercoviciAdrian 这是一个路由问题。您的中间件在管道中注册较晚,并且正文在到达您的中间件时已经被读取。检查指针在正文流中的位置。我敢肯定它会在最后。这就是为什么您尝试在阅读器中阅读它的原因,但您一无所获。将中间件移到app.UseBlazor&lt;Client.Startup&gt;();之前

标签: c# asp.net-core serialization blazor httpcontent


【解决方案1】:

假设你的请求是 request=@" {"title":"foo","body":"bar","userId":1}";

调用 RunTestAsync(request); 只运行这个 JsonConvert.SerializeObject(request); 我确定它失败了,因为它不可序列化。如果是的话应该是
可序列化类的一些对象

(可序列化类请求)

试试这个 var content = new StringContent(request, Encoding.UTF8, "application/json");

公共异步任务 RunTestAsync(字符串请求) { 尝试 { var content = new StringContent(JsonConvert.SerializeObject(request),Encoding.UTF8,"application/json");

   var response=await this.client.PostAsync("http://localhost:8500/mat",
                          content);

    string str=await response.Content.ReadAsStringAsync();
    stringdata = JsonConvert.DeserializeObject<string>(str);
    return data;     
}
catch (Exception ex)
{
    Console.WriteLine("Threw in client" + ex.Message);
    throw;
}

}

【讨论】:

    【解决方案2】:

    不确定您的代码到底出了什么问题,但这可行:

    public class Startup
    {
      // This method gets called by the runtime. Use this method to add services to the container.
      // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
      public void ConfigureServices(IServiceCollection services)
      {
      }
    
      // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
      public void Configure(IApplicationBuilder app, IHostingEnvironment env)
      {
        if (env.IsDevelopment())
        {
          app.UseDeveloperExceptionPage();
        }
    
        app.Run(async (context) =>
        {
          var request = context.Request;
          var body = request.Body;
    
          request.EnableRewind();
          var buffer = new byte[Convert.ToInt32(request.ContentLength)];
          await request.Body.ReadAsync(buffer, 0, buffer.Length);
          var bodyAsText = Encoding.UTF8.GetString(buffer);
          request.Body = body;
          await context.Response.WriteAsync(bodyAsText);
        });
      }
    }
    

    在 chrome 开发工具中运行:

    fetch('http://localhost:39538', {
      method: 'POST',
      body: JSON.stringify({
        title: 'foo',
        body: 'bar',
        userId: 1
      }),
      headers: {
        'Content-type': 'application/json; charset=UTF-8'
      }
    })
    .then(res => res.json())
    .then(console.log)
    

    在浏览器中生成以下内容:

    {"title":"foo","body":"bar","userId":1}

    【讨论】:

    • 好像是因为Blazor。
    【解决方案3】:

    在您的示例中,客户端代码调用路由“/mat”,但中间件配置在“/mid”。如果你运行的代码有同样的错误,中间件不会被命中,你总是会得到一个空的响应,来自客户端,看起来就像中间件收到null一样。确保您还使用了正确的端口号——我的是 :5000,但它可能会因运行时配置而异。

    您是否使用调试器和断点进行测试?如果没有,我强烈建议尝试。我能够很快找到该错误,因为我在服务器端代码中设置了一个断点,并观察到它没有被命中。如果调试器不是一个选项,请考虑通过抛出异常(而不是简单地返回)来“大声失败”,以使您是否真正达到您认为您正在达到的条件更加明显。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-23
      • 2020-12-08
      • 1970-01-01
      • 2021-03-30
      • 2019-04-07
      • 1970-01-01
      • 2012-06-13
      • 2017-09-18
      相关资源
      最近更新 更多