jgiacomini / Tiny.RestClient

Simpliest Fluent REST client for .NET
MIT License
210 stars 30 forks source link

Post MultiPart Form with file or bytes throws on HttpContent.Dispose #93

Closed xixilive closed 4 years ago

xixilive commented 5 years ago

I am using a release version after 8e16d65f13319e39490709a9e6a044f9b2a29acd, which fixed the 'PATCH' issue.

When I post bytes data to my server, T.RC throws exception. And if I rewrite my request with Builtin HttpClient, it works fine.

var req = client.Post("upload").AddHeader("Authorization", "TOKEN_STRING") as IRequest;
var res = await req.AsMultiPartFromDataRequest()
    .AddByteArray(new byte[]{0x11}, "file", "picture.png", "image/jpg")
    .ExecuteAsHttpResponseMessageAsync();

throws following exception.

Exception: System.NullReferenceException: Object reference not set to an instance of an object
  at System.Net.Http.MultipartContent.Dispose (System.Boolean disposing) [0x00003] in <xxx>:0 
  at System.Net.Http.HttpContent.Dispose () [0x00000] in <xxx>:0 
  at Tiny.RestClient.TinyRestClient+<ExecuteAsHttpResponseMessageResultAsync>d__25.MoveNext () [0x00164] in <xxx>:0 

HttpClient implementation works as expected.

ByteArrayContent content = new ByteArrayContent(new byte[]{0x11});
content.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpg");

MultipartFormDataContent formData = new MultipartFormDataContent
{
    { content,"file","picture.jpg" }
};

HttpClient http = new HttpClient { BaseAddress = new Uri("https://api.server.com") };
http.DefaultRequestHeaders.Add("Accept", "application/json");
http.DefaultRequestHeaders.Add("Authorization","TOKEN");

try
{
    return await http.PostAsync("/upload", formData);
}
finally
{
    formData.Dispose();
    content.Dispose();
    http.Dispose();
}
jgiacomini commented 5 years ago

Hello, I will try to reproduce the bug with the current version and fix it.

jgiacomini commented 5 years ago

I try to reproduce the bug in my unit test => https://github.com/jgiacomini/Tiny.RestClient/blob/a5729794a88601f89dde23da8015a5666684aae4/Tests/Tiny.RestClient.Tests/MultiPartTests.cs#L65

But I can't reproduce it. Maybe I miss something.

jgiacomini commented 5 years ago

If you don't read the response can you try like that :

 var req = client.PostRequest("MultiPart/Test").AddHeader("Authorization", "TOKEN_STRING") as IRequest;
            var res = await req.AsMultiPartFromDataRequest()
                .AddByteArray(new byte[] { 0x11 }, "file", "picture.png", "image/jpg")
                .ExecuteAsync();
xixilive commented 5 years ago

I've tried what i can. IMPORTANT: My environment is Unity3D C# Script(net_standard 2.0 & .NET framework 4.x). It seems something was disposed/GC in unexpected during async processing.

Thank you so much, I will retry this with your source code after my project delivered.