ASP.NET MVC File Upload with AJAX

Uploading files using AJAX and ASP.NET MVC could not be simpler. And for the purests out there, this uses NO jQuery. This code actually allows the uploading of multiple files.

NOTE: The following code examples support ASP.NET MVC 5. Go to the ASP.NET Core example if using .NET Core.

To begin, create a web application (MVC) in Visual Studio named "Website".

Now, the client side. Half the work is done by the function buildFormData(). For a full implementation of buildFormData(), see the AJAX library source.

If using CSHTML files then use this code:

@{
    Layout = null;
}
<html>
	<head>
	<title></title>
	<script type="text/javascript">
	function xmlHttp(){
		if(XMLHttpRequest){
			return new XMLHttpRequest();
		} else if(window.ActiveXObject){
			var aVersions = ["MSXML2.XMLHttp.5.0","MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp"];
			for(var i = 0; i < aVersions.length; i++){
				try{
					var oXmlHttp = new ActiveXObject(aVersions[i]);
					return oXmlHttp;
				}catch(oError){
					//void
				}
			}
		}
		throw new Error("XMLHttp object could not be created.");
	}
	//used for posting "multipart/form-data"
	function buildFormData(form_object) {
		var fd = new FormData();
		for (var i = 0; i < form_object.elements.length; i++) {
			if (form_object.elements[i].name != null && form_object.elements[i].name != "") {
				if (form_object.elements[i].type == "checkbox") {
					if (form_object.elements[i].checked) {
						fd.append(form_object.elements[i].name, form_object.elements[i].value)
					}
				}
				else if (form_object.elements[i].type == "file") {
					for (var j = 0; j < form_object.elements[i].files.length; j++) {
						fd.append(form_object.elements[i].name,
						form_object.elements[i].files[j],
							form_object.elements[i].files[j].name)
					}
				}
				else {
					fd.append(form_object.elements[i].name, form_object.elements[i].value)
				}
			}
		}
		return fd;
	}
	function submitForm(oform)
	{
		if (window.FormData !== undefined) {
			document.getElementById("SubmitButton").disabled = true;
			var formData = buildFormData(oform);
			var xmlobj = xmlHttp();
			xmlobj.onreadystatechange = function () {
				if (xmlobj.readyState == 4) {
					if (xmlobj.status == 200) {
						document.getElementById("divResponse").innerHTML = xmlobj.responseText;
						document.getElementById("SubmitButton").disabled = false;
					}
					else {
						throw new Error("Error: " + xmlobj.status + ": " + xmlobj.statusText);
					}
				}
			};
			xmlobj.open("post", oform.action, true);
			xmlobj.send(formData);
		}
		else {
			alert("This browser does not support posting files with HTML5 and AJAX.");
		}
		return false;
	}
	</script>
	</head>
	<body>
	<form enctype="multipart/form-data" onsubmit="return submitForm(this);" method="post" action="/Ajax/UploadFile">
		@Html.AntiForgeryToken()
		<input type="text" required name="fullname" placeholder="enter your name here" /><br />
		<input type="file" accept="image/jpeg" multiple required name="file1" /><br />
		<input type="submit" id="SubmitButton" value="Upload File(s)" />
	</form>
	<div id="divResponse"></div>
	</body>
</html>

If still using ASPX files, then use this code.

<%@ Page Language="C#" Inherits="System.Web.Mvc.ViewPage" %>
<html>
	<head>
	<title></title>
	<script type="text/javascript">
	function xmlHttp(){
		if(XMLHttpRequest){
			return new XMLHttpRequest();
		} else if(window.ActiveXObject){
			var aVersions = ["MSXML2.XMLHttp.5.0","MSXML2.XMLHttp.4.0","MSXML2.XMLHttp.3.0","MSXML2.XMLHttp","Microsoft.XMLHttp"];
			for(var i = 0; i < aVersions.length; i++){
				try{
					var oXmlHttp = new ActiveXObject(aVersions[i]);
					return oXmlHttp;
				}catch(oError){
					//void
				}
			}
		}
		throw new Error("XMLHttp object could not be created.");
	}
	//used for posting "multipart/form-data"
	function buildFormData(form_object) {
		var fd = new FormData();
		for (var i = 0; i < form_object.elements.length; i++) {
			if (form_object.elements[i].name != null && form_object.elements[i].name != "") {
				if (form_object.elements[i].type == "checkbox") {
					if (form_object.elements[i].checked) {
						fd.append(form_object.elements[i].name, form_object.elements[i].value)
					}
				}
				else if (form_object.elements[i].type == "file") {
					for (var j = 0; j < form_object.elements[i].files.length; j++) {
						fd.append(form_object.elements[i].name,
						form_object.elements[i].files[j],
							form_object.elements[i].files[j].name)
					}
				}
				else {
					fd.append(form_object.elements[i].name, form_object.elements[i].value)
				}
			}
		}
		return fd;
	}
	function submitForm(oform)
	{
		if (window.FormData !== undefined) {
			document.getElementById("SubmitButton").disabled = true;
			var formData = buildFormData(oform);
			var xmlobj = xmlHttp();
			xmlobj.onreadystatechange = function () {
				if (xmlobj.readyState == 4) {
					if (xmlobj.status == 200) {
						document.getElementById("divResponse").innerHTML = xmlobj.responseText;
						document.getElementById("SubmitButton").disabled = false;
					}
					else {
						throw new Error("Error: " + xmlobj.status + ": " + xmlobj.statusText);
					}
				}
			};
			xmlobj.open("post", oform.action, true);
			xmlobj.send(formData);
		}
		else {
			alert("This browser does not support posting files with HTML5 and AJAX.");
		}
		return false;
	}
	</script>
	</head>
	<body>
	<form enctype="multipart/form-data" onsubmit="return submitForm(this);" method="post" action="/Ajax/UploadFile">
		<%: Html.AntiForgeryToken() %>
		<input type="text" required name="fullname" placeholder="enter your name here" /><br />
		<input type="file" accept="image/jpeg" multiple required name="file1" /><br />
		<input type="submit" id="SubmitButton" value="Upload File(s)" />
	</form>
	<div id="divResponse"></div>
	</body>
</html>

Next, the server side. Make a controller named "Ajax" and add the UploadFile() method.

// AjaxController.cs
using System;
using System.Web.Mvc;

namespace Website.Controllers
{
	public class AjaxController : Controller
	{
		[HttpPost]
		[ValidateInput(false)]
		[ValidateAntiForgeryToken]
		public string UploadFile()
		{
			int i;
			for (i = 0; i < Request.Files.Count; i++)
			{
				if (Request.Files[i].ContentLength > 0)
				{
					if (Request.Files[i].ContentType.ToLower() == "image/jpeg") // can be modified or omitted
					{
						try
						{
							// make sure that this directory has write permissions
							Request.Files[i].SaveAs(Request.MapPath("/") + Request.Files[i].FileName);
						}
						catch (Exception ex)
						{
							return ex.Message.ToString();
						}
					}
				}
			}
			return i.ToString() + " files copied. Hello, " + Request.Form["fullname"];
		}
	}
}

Tying Up Loose Ends

Finally, make sure that the server will accept large uploads and give the upload enough time to complete (timeout). Edit the Web.config file to have these sections. Note: ASP.NET Core requires that your create a web.config file.

<system.web>
	<httpRuntime executionTimeout="600" maxRequestLength="20480" requestValidationMode="2.0"/>
</system.web>
<system.webServer>
<security>
	<requestFiltering>
	<requestLimits maxAllowedContentLength="102400000"/>
	</requestFiltering>
</security>
</system.webServer>

It couldn't be any simpler!!!