Introduction
In most of the ASP.NET MVC applications, there is a need for uploading file/files on server. We save that file information in database or save the file on the server in a particular folder. If we need to provide the file upload functionality in only one place, then it’s easy. But if we need to provide this functionality in many places, then the code for getting the file/files information and saving it gets duplicated in multiple places in our application. To avoid the duplication of code and simplify the file/files upload procedure, let`s create a simple action filter.
Getting Started
To get started, open visual studio and select File- Project option. It will open up a new project dialog box as shown below (F: 1).
Select the ASP.NET Web Application option and enter the name of the project as FileUploadDemo and then click on Ok button. After clicking on Ok button, Project Template window will popup as shown below (F: 2).
Select the MVC project template and click on Ok button. After clicking on OK button, ASP.NET MVC application will be created.
Before moving on to the actual implementation of action filter, let`s create some simple extension methods and some simple classes, which will help us in creating an action filter.
Let`s first start with creating a simple class called as FileInformation.cs. Add this class in Models folder in our application. Definition of FileInformation class is as follows.
- namespace FileUploadDemo.Models
- {
- public class FileInformation
- {
- public string FileName { get; set; }
- public string ContentType { get; set; }
- public string FileExtension { get; set; }
- public byte[] BinaryData { get; set; }
- }
- }
We will use the above class in one of our extension method.
Now add a new folder in our project called ExtensionMethods. Add a new class in that folder called as HttpPostedFileBaseExtensionMethods and make that class as static (For extension methods class must be static).
Code for our extension methods is as follows.
- using FileUploadDemo.Models;
- using System.IO;
- using System.Web;
-
- namespace FileUploadDemo.ExtensionMethods
- {
- public static class HttpPostedFileBaseExtensionMethods
- {
- public static string GetFileName(this HttpPostedFileBase file)
- {
- return file.FileName;
- }
-
- public static string GetContentType(this HttpPostedFileBase file)
- {
- var contentType = file.ContentType;
- return contentType;
- }
-
- public static byte[] GetBinaryData(this HttpPostedFileBase file)
- {
- var fileBinary = new byte[file.InputStream.Length];
- file.InputStream.Read(fileBinary, 0, fileBinary.Length);
- return fileBinary;
- }
-
- public static string GetFileExtension(this HttpPostedFileBase file)
- {
- return Path.GetExtension(GetFileName(file));
- }
-
- public static FileInformation GetFileInformation(this HttpPostedFileBase file)
- {
- return new FileInformation()
- {
- FileName = GetFileName(file),
- ContentType = GetContentType(file),
- FileExtension = GetFileExtension(file),
- BinaryData = GetBinaryData(file)
- };
- }
- }
- }
All extension methods are created for HttpPostedFileBase object. This object provides access to individual file that have been uploaded by a client. Now let`s understand each extension method.
- GetFileName – It will return the name of the uploaded file.
- GetContentType – It will return the content type (MIME type) for the uploaded file. For example for jpeg image file, content type will be image/jpeg.
- GetBinaryData – It will convert the binary information of a file into a byte array which we can use to save the file information in a table.
- GetFileExtension – It will return the extension for the uploaded file. For example for png image file, it will return .png.
- GetFileInformation – This method returns an object of type FileInformation which contain the information like filename, content type, file extension and byte array data for a single uploaded file.
Now let`s move on to the interesting part of creating an action filter for uploading a file. Add a new folder to our project called as Filters. Add a new class in that folder called as UploadFileAttribute.cs. Code for UploadFileAttribute.cs file is as shown below.
- using FileUploadDemo.Models;
- using System.Collections.Generic;
- using System.Web.Mvc;
- using FileUploadDemo.ExtensionMethod;
-
- namespace FileUploadDemo.Filters
- {
- public class UploadFileAttribute: ActionFilterAttribute
- {
- public override void OnActionExecuting(ActionExecutingContext filterContext)
- {
- var fileInformation = new List<FileInformation>();
-
- if (filterContext != null)
- {
- var request = filterContext.HttpContext.Request;
- if (request != null && request.Files.Count > 0)
- {
- foreach (string uploadedFile in request.Files)
- {
- if (request.Files[uploadedFile].ContentLength > 0)
- {
- var fileInfo = request.Files[uploadedFile].GetFileInformation();
- fileInformation.Add(fileInfo);
- }
- }
- }
- filterContext.ActionParameters["uploadedFiles"] = fileInformation;
- }
- base.OnActionExecuting(filterContext);
- }
- }
- }
Now let`s go through the code to understand the implementation details.
- As we are creating an action filter, we need to inherit from IActionFilter interface which has two methods OnActionExecuted and OnActionExecuting.
- We need to focus on OnActionExecuting method. Because we need to process the uploaded files before the execution of an action method in controller.
- Instead of directly implementing IActionFilter interface, we are using the ActionFilterAttribute class, which provides the default implementation for IActionFilter interface.
- ActionFilterAttribute class is an abstract class, so to provide the implementation details for OnActionExecuting method, we overridden that method in our UploadFileAttribute class.
- OnActionExecuting method has a parameter called filterContext which is of type ActionExecutingContext. Using this parameter, we can get the information about the current request object and thus the uploaded files.
- Using request.Files property, we are getting the collection of all the files that are uploaded by client. Each file in this collection is of type HttpPostedFileBase. Then in for each loop, we are using our GetFileInformation extension method to extract the information like filename, content type, byte array and file extension for the file and adding it to list variable named as fileInformation. This list is of type List of FileInformation which we have created at the beginning of the method.
- Now our fileInformation list variable contains the information about all the uploaded files. Then we are using the ActionParameters property of filterContext object to set our list variable (fileInformation) as a parameter to the called action method. Name of the parameter that we need to add to action method will be uploadedFiles which will be of type List<FileInformation>.
Testing:
This is a very important step. To see the actual working of our filter, I have created a photo gallery application. In this application, we can upload images for photo gallery through an upload form and then these images are displayed as a list in photo gallery. For uploading the images, our UploadFile filter is used. All the information regarding the image like Title, image data etc is stored in database.
Code for the photo gallery application which is used for testing the upload file filter is attached with this article. This application also contains the scripts for creating the tables.
This application has a controller called GalleryController, which is used for saving the uploaded images and display the uploaded images in photo gallery. Let`s set a break point at the first line in Create action method of GalleryController having HttpPost and our UploadFile attribute applied to it and run the application in debug mode. After running the application, let`s navigate to http://localhost:<PORTNUMBER>/Gallery/Create route. We will get a form for uploading the images. Let`s enter the details as shown below (F: 3)
After entering the required details, when we click on Add button we will hit our break point in Create action method.
As we can see in above image, we get all the information regarding the uploaded file like file name, file extension, content type and binary data in uploadedFiles parameter of action method. This is the same parameter that we have added through our UploadFile action filter.
Conclusion:
In this article, we talked about how a simple action filter can be used to the information of uploaded files and reduce the code duplication. I hope you enjoyed reading the article. If you have any suggestions, please let me know through comments. It will be very helpful for me.
Happy Coding!
Read more articles on ASP.NET: