ASP.NET WebApi: how to perform a multipart post with file upload using WebApi HttpClient

C#asp.netasp.net Web-ApiDotnet Httpclient

C# Problem Overview


I have a WebApi service handling an upload from a simple form, like this one:

	<form action="/api/workitems" enctype="multipart/form-data" method="post">
		<input type="hidden" name="type" value="ExtractText" />
		<input type="file" name="FileForUpload" />
		<input type="submit" value="Run test" />
	</form>

However, I can't figure out how to simulate the same post using the HttpClient API. The FormUrlEncodedContent bit is simple enough, but how do I add the file contents with the name to the post?

C# Solutions


Solution 1 - C#

After much trial and error, here's code that actually works:

using (var client = new HttpClient())
{
	using (var content = new MultipartFormDataContent())
	{
		var values = new[]
		{
			new KeyValuePair<string, string>("Foo", "Bar"),
			new KeyValuePair<string, string>("More", "Less"),
		};

		foreach (var keyValuePair in values)
		{
			content.Add(new StringContent(keyValuePair.Value), keyValuePair.Key);
		}

		var fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(fileName));
		fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
		{
			FileName = "Foo.txt"
		};
		content.Add(fileContent);

		var requestUri = "/api/action";
		var result = client.PostAsync(requestUri, content).Result;
	}
}

Solution 2 - C#

Thank you @Michael Tepper for your answer.

I had to post attachments to MailGun (email provider) and I had to modify it slightly so it would accept my attachments.

var fileContent = new ByteArrayContent(System.IO.File.ReadAllBytes(fileName));
fileContent.Headers.ContentDisposition = 
        new ContentDispositionHeaderValue("form-data") //<- 'form-data' instead of 'attachment'
{
    Name = "attachment", // <- included line...
    FileName = "Foo.txt",
};
multipartFormDataContent.Add(fileContent);

Here for future reference. Thanks.

Solution 3 - C#

You need to look for various subclasses of HttpContent.

You create a multiform http content and add various parts to it. In your case you have a byte array content and form url encoded along the lines of:

HttpClient c = new HttpClient();
var fileContent = new ByteArrayContent(new byte[100]);
fileContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
		                                    {
		                                        FileName = "myFilename.txt"
		                                    };

var formData = new FormUrlEncodedContent(new[]
		                                    {
		                                        new KeyValuePair<string, string>("name", "ali"),
		                                        new KeyValuePair<string, string>("title", "ostad")
		                                    });
		
		
MultipartContent content = new MultipartContent();
content.Add(formData);
content.Add(fileContent);
c.PostAsync(myUrl, content);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichael TeperView Question on Stackoverflow
Solution 1 - C#Michael TeperView Answer on Stackoverflow
Solution 2 - C#ThiagoPXPView Answer on Stackoverflow
Solution 3 - C#AliostadView Answer on Stackoverflow