Better way to merge pdfs I am trying to merge two pdfs - one from a razor view and one from a file on the server.  To create the pdf from the razor view I have used the following nuget package: MVCRazorToPDF.

Unfortunately this didn't allow me to merge an existing file with the pdf so I have downloaded the project and changed the PdfActionResult to accept a mergeFilename.

I then generate the new pdf using the following:

public byte[] GeneratePdfOutput(ControllerContext context, object model = null, string viewName = null,
    Action&lt;PdfWriter, Document&gt; configureSettings = null, string filename = null)
{
    byte[] output;

    if (!string.IsNullOrEmpty(filename) &amp;&amp; File.Exists(filename))
    {
        using (var copyDoc = new Document())
        {
            using (var copyStream = new MemoryStream())
            {
                copyDoc.Open();

                PdfCopy copy = new PdfCopy(copyDoc, copyStream);
                copy.CloseStream = false;
                copy.AddDocument(new PdfReader(GetBytes(context, model, viewName, configureSettings)));

                using (var reader = new PdfReader(filename))
                {
                    reader.ConsolidateNamedDestinations();

                    for (int i = 1; i &lt;= reader.NumberOfPages; i++)
                    {
                        PdfImportedPage page = copy.GetImportedPage(reader, i);
                        copy.AddPage(page);
                    }
                }

                copy.Close();
                copyDoc.Close();
                output = copyStream.ToArray();
            }
        }
    }
    else
    {
        output = GetBytes(context, model, viewName, configureSettings);
    }

    return output;
}

private byte[] GetBytes(ControllerContext context, object model = null, string viewName = null, Action&lt;PdfWriter, Document&gt; configureSettings = null)
{
    if (viewName == null)
    {
        viewName = context.RouteData.GetRequiredString("action");
    }

    context.Controller.ViewData.Model = model;

    using (var document = new Document())
    {
        using (var workStream = new MemoryStream())
        {
            PdfWriter writer = PdfWriter.GetInstance(document, workStream);
            writer.CloseStream = false;

            if (configureSettings != null)
            {
                configureSettings(writer, document);
            }

            document.Open();

            using (var reader = new StringReader(RenderRazorView(context, viewName)))
            {
                XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, reader);
                document.Close();
                return workStream.ToArray();
            }
        }
    }
}


I was wondering if there was anyway to do this so that the GetBytes was part of the first function - ie I open a new document and then add the razor and if there is a file on the server, I add that using the same memory stream and document (rather than having to create new ones), without the need for the else
If you change the first line from  


byte[] output;  



to  

byte[] output = GetBytes(context, model, viewName, configureSettings);  


and then revert the if condition you can return early.   

So the remaining code (if the filename is valid and the file exists) could become  


by stacking the usings which saves some horizontal spacing 
by using the byte[] output for the PdfReader ctor  
and using copyStream.GetBuffer() instead of calling its ToArray() method which eleminates the creation of an additional array  


like so  

public byte[] GeneratePdfOutput(ControllerContext context, object model = null, string viewName = null,
    Action&lt;PdfWriter, Document&gt; configureSettings = null, string filename = null)
{
    byte[] output = GetBytes(context, model, viewName, configureSettings);  

    if (string.IsNullOrEmpty(filename) || !File.Exists(filename))
    {
        return output;
    }

    using (var copyDoc = new Document())
    using (var copyStream = new MemoryStream())
    {
        copyDoc.Open();

        PdfCopy copy = new PdfCopy(copyDoc, copyStream);
        copy.CloseStream = false;
        copy.AddDocument(new PdfReader(output));

        using (var reader = new PdfReader(filename))
        {
            reader.ConsolidateNamedDestinations();

            for (int i = 1; i &lt;= reader.NumberOfPages; i++)
            {
                PdfImportedPage page = copy.GetImportedPage(reader, i);
                copy.AddPage(page);
            }
        }

        copy.Close();
        copyDoc.Close();
        return copyStream.GetBuffer();
    }
}