68

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?

2
  • 1
    Do you mind sharing the code in the WebApi side that consumes the MultipartFormDataContent? Commented Jan 25, 2016 at 16:49
  • Example send parameters as multipeart dotnet 3.0 in answer stackoverflow.com/a/59308653/5333683 Commented Dec 12, 2019 at 16:33

3 Answers 3

136

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;
    }
}
Sign up to request clarification or add additional context in comments.

7 Comments

Use StreamContent for large files: var fileContent = new StreamContent(File.OpenRead(fileName));
Woohoo -- I had a totally different issue, but needed to post content nonetheless. I was able to modify to fit my needs. Thanks a lot!!
Strangely this does not work for me. I had to add quotes around the content names, see this: stackoverflow.com/questions/15638622/…
FYI, there is a constant for "attachment" under System.Net.Mime.DispositionTypeNames
I too had to add quotes around the name value: FileName = "\"TestImage.jpg\"". I am using ServiceStack on the server instead of WebAPI not sure if that is related or not.
|
14

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.

Comments

11

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);

3 Comments

That doesn't work, unfortunately, although the ContentDisposition header does seems to take me a step forward. If I use your sample code as is, I get an Unsupported Media Type exception. However, if I replace MultipartContent with MultipartFormDataContent the exception goes away. On the server, however, the value of the hidden field is missing.
@MichaelTeper I have not tested the code. I will play a bit with it and update the post, but my point was to show you a snippet of what you need to look for and not a working code.
I just get StatusCode: 415, ReasonPhrase: 'Unsupported Media Type'

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.