33

I have been asked to do the following in C#:

/**

* 1. Create a MultipartPostMethod

* 2. Construct the web URL to connect to the SDP Server

* 3. Add the filename to be attached as a parameter to the MultipartPostMethod with parameter name "filename"

* 4. Execute the MultipartPostMethod

* 5. Receive and process the response as required

* /

I have written some code that has no errors, however, the file is not attached.

Can someone have a look at my C# code to see if I have written the code incorrectly?

Here is my code:

var client = new HttpClient();
const string weblinkUrl = "http://testserver.com/attach?";
var method = new MultipartFormDataContent();
const string fileName = "C:\file.txt";
var streamContent = new StreamContent(File.Open(fileName, FileMode.Open));
method.Add(streamContent, "filename");

var result = client.PostAsync(weblinkUrl, method);
MessageBox.Show(result.Result.ToString());
user2985419
  • 553
  • 3
  • 9
  • 23
  • 1
    This has been asked a number of times on SO. Here's some possible solutions: C# HttpClient 4.5 multipart/form-data upload: https://stackoverflow.com/questions/16416601/c-sharp-httpclient-4-5-multipart-form-data-upload HttpClient Multipart Form Post in C#: https://stackoverflow.com/questions/18059588/httpclient-multipart-form-post-in-c-sharp On a personal note, check the post data being sent in the request, and check the response. [Fiddler](http://fiddler2.com/) is excellent for this. – Torra Dec 02 '13 at 02:35

5 Answers5

35

Posting MultipartFormDataContent in C# is simple but may be confusing the first time. Here is the code that works for me when posting a .png .txt etc.

// 2. Create the url 
string url = "https://myurl.com/api/...";
string filename = "myFile.png";
// In my case this is the JSON that will be returned from the post
string result = "";
// 1. Create a MultipartPostMethod
// "NKdKd9Yk" is the boundary parameter

using (var formContent = new MultipartFormDataContent("NKdKd9Yk"))
{
    formContent.Headers.ContentType.MediaType = "multipart/form-data";
    // 3. Add the filename C:\\... + fileName is the path your file
    Stream fileStream = System.IO.File.OpenRead("C:\\Users\\username\\Pictures\\" + fileName);
    formContent.Add(new StreamContent(fileStream), fileName, fileName);

    using (var client = new HttpClient())
    {
        // Bearer Token header if needed
        client.DefaultRequestHeaders.Add("Authorization", "Bearer " + _bearerToken);
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("multipart/form-data"));

        try
        {
            // 4.. Execute the MultipartPostMethod
            var message = await client.PostAsync(url, formContent);
            // 5.a Receive the response
            result = await message.Content.ReadAsStringAsync();                
        }
        catch (Exception ex)
        {
            // Do what you want if it fails.
            throw ex;
        }
    }    
}

// 5.b Process the reponse Get a usable object from the JSON that is returned
MyObject myObject = JsonConvert.DeserializeObject<MyObject>(result);

In my case I need to do something with the object after it posts so I convert it to that object with JsonConvert.

KoalaBear
  • 2,755
  • 2
  • 25
  • 29
Braden Brown
  • 3,111
  • 1
  • 20
  • 18
2

I know this is an old post But to those searching for a solution, to provide a more direct answer, here's what I've found:

using System.Diagnostics;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;

public class UploadController : ApiController
{
    public async Task<HttpResponseMessage> PostFormData()
    {
        // Check if the request contains multipart/form-data.
        if (!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }

        string root = HttpContext.Current.Server.MapPath("~/App_Data");
        var provider = new MultipartFormDataStreamProvider(root);

        try
        {
            // Read the form data.
            await Request.Content.ReadAsMultipartAsync(provider);

            // This illustrates how to get the file names.
            foreach (MultipartFileData file in provider.FileData)
            {
                Trace.WriteLine(file.Headers.ContentDisposition.FileName);
                Trace.WriteLine("Server file path: " + file.LocalFileName);
            }

            return Request.CreateResponse(HttpStatusCode.OK);
        }
        catch (System.Exception e)
        {
            return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
        }
    }
}

Here's where I found it: http://www.asp.net/web-api/overview/advanced/sending-html-form-data,-part-2

For a more Elaborate implementation: http://galratner.com/blogs/net/archive/2013/03/22/using-html-5-and-the-web-api-for-ajax-file-uploads-with-image-preview-and-a-progress-bar.aspx

KoalaBear
  • 2,755
  • 2
  • 25
  • 29
iuppiter
  • 315
  • 3
  • 9
  • 13
    This *reads* multipart/form-data, it doesn't *send* it. I wonder if you read the question, which doesn't even involve ASP.NET Web API – Camilo Terevinto Jul 01 '19 at 15:11
  • This is server side code. OP asked for a client side code that sends the request. – Mostafa Zeinali Jul 14 '19 at 04:07
  • @SOusedtobegood I know this comment is old, but I haven't logged in in a while. Um, the question reads C# so .NET is implied and that code is not from ASP, it's from an MVC project I was working on. O_o – iuppiter Aug 06 '19 at 23:01
  • @MostafaZeinali dude, when have you ever seen C# client side? You have really got to read the questions before posting comments. the question clearly states "Can someone have a look at my C# code to see if I have written the code incorrectly?". o_O – iuppiter Aug 06 '19 at 23:07
  • 3
    @iuppiter I have seen C# client side many times my friend. Any client C# application that wants to send/receive data to/from a server needs to write client side code. I also saw it one more time here, in the authors question, in the line: "client.PostAsync(weblinkUrl, method);" This is a client side code that is trying to send a post request to a server. Plain and simple. Your code, on the other hand, is a server side code, that receives a multipart post request and "reads" the attached file from it. You and the author could create a web app together, you do server side, he does client side. – Mostafa Zeinali Aug 08 '19 at 07:35
  • The links are broken. – Gert Arnold Nov 30 '20 at 07:54
2

Specify the third parameter which is a fileName.

Something like this:

method.Add(streamContent, "filename", "filename.pdf");
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
  • As it’s currently written, your answer is unclear. Please [edit] to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 08 '22 at 00:40
  • 1
    Seems pretty clear to me. – TheLegendaryCopyCoder Jun 21 '22 at 07:27
1

I debugged this the problem is here:

method.Add(streamContent, "filename");

This 'Add' doesn't actually put the file in the BODY of Multipart Content.

A-Sharabiani
  • 17,750
  • 17
  • 113
  • 128
0

I know this is old, but I only want to give a clearer example. Variable image is a byte[] and filename is an string with the name of the image:

        ByteArrayContent imageContent = new ByteArrayContent(image);
        imageContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");

        MultipartFormDataContent formData = new MultipartFormDataContent();        
        pFormData.Add(imageContent, "image", fileName);
        
        HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "destinatioUri");
        request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        request.Content = formData;
            
        HttpResponseMessage response = await _httpClient.SendAsync(request);            
xrodas
  • 466
  • 2
  • 10