1

I'm trying to upload a file and I'd like to pass the current MVC HttpContext.Current.Request.Files to a Web API.

I tried to pass the HttpFileCollectionBase as parameter to pass it to the API but it's always null. Controller

public object UploadAttachment(string param1, int param2, HttpFileCollectionBase files)
{
   string _url = _restUrl + param1+ "/Folders/" + param2+ "/UploadAttachment";
   HttpResponseMessage _response = SendJsonRequest(_url, HttpMethod.Post, files);
   var ret = DeserializeResponse(_response);
   return ret;
}

API code:

[HttpPost]
[Route("Archives/{param1}/Folders/{param2}/UploadAttachment")]      
public IHttpActionResult UploadAttachment([FromUri]string param1, [FromUri]int param2, [FromBody] HttpFileCollectionBase files)

View Code

using (Ajax.BeginForm("UploadAttachment", null, new { param1 = Model.Param1 }, new AjaxOptions { HttpMethod = "POST", OnSuccess = "uploadAttachmentSuccess" }, new { id = "uploadAttachment", enctype = "multipart/form-data" }))
                    {
                    <div class="row">
                        <div class="col-xs-10">
                            <div class="input-group">
                                <label class="input-group-btn" title="">
                                    <span class="btn btn-primary">
                                        <input type="file" name="file_upload" id="file_upload" style="display: none;" multiple />
                                        Browse
                                    </span>
                                </label>
                                <input type="text" id="file_upload_name" class="form-control" readonly>
                            </div>
                        </div>
                        <div class="col-xs-2">
                            <button type="submit" class="btn btn-success" data-toggle="tooltip" id="btn-submit-upload" title="" disabled>
                                Upload
                            </button>
                        </div>
                    </div>
                    <div class="row">
                        <div class="col-xs-12" id="warning-format">
                        </div>
                    </div>
                    }

SendJsonRequest Implementation

            protected virtual HttpResponseMessage SendJsonRequest(string url, HttpMethod method, object objectToSerialize = null, bool tryToRefreshToken = true)
    {
        ...
        HttpRequestMessage _request = new HttpRequestMessage(method, _uri);
        if (objectToSerialize != null)
        {
            string _serializedJSONObject = JsonConvert.SerializeObject(objectToSerialize);
            _request.Content = new StringContent(_serializedJSONObject);
            _request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
        }...
Caloyski
  • 328
  • 2
  • 6
  • 18
  • Are you using a "file" type input to browse and upload the file? – Wheels73 Apr 04 '17 at 12:39
  • Yes, and the MVC Action detects it, but when I try to pass the file from my MVC Controller to the Web Api Controller, it becomes null. – Caloyski Apr 04 '17 at 12:43
  • How are you posting to the controller? Ajax? Can you post your view / ajax post code? – Wheels73 Apr 04 '17 at 12:51
  • Yes, I'm passing the file through Ajax to the Controller. We're trying to avoid to make an Ajax request to the Web Api directly, we have to go through the MVC Controller. Every example out there is about making an Ajax request to the Web Api. – Caloyski Apr 04 '17 at 12:57
  • In my MVC controller, my type that is received on post from the form is "HttpPostedFileBase" Try that instead of HttpFileCollectionBase. – Wheels73 Apr 04 '17 at 12:58
  • I tried that too but like HttpFileCollectionBase, HttpPostedFileBase is null too. How did you include it in the Body of the request? – Caloyski Apr 04 '17 at 13:01
  • Can you please show SendJsonRequest implementation? – Mukesh Modhvadiya Apr 04 '17 at 13:02
  • i'll post as an answer to show you how I did it. DONE! – Wheels73 Apr 04 '17 at 13:02
  • @MukeshModhvadiya Good point, looks like HttpFileCollectionBase wasn't serialized. Do you think it's another reason to follow my solution in my question (about HttpContext)? – Caloyski Apr 04 '17 at 13:18
  • Hello... Final thought from me then...the ActionExecutingContext could be a solution. Use an OnActionExecuting override in your controller and see if you can post that context to your API? – Wheels73 Apr 04 '17 at 13:37
  • Yes indeed, I thought so! I am not sure exactly what is wrong, but can you please check if setting content type : multipart/form-data works or not? I was busy so replied late. – Mukesh Modhvadiya Apr 04 '17 at 14:07
  • I just tried to change the content type, but it says it's not supported. I tried to store the file in a Stream and pass it to the API, but again it's null. I'm wondering why nobody is upvoting my question even though this is a real world problem and it's not a duplicate :S – Caloyski Apr 04 '17 at 14:26
  • @Caloyski, I have created a working sample, posting it! – Mukesh Modhvadiya Apr 06 '17 at 07:16

1 Answers1

2

I have created a sample for uploading files from MVC controller to Web Api controller, and it's working perfectly

MVC controller :

    [ActionName("FileUpload")]
    [HttpPost]
    public ActionResult FileUpload_Post()
    {
        if (Request.Files.Count > 0)
        {
            var file = Request.Files[0];

            using (HttpClient client = new HttpClient())
            {
                using (var content = new MultipartFormDataContent())
                {
                    byte[] fileBytes = new byte[file.InputStream.Length + 1];                     file.InputStream.Read(fileBytes, 0, fileBytes.Length);
                    var fileContent = new ByteArrayContent(fileBytes);
                    fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = file.FileName };
                    content.Add(fileContent);
                    var result = client.PostAsync(requestUri, content).Result;
                    if (result.StatusCode == System.Net.HttpStatusCode.Created)
                    {
                        ViewBag.Message= "Created";
                    }
                    else
                    {
                        ViewBag.Message= "Failed";
                    }
                }
            }
        }
        return View();
    }

Web Api controller :

    [HttpPost]
    public HttpResponseMessage Upload()
    {
        if(!Request.Content.IsMimeMultipartContent())
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
        if (System.Web.HttpContext.Current.Request.Files.Count > 0)
        {
            var file = System.Web.HttpContext.Current.Request.Files[0];
            ....
            // save the file
            ....
            return new HttpResponseMessage(HttpStatusCode.Created);
        }
        else
        {
            return new HttpResponseMessage(HttpStatusCode.BadRequest);
        }
    }

For more information on saving file in Web Api, refer Web API: File Upload

Hope that helps!

Mukesh Modhvadiya
  • 2,178
  • 2
  • 27
  • 32