Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Model binding posted file to byte array

, 15 Apr 2014 CPOL
Rate this:
Please Sign up or sign in to vote.
Custom model binders are a great way to go when you want to customize the binding process and reuse it in more than one place.

"THE ARTICLE IS NO LONGER MAINTAINED HERE. PLEASE POST ANY FURTHER DISCUSSIONS/QUESTIONS IN MY BLOG http://www.prideparrot.com/blog/archive/2012/6/model_binding_posted_file_to_byte_array" - Author

Uploading files

The improvements made in model binding from ASP.NET MVC 2 helps to easily map the uploaded files to models. The HttpPostedFileBaseModelBinder is the one that maps the file(s) available in the Request.Files to single or collection of HttpPostedFileBase instances. Whenever you have HttpPostedFileBase as a parameter in an action method or as a property in the model the HttpPostedFileBaseModelBinder comes to play and does the magic.

An example is:

public ActionResult Upload(MyModel model, HttpPostedFileBase file)
{
    // the uploaded file is automatically available in the HttpPostedFileBase by the built-in
    // model binder
    if (file.ContentLength > 0) 
    {
        var fileName = Path.GetFileName(file.FileName);
        var path = Path.Combine(Server.MapPath("~/App_Data/uploads"), fileName);
        file.SaveAs(path);
      }
            
      return RedirectToAction("Index");
}
Listing 1. HttpPostedFileBase as action parameter

But sometimes we need little more convenience for ex. when an uploaded file needs to be persisted in database, we would love to have the uploaded file automatically converted into a byte array and available right in the action.

public ActionResult Upload(MyModel model, byte[] file)
{
    ...
}
Listing 2. byte[] as action parameter

In this article we are going to see how we can achieve that by extending the built-in ByteArrayModelBinder.

ByteArrayModelBinder

The ByteArrayModelBinder is used to convert the base64 encoded string into byte array and it doesn't care about converting the uploaded file into byte array unless we do something about that!

We can't just use a new binder for binding byte array unless we remove the ByteArrayModelBinder from Binders collection. Instead of adding a brand new model binder that will take care of only converting the file into byte array we can extend the ByteArrayModelBinder to take of this conversion along with the usual job.

So here is our custom ByteArrayModelBinder.

CustomByteArrayModelBinder

public class CustomFileModelBinder : ByteArrayModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var file = controllerContext.HttpContext.Request.Files[bindingContext.ModelName];

        if (file != null)
        {
            if (file.ContentLength != 0 && !String.IsNullOrEmpty(file.FileName))
            {
                var fileBytes = new byte[file.ContentLength];
                file.InputStream.Read(fileBytes, 0, fileBytes.Length);
                return fileBytes;
            }

            return null;
        }

        return base.BindModel(controllerContext, bindingContext);
    }
}
Listing 3. CustomFileModelBinder

In the BindModel method we are checking out whether the Request.Files collection contains a file with the model name and if yes then we are reading the file, converting it into byte array and returning it else we are just by-passing the call to the base ByteArrayModelBinder.

Last but not least we have to throw away the ByteArrayModelBinder from the Binders collection and add our custom made one to it.

protected void Application_Start()
{
    ...
    ModelBinders.Binders.Remove(typeof(byte[]));
    ModelBinders.Binders.Add(typeof(byte[]), new CustomFileModelBinder());
}
Listing 4. Registering CustomFileModelBinder in Global.asax.cs

Yeah, we are done! now we can do things like this:

public class Profile
{
    public string Name {get; set;}
    public int Age{get; set;}
    public byte[] photo{get; set;}
}

[HttpPost]
public ActionResult Save(Profile profile)
{
    if(ModelState.IsValid)
    {
        db.Save(profile);
        return RedirectToAction("Home");
    }

    return View();
}
Listing 4. Using CustomFileModelBinder

Summary

Custom model binders are a great way to go when you want to customize the binding process and reuse it in more than one place. Our custom ByteArrayModelBinder helps to avoid manually convert the file stream from HttpPostedFileBase into byte array.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

After2050
Software Developer Trigent Software Private Limited
India India
I'm a software developer from south tip of India. I spent most of the time in learning new technologies. I've a keen interest in client-side technologies especially JavaScript and admire it is the most beautiful language ever seen.
 
I like sharing my knowledge and written some non-popular articles. I believe in quality and standards but blames myself for lagging them.
 
I believe in small things and they makes me happy!
Follow on   Twitter

Comments and Discussions

 
QuestionJavascript PinmemberElayaraja Ponnusamy16-Apr-13 1:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.141015.1 | Last Updated 15 Apr 2014
Article Copyright 2012 by After2050
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid