Last week I was conducting a training for one of my clients on ASP.NET MVC 3 features. They had a file server, hosting various types of reports and were using an ASP.NET Web Form application as a front-end to download the reports on the client machine. Now since they planned on migrating the ASP.NET WebForms to ASP.NET MVC, they expected a similar functionality in MVC too.
As most of you working on ASP.NET MVC know, the Views are directly controlled by controller action. Every action method from the controller class returns an ActionResult. This itself is an abstract class. We have several classes inherited from it and they are used in specific cases. One of the classes inherited from ActionResult is FileResult. This class is used to send binary file content to the response. In the following sample, we will see how we can leverage the FileResult action to download files in an ASP.NET MVC Web Application.
Step 1: Open VS2010 and create a new ASP.NET MVC 3 project, name it as ‘MVC3_Returning_Files’.
Step 2: In the project, add a new folder and name it as ‘Files’. Add couple of PDF files in it.
Step 3: Right-click on the Models folder and add a new class file, name it as ‘DataClasses.cs’. Add the following classes in it:
namespace MVC3_Returning_Files.Models
{
public class DataClasses
{
public List<FileNames> GetFiles()
{
List<FileNames> lstFiles = new List<FileNames>();
DirectoryInfo dirInfo = new DirectoryInfo(HostingEnvironment.MapPath("~/Files"));
int i = 0;
foreach (var item in dirInfo.GetFiles())
{
{
public class DataClasses
{
public List<FileNames> GetFiles()
{
List<FileNames> lstFiles = new List<FileNames>();
DirectoryInfo dirInfo = new DirectoryInfo(HostingEnvironment.MapPath("~/Files"));
int i = 0;
foreach (var item in dirInfo.GetFiles())
{
lstFiles.Add(new FileNames() {
FileId = i + 1, FileName = item.Name, FilePath = dirInfo.FullName+@"\"+item.Name});
i = i + 1;
}
return lstFiles;
}
}
public class FileNames
{
public int FileId { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
}
}
{
public int FileId { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
}
}
The class DataClasses contains ‘GetFiles’ method. This method reads all files from the ‘Files’ folder created in Step 2 and returns a list of files with information as Field, FileName and FilePath declared in FileNames class.
Step 4: Add a new ‘ReportsController’ with the following action methods:
namespace MVC3_Returning_Files.Controllers
{
public class ReportsController : Controller
{
DataClasses objData;
{
public class ReportsController : Controller
{
DataClasses objData;
public ReportsController()
{
objData = new DataClasses();
}
{
objData = new DataClasses();
}
//
// GET: /Reports/
// GET: /Reports/
public ActionResult Index()
{
var files = objData.GetFiles();
return View(files);
}
{
var files = objData.GetFiles();
return View(files);
}
public FileResult Download(string id)
{
int fid = Convert.ToInt32(id);
var files = objData.GetFiles();
string filename = (from f in files
where f.FileId == fid
select f.FilePath).First();
string contentType = "application/pdf";
//Parameters to file are
//1. The File Path on the File Server
//2. The content type MIME type
//3. The parameter for the file save by the browser
return File(filename, contentType,"Report.pdf");
}
}
}
}
The ‘Download’ action method accepts id (FileId) from the view and queries the Files List returned from the GetFiles method. After querying the List of files, it retrieve the file path. It also defines content type which is MIME type defined content header. This information is required by the browser to decide how to handle file. In this case, it is defined as aPDF. The method returns an object of the type ‘FilePathResult’. This is the class inherited from FileResult. FilePathResult accepts three parameters. The first is the file path of the file which is to be downloaded. The second is the content type. The third parameter is the Download file name. This is an optional parameter, but if passed, then the browser will show the download effect.
Step 5: Add a new Index View using Index action which has some Razor code as shown below:
model IEnumerable<MVC3_Returning_Files.Models.FileNames>
@{
ViewBag.Title = "Index";
}
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
FileId
</th>
<th>
FileName
</th>
</tr>
@Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
FileId
</th>
<th>
FileName
</th>
</tr>
@foreach (var item in Model) {
<tr>
<td>
@Html.DisplayFor(modelItem => item.FileId)
</td>
<td>
@Html.DisplayFor(modelItem => item.FileName)
</td>
<td>
@Html.ActionLink("Download", "Download", new { id = item.FileId })
</td>
</tr>
}
<tr>
<td>
@Html.DisplayFor(modelItem => item.FileId)
</td>
<td>
@Html.DisplayFor(modelItem => item.FileName)
</td>
<td>
@Html.ActionLink("Download", "Download", new { id = item.FileId })
</td>
</tr>
}
</table>
Step 6: Add the following Action link in the menucontainer <div> of the _Layout.cshtml:
<li>@Html.ActionLink("Reports", "Index", "Reports")</li>
Step 7: Run the application and you will find the Report menu. After clicking on it, the Index page will display all the Files as shown below:
Click on the Download link and you will get a download box as shown below (Note: I am using IE9)
Conclusion
The FileResult action that comes out of box with ASP.NET MVC3 provides an easy to use abstraction for downloading files in an ASP.NET MVC application.
The entire source code of this article can be downloaded from GitHub
No comments:
Post a Comment