Ok, I really hate and enjoy spending 6 hours hunting down an issue. I hate it because the bug is super stupid and I have no idea why it would be this way. I enjoy it because this is what developers do, we solve issues and bugs are issues.
I have spent a total of 6 hours trying figure out why I was not able to do an HTTP post to an endpoint with a file attached. I was at an advantage because I had a working example (no direct access to the source, just the running application) so I could upload the file and capture the traffic via Fiddler.
I tried to make my post as similar as the working example, but I kept getting back a 400 error telling me that the file was not included. The problem was that the FILE WAS INCLUDED. I could see the bytes in the message via Fiddler. Finally I decided to pull the source for RestSharp.Portable locally to see if I could find the issue.
After a ton of testing I finally noticed one little difference. A difference to me looked like a non-issue… turns out it was the issue.
Here is the Fiddler results of the working post
Content-Disposition: form-data; name=”file”; filename=”awesome-desktop-wallpapers-4.jpg”
Here is the Fiddler results of the non-working post
Content-Disposition: form-data; name=file; filename=awesome-desktop-wallpapers-4.jpg;
Notice the difference? Yea the quotes around the filename header property. This was the issue. Turns out that per the w3 spec for Content-Disposition the file name SHOULD be wrapped in quotes.
To fix this issue I simply escaped my file name prior to adding it to my request and then the post uploaded.
Now on to the core issue. When stepping through the source for the Restsharp library I found the exact line of code causing the issue. Take a look at the code below, the yellow box is the bad line.
The issue is that multipartContent.Add is a part of the System.Net.Http namespace.
Turns out that if you do not have the fileName escaped it will NOT add quotes around it when the HTTP header is created. If the fileName IS escaped it will add quotes when it is added to the HTTP header.
Something does not seem right, but at least I know the issue and how to work around it.
Till next time,