Uploading a File (Or Files) With ASP.NET MVC

I wanted to confirm something about how to upload a file or set of files with ASP.NET MVC and the first search result for the phrase “uploading a file with asp.net mvc” is Scott Hanselman’s blog post on the topic.

His blog post is very thorough and helps provide a great understanding of what’s happening under the hood. The only complaint I have is that the code could be much simpler since we’ve made improvements to the ASP.NET MVC 2. I write this blog post in the quixotic hopes of knocking his post from the #1 spot.

Uploading a single file

Let’s start with the view. Here’s a form that will post back to the current action.

<form action="" method="post" enctype="multipart/form-data">
  
  <label for="file">Filename:</label>
  <input type="file" name="file" id="file" />

  <input type="submit" />
</form>

Here’s the action method that this view will post to which saves the file into a directory in the App_Data folder named “uploads”.

[HttpPost]
public ActionResult Index(HttpPostedFileBase file) {
            
  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");
}

Notice that the argument to the action method is an instance of HttpPostedFileBase. ASP.NET MVC 2 introduces a new value providers feature which I’ve covered before.

Whereas model binders are used to bind incoming data to an object model, value providers provide an abstraction for the incoming data itself.

In this case, there’s a default value provider called the HttpFileCollectionValueProvider which supplies the uploaded files to the model binder.Also notice that the argument name, file, is the same name as the name of the file input. This is important for the model binder to match up the uploaded file to the action method argument.

Uploading multiple files

In this scenario, we want to upload a set of files. We can simply have multiple file inputs all with the same name.

<form action="" method="post" enctype="multipart/form-data">
    
  <label for="file1">Filename:</label>
  <input type="file" name="files" id="file1" />
  
  <label for="file2">Filename:</label>
  <input type="file" name="files" id="file2" />

  <input type="submit"  />
</form>

Now, we just tweak our controller action to accept an IEnumerable of HttpPostedFileBase instances. Once again, notice that the argument name matches the name of the file inputs.

[HttpPost]
public ActionResult Index(IEnumerable<HttpPostedFileBase> files) {
  foreach (var file in files) {
    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");
}

Yes, it’s that easy. :)

What others have said

Requesting Gravatar... Andrei Rinea Jul 17, 2010 4:24 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Two small comments :

1. I wouldn't say "an enumeration of HttpPostedFileBase" but "an IEnumerable of HttpPostedFileBase" to avoid confusion with the enum type

2. If the two files come from different client folders AND have the same file name the last file will win on the server (i.e.: it will overwrite the first)
Requesting Gravatar... Brian Jul 17, 2010 11:31 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Awesome, thanks!

Perhaps you (or somebody else) has an answer to this problem. In IIS6 it seems that if you recycle the app pool any uploads occurring at the time will fail. Is this a known problem? Is there a known work-around? Is this fixed in IIS7 (it seems like it is, but I haven't fully tested it yet)?
Requesting Gravatar... haacked Jul 17, 2010 12:15 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
@andrei, thanks for the feedback. :)
Requesting Gravatar... Fynn Jul 19, 2010 7:13 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Excellent stuff. As a newbie to web development, I would like to see how best to implement the file(s) upload scenario in asp.net mvc 2 where the client is Windows application and not a web form.

Thanks.
Requesting Gravatar... Kevin Major Jul 19, 2010 7:20 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Quick question: what if you want another controller method to handle the upload? What would one have to specify as the path for the form's action attribute? Simply '/controller/method'?
Requesting Gravatar... Mike Henry Jul 19, 2010 7:48 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Nice, I was wondering how best to handle multiple files with MVC.

What is your preferred way to handle uploads that are too large (which cause System.Web.HttpException: Maximum request length exceeded)?

Thanks
Requesting Gravatar... g Jul 19, 2010 7:56 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
This works, but unless the files are small, it will only frustrate the user.

I still consider SWFUpload the gold standard. Anytime you're uploading files, you need to communicate to the UI that something is happening. The only way to do that is with Flash unfortunately (HTML5 solves this, however).
Requesting Gravatar... Nick K Jul 19, 2010 9:19 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Hi Phil,

