Sunday, June 2, 2013

How to Implement a File Upload RESTful Web Service with ASP.NET MVC

In this post we will create a basic web service that allows clients to upload or post binary files. This is a common feature to allow your apps to upload and share photos from mobile apps or the like. We will use ASP.NET MVC to create the service, and demonstrate how simple it is.

Fire up Visual Studio and create a basic ASP.NET MVC application. For this sample Ill be using Visual Studio 2012 and ASP.NET MVC 4.0 on a Windows 8 development machine. Additionally, I’ll be using Fiddler 4 beta for testing the service.

image

image

image

Now, let’s create a simple controller with its view, so we can run and test the service. Create a new empty controller named TestController. We won’t be doing anything especial on it, we just need to have the endpoint and its view available.

image

image

Then, create a new view for the TestController. Within the Views folder, create a new folder named “Test” and then right click, select Add, and then View. Name the view index. Then modify the view’s code so we can differentiate it from the default views.

image

image    image

Compile and run the application to make sure everything is running so far. Since we don’t have a default home controller, when the page loads on the root URL, you will see an error page.

image

Once you add the “/test” route in the address bar, the app will resolve to our TestController and will display its view.

image

Ok, lets quickly code the file upload service so we have it ready. Create a new controller as we did before and name it FileUploadController.

image

The code for the file upload is as follows (base code courtesy of my good colleague Herber Madrigal):

  1: public class FileUploadController : Controller
  2: {
  3:     //
  4:     // GET: /FileUpload/
  5:     //[HttpPost]
  6:     public ActionResult Index()
  7:     {
  8:         var fileUploaded = false; 
  9: 
 10:         foreach (string upload in Request.Files)
 11:         {
 12:             if (!HasFile(Request.Files[upload]))
 13:                 continue;
 14: 
 15:             string path = Path.Combine(
 16:                           AppDomain.CurrentDomain.BaseDirectory, 
 17:                           "uploads");
 18:             string filename = Path.GetFileName(
 19:                               Request.Files[upload].FileName);
 20: 
 21:             if (!Directory.Exists(path))
 22:                 Directory.CreateDirectory(path);
 23: 
 24:             Request.Files[upload].SaveAs(Path.Combine(
 25:                                          path, 
 26:                                          filename));
 27: 
 28:             fileUploaded = true;
 29:         }
 30: 
 31:         this.ViewData.Add("uploaded", fileUploaded);
 32: 
 33:         return View();
 34:     }
 35: 
 36:     private static bool HasFile(HttpPostedFileBase file)
 37:     {
 38:         return (file != null && file.ContentLength > 0) ? true : false;
 39:     }
 40: 
 41: }

The service will try to retrieve the files being posted. It will verify that the file is present, and if so, it will save it within the “uploads” folder in the local machine, using the original file name. The request is of type HttpRequestBase, which contains a handy property called Files. The property gives you a collection of files that were uploaded by the client, in multipart MIME format. The collection is of type HttpFileCollection, and each item is of type HttpPostedFile. The code uses a helper function to determine if the request effectively has or not a file. Additionally we use a simple flag to communicate if a file was received and saved, so we can display a message in the view.


Let’s create a default view for the FileUploadController. Create a new FileUpload folder inside the Views folder, and then add a new view and name it index.


image    image 


Let’s modify the view so we can display a meaningful message and and also indicate if a file was actually received and stored or not.


image


Let’s give it a quick test by running the app and executing the file upload action by entering “/fileupload” in the address bar. Remember that you can debug the actions by placing breakpoints into your controller’s code. The view should display the message “File received: False” since we are not submitting any file.


image


image


Now, let’s test the file upload. For this purpose, I’ll be using Fiddler. Run the app and go to the compose tab. Select Post as the HTTP method, enter the URL for the FileUpload action, and use the “Upload File” functionality to include a local file in the request (tip: you can go to the filters tab and check the option to track only traffic coming from localhost).


image


Once you execute the post, you should be able to debug the FileUpload action on the MVC project. Check to make sure you are receiving the correct file you posted with Fiddler and that that file content is not null.


image


image


After executing the HTTP request, you should see a 200 response in fiddler and the file being saved in the newly created “uploads” folder inside your MVC solution folder.


image


image


That all for now. You have a web service accepting file upload requests now. We were able to test that the service is running and responding, and also test an actual file upload using Fiddler. The next step is to create actual client apps that connect and upload to the service, which hopefully I’ll share soon.


You can download the sample application from my Github repo here.

2 comments:

  1. Good example. Thank you. I will elaborate on it further.

    ReplyDelete
  2. HI!
    Thank you.
    How can I use this service in my domain?

    ReplyDelete