Search code examples
c#asp.net-coreserializationblazorhttpcontent

Can not deserialize HttpContent from POST request


I am trying to send a POST request to a server.The request gets into the Middleware's Invoke method.

However the Content is always null, no matter the type of the object.

Sender

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

Server

The server has no service defined ,just a plain middleware that responds on a route. ( The request gets in the Invoke method ! )

Startup

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

Middleware

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

I have checked my serialization and the object is serialized just fine.

Despite this I am always getting a null on the other side.

P.S

I have also tried using no middleware just a plain delegate like below :

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

Even without a dedicated middleware the problem persists.

The problem is not the middleware , its the request that is serialized correctly in the client, sent to the server ,and somehow its body shows up as null.

I would've understood if it failed to deserialize the object , but the HttpContext.Request.Body as a string is received null and its length is null !!


Solution

  • Not sure what's exactly wrong with your code, but this works:

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

    Running this in chrome dev tools:

    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)
    

    Yields the following in the browser:

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