How can I make evoPDF to work as ActionFilterAttribute in ASP.NET MVC

477 views Asked by At

I just need to render PDF from website in ASP.NET MVC. I have found quite interesting article about generating PDF from ASP.NET MVC. I think it could be done even better if the page is rendered through ActionFilterAttribute. My Idea is somesthing like that:

[EnableCompression]
[OutputCache(Duration=7200)]
[EvoPDFFilter]
public ActionResult DownloadAsPDF()
{
    var model= GetModel(); 
    return View(model); //return just HTML and convert it by filter to PDF
}

public class EvoPDFFilterAttribute: ActionFilterAttribute
{
    //some code should be here. Is this solution even possible?
}

It is possible? How should look like the EvoPDFFilterAttribute?

1

There are 1 answers

0
Tomas Kubes On

I finally managed to do it :-)

using EvoPdf;
using System.IO;
using System.Web;
using System.Web.Mvc;


namespace MyProject.Helpers
{
    /// <summary>
    /// PDF filter based on code https://lostechies.com/jimmybogard/2014/02/04/rendering-asp-net-content-as-pdf/
    /// </summary>
    public class EvoPDFFilterAttribute : ActionFilterAttribute
    {

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            HttpRequestBase request = filterContext.HttpContext.Request;
            HttpResponseBase response = filterContext.HttpContext.Response;

            if (response.Filter == null)//RenderAction
                return;

            string acceptEncoding = request.Headers["Accept-Encoding"];
            if (acceptEncoding == null)
                return;


            response.ContentType = "application/pdf";
            var baseUrl = string.Format("{0}://{1}{2}/", request.Url.Scheme, request.Url.Authority, request.ApplicationPath.TrimEnd('/'));
            response.Filter = new PdfFilter(response.Filter, baseUrl);           
        }

        public class PdfFilter : Stream
        {
            private readonly Stream _oldFilter;
            private readonly string _baseUrl;
            private readonly MemoryStream _memStream;

            public override bool CanSeek
            {
                get { return false; }
            }

            public override bool CanWrite
            {
                get { return true; }
            }

            public override bool CanRead
            {
                get { return false; }
            }

            public override long Position
            {
                get { return 0L; }
                set { }
            }

            public override long Length
            {
                get { return 0L; }
            }

            public PdfFilter(Stream oldFilter, string baseUrl)
            {
                _oldFilter = oldFilter;
                _baseUrl = baseUrl;
                _memStream = new MemoryStream();
            }

            public override int Read(byte[] buffer, int offset, int count)
            {
                return 0;
            }

            public override long Seek(long offset, SeekOrigin origin)
            {
                return 0L;
            }

            public override void SetLength(long value)
            {
            }

            public override void Write(byte[] buffer, int offset, int count)
            {
                _memStream.Write(buffer, offset, count);
            }

            public override void Flush()
            {
            }

            public override void Close()
            {
                var converter = new PdfConverter
                {
                    MediaType = "print",
                };
                converter.PdfDocumentOptions.LiveUrlsEnabled = false;

                _memStream.Position = 0;

                converter.SavePdfFromHtmlStreamToStream(_memStream, System.Text.Encoding.UTF8, _baseUrl, _oldFilter);

                _oldFilter.Close();
            }
        }
    }
}