<input type="file">… working with uploaded file data using ASP.NET MVC

I’ve been building an application with the MVC beta, and came to implement a form that included a file upload form control. Accessing uploaded file data is quite simple via…

HttpContext.Current.Request.Files["controlName"]

However, in this case I want to unit-test the action method on the controller, and any direct reference to a dependency will make unit-testing difficult. I can use Dependency Injection, but I don’t particularly want to provide a mocked version of the HttpContext.

This is a scenario where custom Model Binders can be applied. Define the following class that implements the IModelBinder interface.

   1: public class HttpPostedFileModelBinder : IModelBinder
   2: {
   3:     public ModelBinderResult BindModel(ModelBindingContext bindingContext)
   4:     {
   5:         HttpPostedFileBase file = bindingContext.HttpContext.Request.Files[bindingContext.ModelName];
   6:         byte[] fileData = new byte[file.InputStream.Length];
   7:         file.InputStream.Read(fileData, 0, Convert.ToInt32(file.InputStream.Length));
   8:
   9:         return new ModelBinderResult(fileData);
  10:     }
  11: }

Then in global.asax, hook up the custom binder to work with parameters of type byte[]…

ModelBinders.Binders[typeof(byte[])] = new HttpPostedFileModelBinder();

You can now define a named parameter on your action method of type byte[], where the name matches the name on your <input type=”file”> element, and the binary data from the uploaded file will be passed into the action method.

   1: [ActionName("Index"), AcceptVerbs(HttpVerbs.Post)]
   2: public ActionResult FormSubmit(byte[] photo)
   3: {
   4:    // do something with the posted image
   5: }

Unit testing the action method is now simply a case of passing a byte array, and the run-time version will pull the appropriate information from the HttpContext and pass into the action method.

Posted:

November 3, 2008 @ 10:08

Categories:

Personal

Tags:

Comments:

No comments so far

Comments RSS feed for comments on this post.

No comments yet.

Leave a comment