Skip to content

Instantly share code, notes, and snippets.

@Antaris
Created October 22, 2011 09:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Antaris/1305827 to your computer and use it in GitHub Desktop.
Save Antaris/1305827 to your computer and use it in GitHub Desktop.
An updated model binder that supports async and non-async file uploads.
namespace AsyncUpload.Controllers
{
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
return View();
}
public ActionResult About()
{
return View();
}
[HttpPost]
public ActionResult Upload(HttpPostedFileBase file)
{
// Use the standard HttpPostedFileBase
return View();
}
}
}
namespace AsyncUpload.Models
{
public class HttpPostedFileBaseModelBinder : IModelBinder
{
public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var request = controllerContext.RequestContext.HttpContext.Request;
if (request.Files.Count > 0)
{
var file = request.Files[bindingContext.ModelName];
if (file != null && file.ContentLength > 0 && !string.IsNullOrEmpty(file.FileName))
return file;
return null;
}
if (request.ContentLength > 0)
{
string filename = request.Headers["X-File-Name"];
if (string.IsNullOrEmpty(filename))
return null;
string fileType = request.Headers["X-File-Type"];
byte[] fileContent = new byte[request.ContentLength];
request.InputStream.Read(fileContent, 0, request.ContentLength);
return new AsyncHttpPostedFile(filename, fileType, fileContent);
}
return null;
}
class AsyncHttpPostedFile : HttpPostedFileBase
{
private readonly string _filename;
private readonly string _contentType;
private readonly int _contentLength;
private readonly byte[] _data;
public AsyncHttpPostedFile(string filename, string contentType, byte[] data)
{
_filename = filename;
_contentType = contentType;
_contentLength = data.Length;
_data = data;
}
public override string FileName { get { return _filename; } }
public override string ContentType { get { return _contentType; } }
public override int ContentLength { get { return _contentLength; } }
public override Stream InputStream { get { return new MemoryStream(_data); } }
}
}
}
@Antaris
Copy link
Author

Antaris commented Oct 22, 2011

This is based around Ben (@Buildstarted)'s blog post entitled "Asp.net MVC 3 file uploads using the FileApi" whereby we need to handle async file uploads which don't populate the HttpRequest.Files collection. We can build a new model binder to replace the existing implementation.

ModelBinders.Binders.Remove(typeof(HttpPostedFileBase));
ModelBinders.Binders.Add(typeof(HttpPostedFileBase), new AsyncUpload.Models.HttpPostedFileBaseModelBinder());

@Mart-Bogdan
Copy link

Wait, it's not Async at all, it uses InputStream.Read, not InputStream.BeginRead or InputStream.ReadAsync

@ranjanified
Copy link

Where is async stuff here?

@Antaris
Copy link
Author

Antaris commented Jun 22, 2020

This gist is from 2011. By "async" - this was back in the day when you're performing "async" file uploads in a browser using AJAX. This is explicitly not modern C# async/await.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment