Search code examples
c#apirestsharpasp.net-core-2.1

XUnit test for file upload causes an exception though the endpoint works when used in my site


Using insomnia to create the code with RestSharp:

var client = new RestClient("https://localhost:44372/api/Box/Upload");
var request = new RestRequest(Method.POST);
request.AddHeader("content-type", "multipart/form-data; boundary=---011000010111000001101001");
request.AddParameter("multipart/form-data; boundary=---011000010111000001101001", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"LiterallyAnything\"\r\n\r\n", ParameterType.RequestBody);
request.AddFile("MyFileName", "MyFileAndPath");
IRestResponse response = client.Execute(request);

This hits the .net Core 2.1 endpoint just fine:

[HttpPost("Upload")]
[ProducesResponseType(typeof(ActionResult), 201)]
[ProducesResponseType(typeof(ActionResult), 400)]
[ProducesResponseType(typeof(ActionResult), 500)]
public async Task<IActionResult> Upload() {
    ActionResult retVal = StatusCode(500);
    try {
        if (Request.Form.Files.Count() != 1) { //<----Throws exception here

I get the following error:

Unexpected end of Stream, the content may have already been read by another component.

I've checked to see if there's some kind of file lock (there isn't). The file absolutely exists. It just doesn't seem to handle it too well when running from within the unit test.

What gives?


Solution

  • When you use any overload of IRestRequest.AddFile, it will add a special type of parameter to the request, called FileParameter. When the RestClient discovers that the list of files in the request is not empty, it will form a mult-part form request automatically for you and set all the necessary headers.

    In general, there is a very little number of cases when you need to manually add headers and technical parameters to your requests when using RestSharp. Hence that nowhere in the documentation we add things like the content type to the request headers as it is always done automatically for you based on the request parameters, body, files and so on.

    Concerning the Insomnia client, they use the httpsnippet tool from Kong to generate code snippets. This is their code for RestSharp, which is extremely simplistic and definitely doesn't fit our recommended usage, so I would recommend checking our docs.