I am trying to upload a file with additional form data and post to Web API via MVC but i couldn't accomplish.
MVC Side
Firstly i got the submitted form at MVC. Here is the action for this.
[HttpPost] public async Task<ActionResult> Edit(BrandInfo entity) { try { byte[] logoData = null; if(Request.Files.Count > 0) { HttpPostedFileBase logo = Request.Files[0]; logoData = new byte[logo.ContentLength]; logo.InputStream.Read(logoData, 0, logo.ContentLength); entity.Logo = logo.FileName; entity = await _repo.Update(entity.BrandID, entity, logoData); } else entity = await _repo.Update(entity,entity.BrandID); return RedirectToAction("Index", "Brand"); } catch(HttpApiRequestException e) { // logging, etc return RedirectToAction("Index", "Brand"); } }
Below code post the Multipartform to Web API
string requestUri = UriUtil.BuildRequestUri(_baseUri, uriTemplate, uriParameters: uriParameters); MultipartFormDataContent formData = new MultipartFormDataContent(); StreamContent streamContent = null; streamContent = new StreamContent(new MemoryStream(byteData)); streamContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data") { FileName = "\"" + fileName + "\"", Name = "\"filename\"" }; streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); formData.Add(streamContent); formData.Add(new ObjectContent<TRequestModel>(requestModel, _writerMediaTypeFormatter), "entity"); return _httpClient.PutAsync(requestUri, formData).GetHttpApiResponseAsync<TResult>(_formatters);
As you can see i am trying to send file data and object with same MultipartFormDataContent
. I couldn't find better way to send my entity as ObjectContent
. Also i am using JSON.Net Serializer
Regarding to fiddler, post seems successfull.
Web API Side
Finally i am catching post at Web API side and trying to parse but i couldn't. Because MultipartFormDataStreamProvider
's FileData
and FormData
collections are allways empty.
[HttpPut] public void UpdateWithLogo(int id) { if(Request.Content.IsMimeMultipartContent()) { var x = 1; // this code has no sense, only here to check IsMimeMultipartContent } string root = HttpContext.Current.Server.MapPath("~/App_Data"); var provider = new MultipartFormDataStreamProvider(root); try { // Read the form data. Request.Content.ReadAsMultipartAsync(provider); foreach(var key in provider.FormData.AllKeys) { foreach(var val in provider.FormData.GetValues(key)) { _logger.Info(string.Format("{0}: {1}", key, val)); } } // This illustrates how to get the file names. foreach(MultipartFileData file in provider.FileData) { _logger.Info(file.Headers.ContentDisposition.FileName); _logger.Info("Server file path: " + file.LocalFileName); } } catch(Exception e) { throw new HttpApiRequestException("Error", HttpStatusCode.InternalServerError, null); } }
I hope you can help to find my mistake.
UPDATE
I also realized that, if i comment out StreamContent
or ObjectContent
and only add StringContent, still i can't get anything from MultipartFormDataStreamProvider
.