Just want to point out that you should be careful with this code, because unless you have some special routing rules in place, you've just introduced a vulnerability! :(

Say I upload a file called haacked.aspx, then I can just browse to <site>/uploads/haacked.aspx and execute whatever c# code I want on your server.

You should probably either:
a) make a note of this in your post so that it doesn't bite people who use this code
b) move the upload path outside of the webroot or
c) include some fancy routing rule to stop this

Cheers :)
Requesting Gravatar... M Jul 19, 2010 10:36 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Thank you for keeping "simple" your focus. We all appreciate it!
Requesting Gravatar... Jordan Jul 19, 2010 10:37 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Fine and all, but who uploads files with postback these days? More useful if the uploads were being done with jQuery/ajax and result handled with json.
Requesting Gravatar... Phil Jul 19, 2010 11:19 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Thanks for the post. It is nice and simple.
Requesting Gravatar... Arun Mahendrakar Jul 19, 2010 9:31 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
Andrei Rinea, the answer to your second question is 'yes'. It does overwrite the first one.

Arun
Requesting Gravatar... bennyb Jul 21, 2010 11:10 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Hi Phil,
What if I wanted to add a few textboxes such as for a freindly file name and short description, are we still going to receive the HttpPostedFileBase?
Requesting Gravatar... Tim Hobbs Jul 21, 2010 6:30 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
@Nick K-

I am pretty sure that App_Data is a "reserved" folder and won't allow any execution of code or anything. I think that is one of the ideas with those folders (App_Code, Bin, etc.): IIS knows better than to allow outside access to the contents.
Requesting Gravatar... haacked Jul 22, 2010 8:49 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
@Tim You are correct. But in fairness to Nick, I made that change to the sample after Nick suggested it. :)
Requesting Gravatar... Imranhussein Jul 23, 2010 8:31 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
@Nick, @haacked
we can validate the file and allow only to upload allowed file ext. Isn't it?
Requesting Gravatar... Morin Jul 26, 2010 4:07 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
NOT RELATED TO THIS ARTICLE:
I have a question and not able to get it answered.

stackoverflow.com/...

I would highly appreciate if anybody can answer this.

Requesting Gravatar... bennyb Jul 26, 2010 1:02 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
So how do you access other form fields e.g. TextBox, TextArea etc. added to this form?
Clearly they are not part of the HttpPostedFileBase.
Requesting Gravatar... Rony Jul 27, 2010 10:40 AM
# re: Uploading a File (Or Files) With ASP.NET MVC
Hi Phil,

I came across an interesting situation in one of my previous projects, HttpPostedFileBase file was NULL only in production and finally came to know that it was because of the IIS7 URL rewrite rules, is there any way you recommend to avoid that?
Requesting Gravatar... Chirag Nirmal Jul 27, 2010 2:12 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
Wow.. I never thought it would be so easy. This is even simpler than asp.net file uploader control.
Requesting Gravatar... Romero Brito Jul 29, 2010 4:12 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
Any ideas about how to get "asynchronous upload progress report" using this technique (for large file uploads)?
Requesting Gravatar... Joshua Hayes Jul 29, 2010 5:34 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
Just did a quick google. Nope, second to Hansleman :p

I like this comment by 'Chirag'

"Wow.. I never thought it would be so easy. This is even simpler than asp.net file uploader control."

So true. ASP.NET MVC is Win!
Requesting Gravatar... Joshua Hayes Jul 29, 2010 5:37 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
Hey Phil,

Love your blog. I read it all the time. It's a bit old school though isn't it? I think you need to make a new one using MVC ;)
Requesting Gravatar... Thanigainathan Jul 29, 2010 11:37 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
Hi,

Article is very nice.
Will this work all the file types. What happens if upload a exe extension.

Thanks,
Thani
Requesting Gravatar... duffy Aug 03, 2010 11:05 PM
# re: Uploading a File (Or Files) With ASP.NET MVC
What if the user only uploads only the second file but leaves the first input field blank. Is there a way to access the id to figure which of the two files arrived at the server?

What do you have to say?

(will show your gravatar)
Please add 3 and 2 and type the answer here: