From 7eaa57a10afdfc93c4f4816155381fb778f87a7a Mon Sep 17 00:00:00 2001 From: Todd Date: Mon, 14 Dec 2020 12:57:44 -0600 Subject: [PATCH] #580 CapturedMultipartContent shouldn't lose parts when sent --- Test/Flurl.Test/Http/MultipartTests.cs | 35 +++++++++++++------ .../Content/CapturedMultipartContent.cs | 7 +++- 2 files changed, 30 insertions(+), 12 deletions(-) diff --git a/Test/Flurl.Test/Http/MultipartTests.cs b/Test/Flurl.Test/Http/MultipartTests.cs index 53083ec4..500d4266 100644 --- a/Test/Flurl.Test/Http/MultipartTests.cs +++ b/Test/Flurl.Test/Http/MultipartTests.cs @@ -5,7 +5,9 @@ using System.Net.Http; using System.Text; using System.Threading.Tasks; +using Flurl.Http; using Flurl.Http.Content; +using Flurl.Http.Testing; using NUnit.Framework; namespace Flurl.Test.Http @@ -13,8 +15,8 @@ namespace Flurl.Test.Http [TestFixture, Parallelizable] public class MultipartTests { - [Test] - public void can_build_multipart_content() { + [Test] + public async Task can_build_and_send_multipart_content() { var content = new CapturedMultipartContent() .AddString("string", "foo") .AddString("string2", "bar", "text/blah") @@ -24,15 +26,26 @@ public void can_build_multipart_content() { .AddJson("json", new { foo = "bar" }) .AddUrlEncoded("urlEnc", new { fizz = "buzz" }); - Assert.AreEqual(8, content.Parts.Length); - AssertStringPart(content.Parts[0], "string", "foo", null); - AssertStringPart(content.Parts[1], "string2", "bar", "text/blah"); - AssertStringPart(content.Parts[2], "part1", "1", null); - AssertStringPart(content.Parts[3], "part2", "2", null); - AssertFilePart(content.Parts[4], "file1", "image1.jpg", "image/jpeg"); - AssertFilePart(content.Parts[5], "file2", "new-name.jpg", "image/jpeg"); - AssertStringPart(content.Parts[6], "json", "{\"foo\":\"bar\"}", "application/json; charset=UTF-8"); - AssertStringPart(content.Parts[7], "urlEnc", "fizz=buzz", "application/x-www-form-urlencoded"); + void AssertAll() { + Assert.AreEqual(8, content.Parts.Count); + AssertStringPart(content.Parts[0], "string", "foo", null); + AssertStringPart(content.Parts[1], "string2", "bar", "text/blah"); + AssertStringPart(content.Parts[2], "part1", "1", null); + AssertStringPart(content.Parts[3], "part2", "2", null); + AssertFilePart(content.Parts[4], "file1", "image1.jpg", "image/jpeg"); + AssertFilePart(content.Parts[5], "file2", "new-name.jpg", "image/jpeg"); + AssertStringPart(content.Parts[6], "json", "{\"foo\":\"bar\"}", "application/json; charset=UTF-8"); + AssertStringPart(content.Parts[7], "urlEnc", "fizz=buzz", "application/x-www-form-urlencoded"); + } + + // Assert before and after sending a request. MultipartContent clears the parts collection after request is sent; + // CapturedMultipartContent (as the name implies) should preserve it (#580) + + AssertAll(); + using (var test = new HttpTest()) { + await "https://upload.com".PostAsync(content); + } + AssertAll(); } private void AssertStringPart(HttpContent part, string name, string content, string contentType) { diff --git a/src/Flurl.Http/Content/CapturedMultipartContent.cs b/src/Flurl.Http/Content/CapturedMultipartContent.cs index 79117beb..71a792a7 100644 --- a/src/Flurl.Http/Content/CapturedMultipartContent.cs +++ b/src/Flurl.Http/Content/CapturedMultipartContent.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Net.Http; @@ -15,11 +16,12 @@ namespace Flurl.Http.Content public class CapturedMultipartContent : MultipartContent { private readonly FlurlHttpSettings _settings; + private readonly List _capturedParts = new List(); /// /// Gets an array of HttpContent objects that make up the parts of the multipart request. /// - public HttpContent[] Parts => this.ToArray(); + public IReadOnlyList Parts => _capturedParts; /// /// Initializes a new instance of the class. @@ -122,6 +124,9 @@ private CapturedMultipartContent AddInternal(string name, HttpContent content, s FileName = fileName, FileNameStar = fileName }; + // The base class's collection of parts is cleared on Dispose, which isn't exactly in the spirit of "Captured", + // which is why we need to add it to this other collection. (#580) + _capturedParts.Add(content); base.Add(content); return this; }