Reputation: 534
Digging into sending a multipart POST call using flurl to a client's server. Unfortunately, their server is a black box to us. I'm getting a 400 back, with a generic message, so before I bug them, I need to have all my bases covered.
Performing a call like this:
string s = await "https://clientservier.com/cgi-bin/perl-script"
.PostMultipartAsync(mp => mp
.AddString("DisplayActive", "IsDisplayed")
.AddString("ControlTypeHidden", "ALL")
.AddString("QueryHidden", "KEYs")
.AddString("dump_app_trace", "false")
.AddString("db_debug", "false")
.AddString("Get Data", "Get Data"))
.ReceiveString();
If I attach a handler on the BeforeCall event, and look at HttpCall
object, my variables are listed in the Request.Content.Parts
as expected. However, the RequestBody
is null- I'd like to see the string output of the request sent, similar to:
-----------------------------13377838992432022416720759
Content-Disposition: form-data; name="DisplayActive"
IsDisplayed
-----------------------------13377838992432022416720759
Content-Disposition: form-data; name="ControlTypeHidden"
ALL
-----------------------------13377838992432022416720759
Content-Disposition: form-data; name="QueryHidden"
KEYs
-----------------------------13377838992432022416720759
Content-Disposition: form-data; name="Get Data"
Get Data
-----------------------------13377838992432022416720759
Content-Disposition: form-data; name="dump_app_trace"
false
-----------------------------13377838992432022416720759
Content-Disposition: form-data; name="db_debug"
false
-----------------------------13377838992432022416720759--
(Obviously, yes, the boundary would be different, this is just a browser example.) Interestingly, when the call comes back with the 400, the AfterCall event handler does NOT have the above Parts in the object, so I'm wondering if I'm forgetting to do something before making this call.
Upvotes: 1
Views: 578
Reputation: 39319
It's definitely unintuitive that RequestBody
is null in this case. In the HttpClient stack, request bodies are basically read-once streams, making it difficult to read it back as a string if you need to for diagnostics. Flurl basically says, yeah, that's probably a micro-optimization in most typical cases, such as JSON or URL-encoded POSTs where request bodies don't tend to be very big. So internally it uses a type called CapturedStringContent
, which just "captures" the string to a property on construction. Event handlers use this to expose that RequestBody
property.
But multipart requests are much more likely to be large, and capturing the request body in string could be a legitimate memory concern. So the types at play here don't derive from CapturedStringContent
and hence you can't easily get at the body as a string.
As to why Parts
is empty, HttpClient
(which Flurl is built to top of) disposes the HttpContent
object automatically after the request is sent. Strangely (in my opinion), this clears the underlying collection that Parts
comes from, which I confirmed in the source.
All that being said, your code looks fine to me and I have little doubt it's doing what you expect. But if you want to be absolutely certain, I'd suggest using a network sniffer like Fiddler or Wireshark.
Upvotes: 1