0

I want to upload a file asynchronously from a web page to an ASP.NET MVC action:

[HttpPost]
public JsonResult AnalyseFile(HttpPostedFileBase file)
{
  // do stuff
  return Json(someResultObjects);
}

My problem is that when the method executes on the server, the file argument is null.

Over in HTML land, I have an input field containing a file:

<input type="file" accept=".xlsx" required="required" id="FileInput" name="FileInput" onchange="javascript:AnalyseFile();" />

And I have some javascript code:

function AnalyseFile() {
  var fileInput = document.getElementById('FileInput');
  var file = fileInput.files[0];
  var url = 'http://someserver/somecontroller/AnalyseFile';
  var xhr = new XMLHttpRequest();
  xhr.upload.onreadystatechange = function() {
    if(xhr.readyState == 4) {
      // do stuff
    }
  };
  xhr.open('POST', url, true);
  xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
  xhr.send('file=' + file);
}

I've verified that the javascript file object has a reference to the file by inserting the following line of code after var file = fileInput.files[0]:

alert(file.Name);

which correctly displays the file name in a message box.

However, when the server side method is called, the file itself is missing (the HttpPostedFileBase "file" argument is null). Can anyone advise me what I'm doing wrong here? The objective is for the HttpPostedFileBase to have the reference to the file so I can do some analyses on it on the server and send the results back to the browser for rendering to the user.

Mark Micallef
  • 2,643
  • 7
  • 28
  • 36
  • Shouldn't the input name be equal to the HttpPostetFileBase name, ie "file"? – andreasnico Mar 04 '16 at 06:31
  • Is server expecting a `javascript` `File` object ? Does `JsonResult` at `public JsonResult AnalyseFile(HttpPostedFileBase file)` indicate server is expecting `JSON` at `POST` ? – guest271314 Mar 04 '16 at 06:32
  • See http://stackoverflow.com/questions/19042116/ajax-beginform-in-mvc-to-upload-files/ – guest271314 Mar 04 '16 at 06:39
  • 1
    @andreasnico I tried that (matching the html element name to the argument name), but it made no difference. – Mark Micallef Mar 04 '16 at 06:43
  • @guest271314 No, JsonResult means the server will be returning JSON to the user-agent. – Mark Micallef Mar 04 '16 at 06:44
  • What data type is the server expecting ? Appear to `POST` at `File` object at `'file=' + file`, though `Content-Type` set to `'application/x-www-form-urlencoded'` ? – guest271314 Mar 04 '16 at 06:45
  • @guest271314 The server is expecting a file, which it represents with a HttpPostedFileBase object. As I've called the parameter 'file', I'm trying to specify the parameter name in the ajax request to 'file' so there will be a match. – Mark Micallef Mar 04 '16 at 06:49
  • @guest271314 I've also set the content-type to 'multipart/form-data', but it made no difference (though it may be correct). – Mark Micallef Mar 04 '16 at 06:50
  • See https://developer.mozilla.org/en-US/docs/Web/API/FormData/Using_FormData_Objects , http://stackoverflow.com/questions/581703/how-to-do-a-asp-net-mvc-ajax-form-post-with-multipart-form-data/ – guest271314 Mar 04 '16 at 06:52
  • @guest271314 Thanks, I just tried it with the DataData object, but it doesn't seem to solve the problem. Code: var formData = new FormData(); formData.append('file', file); xhr.send(formData); – Mark Micallef Mar 04 '16 at 06:56
  • @guest271314 I'm going to read through those stack articles you sent me and see if I can give their methodology a try. Thanks. – Mark Micallef Mar 04 '16 at 06:58

1 Answers1

0

You can allow Mediatype headers to accept 'application/x-www-form-urlencoded' in server side. The default formatter might not support 'application/x-www-form-urlencoded' , Hence file is null .

DAre G
  • 177
  • 10
  • I've changed the content-type to 'multipart/form-data' just to be sure, but that didn't resolve the issue. I'm uncertain as to which is better. – Mark Micallef Mar 04 '16 at 06:51
  • In a project that i am doing i use a custom Json Formatter . In that i have the following code `public JsonNetFormatterDecide() : base() { SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/json")); SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/plain")); }` This is because i know that I am expecting Json or Plain Text as input , Depending on what your mediatype header is you have to change the Header Value. – DAre G Mar 04 '16 at 08:10