A simple Pdf ActionResult in MVC

Recently, I needed an ActionResult implementation to return the Pdf documents from my Controller Action to MVC views and it tooks few minutes to build the functionality on the existing FileResult.

I decided to build a base class PdfResult to abstract the ContentType implementation as well as it will also serve as a common return type from the action method irrespective of derived implementation like Content, Path etc.

PdfResult Base class

///
/// PdfResult
/// Represents a base class that is used to send PDF file content to the response.
public abstract class PdfResult : FileResult
{
    #region Constructor
     ///
     /// Initializes a new instance of the FileResult class.
     ///

    public PdfResult()
      : base(System.Net.Mime.MediaTypeNames.Application.Pdf)
    {
    }

    #endregion
}

PdfStreamResult It’s one of the implementation class for PdfResult to return the Pdf content as stream on HttpResponse Stream.

///
/// PdfStreamResult
/// Sends binary content to the response by using a Stream instance.
///
public class PdfStreamResult : PdfResult
{
    // Fields
    private const int _bufferSize = 0x1000;

    #region Constructor

    ///
    /// PdfContentResult
    /// Initializes a new instance of the FileStreamResult class.
    ///
    public PdfStreamResult(Stream fileStream)
       : base()
    {
         if (fileStream == null)
         {
             throw new ArgumentNullException("fileStream");
         }
         this.FileStream = fileStream;
    }

    #endregion

    #region Overriden Methods

    ///
    /// WriteFile
    /// Writes the file to the response. (Overrides FileResult.WriteFile(HttpResponseBase).)
    protected override void WriteFile(HttpResponseBase response)
    {
         Stream outputStream = response.OutputStream;
         using (this.FileStream)
         {
              byte[] buffer = new byte[0x1000];
              while (true)
              {
                   int count = this.FileStream.Read(buffer, 0, 0x1000);
                   if (count == 0)
                   {
                       return;
                   }
                   outputStream.Write(buffer, 0, count);
              }
         }
     }

    #endregion

     ///
     /// FileContents
     /// Gets the stream that will be sent to the response.
     public Stream FileStream { get; private set; }
}

PdfPathResult

This implementation class return the Pdf document from a physical Pdf file on the server.


///
/// PdfPathResult
/// Sends the contents of a file to the response.
public class PdfPathResult : PdfResult
{
    #region Constructor

    ///
    /// PdfContentResult
    /// Initializes a new instance of the FilePathResult class by using the specified file name and content type.
    ///
    public PdfPathResult(string fileName)
         : base()
    {
        if (string.IsNullOrEmpty(fileName))
        {
            throw new ArgumentException("Value cannot be null or empty.", "fileName");
        }
        this.FileName = fileName;
    }

    #endregion

    #region Overriden Methods

     ///
     /// WriteFile
     /// Writes the file to the response. (Overrides FileResult.WriteFile(HttpResponseBase).)
     protected override void WriteFile(HttpResponseBase response)
     {
          response.TransmitFile(this.FileName);
     }

     #endregion

     ///
     /// FileContents
     /// Gets the path of the file that is sent to the response.
     public string FileName { get; private set; }
  }

PdfContentResult

This implementation returns the Pdf document out of binary content of Pdf document.


///
/// PdfContentResult
/// Sends the contents of a binary file to the response.
///
public class PdfContentResult : PdfResult
{
    #region Constructor

    ///
    /// PdfContentResult
    /// Initializes a new instance of the PdfContentResult class by using the specified file contents and content type.
    ///
    public PdfContentResult(byte[] fileContents)
        : base()
    {
        if (fileContents == null)
        {
            throw new ArgumentNullException("fileContents");
        }
        this.FileContents = fileContents;
    }

    #endregion

    #region Overriden Methods

    ///
    /// WriteFile
    /// Writes the file content to the response. (Overrides FileResult.WriteFile(HttpResponseBase).)
    protected override void WriteFile(HttpResponseBase response)
    {
      response.OutputStream.Write(this.FileContents, 0, this.FileContents.Length);
    }

    #endregion

    ///
    /// FileContents
    /// The binary content to send to the response.
    public byte[] FileContents { get; private set; }
  }

Controller Extensions

I needed to write these extension to have the calling code look similar to ViewResult or other result types.


///
/// Defines extensions for controllers
public static class ControllerExtensions
{
   #region Pdf Extension method for Controller

   ///
   /// Pdf
   /// Creates a PdfContentResult object by using the file contents, content type, and the destination file name.
   /// The Controller
   /// The binary content to send to the response.
   /// The file name to use in the file-download dialog box that is displayed in the browser.
   /// The file-content result object.
   public static PdfResult Pdf(this Controller controller, byte[] fileContents, string fileDownloadName)
   {
      return new PdfContentResult(fileContents) { FileDownloadName = fileDownloadName };
   }

   ///
   /// Pdf
   /// Creates a PdfStreamResult object using the Stream object, the content type, and the target file name.
   /// The Controller
   /// The stream to send to the response.
   /// The file name to use in the file-download dialog box that is displayed in the browser.
   /// The file-stream result object.
   public static PdfResult Pdf(this Controller controller, Stream fileStream, string fileDownloadName)
   {
       return new PdfStreamResult(fileStream) { FileDownloadName = fileDownloadName };
   }

   ///
   /// Pdf
   /// Creates a PdfPathResult object by using the file name, the content type, and the file download name.
   /// The Controller
   /// The path of the file to send to the response.
   /// The file name to use in the file-download dialog box that is displayed in the browser.
   /// The file-stream result object.
   public static PdfResult Pdf(this Controller controller, string fileName, string fileDownloadName)
   {
        return new PdfPathResult(fileName) { FileDownloadName = fileDownloadName };
   }

   #endregion
}

Example

PdfStreamResult

public PdfResult DownloadPdf()
{
   Stream fileStream = ...; //initialization code to initialize the stream with Pdf File.
   return this.Pdf(fileStream, "Sample.pdf");
}

PdfPathResult


public PdfResult DownloadPdf()
{
    string filePath = ; //initialization code to initialize the string with Pdf File Path.
    return this.Pdf(filePath, "Sample.pdf");
}

PdfContentResult


public PdfResult DownloadPdfContent()
{
    string filePath = ; //initialization code to initialize the string with Pdf File Path.
    byte[] pdfBytes = System.IO.File.ReadAllBytes(filePath);
    return this.Pdf(pdfBytes, "sample.pdf");
    return pdfContent;
}
Posted in MVC | Tagged , | 14 Comments