3

I need to come up with a ASP.NET WebAPI method that accepts a request containing an uploaded file and a few other parameters. The C# model for this request is the following:

public class MyRequestViewModel
{       
    public byte[] ZipArchive { get; set; }
    public string Param1 { get; set; }
    public string Param2 { get; set; }
}

I need to be able to accept the following requests:

Form data request body example:

-----------------------------8198313082943
Content-Disposition: form-data; name="File"; filename="invoice.zip"
Content-Type: application/x-zip-compressed

PK....<long uploded file data>
-----------------------------8198313082943
Content-Disposition: form-data; name="Param1"

1
-----------------------------8198313082943
Content-Disposition: form-data; name="Param2"

2
-----------------------------8198313082943--

JSON request body example:

    -----------------------------8198313082943
    Content-Disposition: form-data; name="File"; filename="invoice.zip"
    Content-Type: application/x-zip-compressed

    PK....<long uploded file data>
    -----------------------------8198313082943
    Content-Disposition: form-data; name="myJsonString"
    Content-Type: application/json

    {"Param1": "1", "Param2": "2"}
    -----------------------------8198313082943--

So far I've tried to write my WebAPI method like this:

[HttpPost]
public async Task<HttpResponseMessage> UploadStuff([FromBody] MyRequestViewModel request)
{
    if (!this.Request.Content.IsMimeMultipartContent())
    {
        throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
    }

    var streamProvider = new MultipartMemoryStreamProvider();
    await Request.Content.ReadAsMultipartAsync(streamProvider);
    request.ZipArchive = await streamProvider.Contents.FirstOrDefault()?.ReadAsByteArrayAsync();
    return Process(request);
}

But when I try to upload file, I'm getting the following error:

The request entity's media type 'multipart/form-data' is not supported for this resource.

Seems like WebAPI doesn't know how to bind the request body to MyRequestViewModel. If I change [FromBody] to [FromUri] and pass Param1 and Param2 as query string parameters, then everything works fine.

But I really need to get these parameters from request body. What's worse, I have to accept them as both FormData and JSON, and I don't know in what order they will be passed in the request. (So I can't always be sure that streamProvider.Contents[0] is a binary file and streamProvider.Contents[1] is a JSON). How do I make WebAPI correctly bind these body parameters?

Nazz
  • 193
  • 3
  • 9
  • 1
    As you discovered `multipart/form-data` requests cannot be bound to action parameters. You have to remove your `MyRequestViewModel` parameter from the action and just read the body using the `Request` object. – Federico Dipuma May 24 '17 at 15:19
  • @FedericoDipuma, are you sayng that my only option is manually parsing request body to find ot whether it is FormData or JSON, and then manually map this FormData or JSON to my C# objects? – Nazz May 24 '17 at 15:34
  • There could be [other nontrivial options](https://stackoverflow.com/questions/12593001/web-api-model-binding-with-multipart-formdata), but in your case the json part of your multipart form should anyway be retrived as string and then deserialized manually (using `JsonConver.DeserializeObject` at least). – Federico Dipuma May 24 '17 at 15:37

0 Answers0