0

The below code is initiated from my "export" li tag, which changes a FusionChart to an SVG string and then passes it to my controller via an ajax call.

The problem I have is that it hits the controller, runs through the code right till the end and "Success" is displayed by the alert, but no popup is displayed to save the pdf ?

I have grabbed the entire HTML string and put into notepad, saved as html and everything displays as it should, but simply will not work when running from the controller and popping up the save message...

Am I missing something ? or doing something wrong, or anything that is not best practice ?

I have the following that is calling a javascript function:

<li id="export" style="font-size:13px"><a onclick="svgString()">Rotativa Export</a></li>

Here is my javascript that is making the AJAX call:

function svgString() {
                var ChartSVG = new Array(10);
                var text = document.createTextNode(savingsChart.getSVGString());
                document.getElementById("msg").appendChild(text);

                ChartSVG = chunkSubstr(document.getElementById("msg").innerHTML, 10);

                var Details =
                  {
                      "fkiProjectID" : @Model.fkiProjectID,
                      "ChartSVG": ChartSVG
                  };

                $.ajax({

                    url: '/Profile/ExportCombinedPDF',
                    data: JSON.stringify(Details),
                    type: 'POST',
                    contentType: 'application/json; charset=utf-8',
                    success: function (data) {
                        alert("Success : " + data);
                    },
                    error: function(data){
                        alert("Error: " + data);
                    }
                });
            }

document.getElementById("export").addEventListener("click", svgString);

function chunkSubstr(str, size) {
            var numChunks = Math.ceil(str.length / size),
                chunks = new Array(size);

            //alert(str.length);

            for(var i = 0, o = 0; i < size; ++i, o += numChunks) {
                chunks[i] = str.substring(o, o + numChunks);

                //alert(o + " " + numChunks);
            }

            return chunks;
        }

Controller:

public FileStreamResult ExportCombinedPDF(CalculatedOutputViewModel CVM)
        {
            List<PipelineDetails> PipeList = new List<PipelineDetails>();
            ProjectManager PM = new ProjectManager();

            PipeList = PM.GetPipelineList(CVM.fkiProjectID);

            string webgridstyle = PM.Pipeline_HtmlForExport(CVM.fkiProjectID);
            string ProjectHtml = PM.Project_HtmlForExport(CVM.fkiProjectID);
            string chartcontent = ExportRotativaPDF2(CVM);

            WebGrid grid = new WebGrid(source: PipeList, canPage: false, canSort: false);
            string gridHtml = grid.GetHtml(tableStyle: "webGrid",
                                           headerStyle: "webGridHeader",
                                           alternatingRowStyle: "webGridAlt",
                    columns: grid.Columns(
                     grid.Column("NodeNumber", "Node Nr."),
                     grid.Column("Accumulated_Length", "Accumulated Length"),
                     grid.Column("Elevation", "Elevation"),
                     grid.Column("Pipe_Outside_Diameter", "Pipe Outside Diameter"),
                     grid.Column("Wall_Thickness", "Wall Thickness"),
                     grid.Column("Control_Point_Description", "Control Point Description"),
                     grid.Column("Control_Point_Size", "Control Point Size"))).ToString();

            string exportData = String.Format("<html><body>{0}{1} <p style='page-break-after:always;'></p> {2} {3}</body></html>", "<style>" + webgridstyle + "</style>", ProjectHtml, gridHtml, chartcontent);

            var bytes = System.Text.Encoding.UTF8.GetBytes(exportData);
            using (var input = new MemoryStream(bytes))
            {
                var output = new MemoryStream();
                var document = new iTextSharp.text.Document(PageSize.A4, 50, 50, 50, 50);
                var writer = PdfWriter.GetInstance(document, output);

                PdfPTable table = new PdfPTable(1);

                table.HeaderRows = 1;

                Font headerFont = FontFactory.GetFont("Verdana", 10);
                Font rowfont = FontFactory.GetFont("Verdana", 10);

                writer.CloseStream = false;
                document.Open();

                var xmlWorker = iTextSharp.tool.xml.XMLWorkerHelper.GetInstance();
                xmlWorker.ParseXHtml(writer, document, input, System.Text.Encoding.UTF8);

                document.Add(table);
                document.Close();
                output.Position = 0;

                return File(output, "application/pdf", "Pipeline_Report.pdf");

                //return new FileStreamResult(output, "application/pdf");
            }

        }

If anyone is able to help, Thanks!

AxleWack
  • 1,801
  • 1
  • 19
  • 51
  • http://stackoverflow.com/a/23797348/307976 – vtortola Oct 05 '16 at 12:19
  • Do not use ajax. Simply do open the url you use for the download endpoint in a browser tab.(hint : window.open method) – Shyju Oct 05 '16 at 12:22
  • The problem I am sitting with is that I need to use Javascript to get the FusionChart to an SVG string(and broken up into an array) and then I have functions I call from my controller to build an html string that needs to be exported to pdf. If I am able to pass this ChartSVG array to the controller with out using an ajax call, that would be great..If this is possible ? – AxleWack Oct 05 '16 at 12:32
  • Thanks vtortola & Shyju. I looked into passing via a url, but ran into a problem where the URL exceeded its max length. The ChartSVG(Array) is a MASSIVE string(around 98k characters). – AxleWack Oct 05 '16 at 14:02

2 Answers2

0

remove this code

using (var input = new MemoryStream(bytes))
{
      // using keyword dispose your stream value before return      
}

add like this

 var input = new MemoryStream(bytes);
0

So I was able to sort this out. I needed to change the way I did things a little, but ultimately it worked.

So the following is what I did :

  1. Clicked on button that called my JavaScript Function and used an ajax call that displayed a partial view as a modal. The modal then opens up after the ajax call is complete
  2. On this partial view, I have a button to "print". I then submit the Model back to my controller and then build the stringin that action result.
  3. I then use Rotativa ViewAsPdf that then displays the save dialog.

Not EXACTLY how I wanted it, but the result is exactly as I wanted.

The code is below :

View:

This is my Modal and button underneath it

<div class="modal fade" id="PrintModel" tabindex="-1" role="dialog" aria-labelledby="myPrintModalLabel">
    <div class="modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
                @*<h4 class="modal-title" id="myEditModalLabel">Update Pipeline Details</h4>*@
            </div>
            <div class="modal-body">
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-default3" data-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

<div>
    <button id="get" data-loading-text="Preparing..." type="button" class="btn btn-default2" data-dismiss="modal">Prepare for Print</button>
</div>

JavaScript(With the FusionChart part being rendered):

FusionCharts.ready(function () {
            var savingsChart = new FusionCharts({
                id: 'chart-1',
                type: "scatter",
                renderAt: "chart-container",
                width: "1000",
                height: "500"
            });
            savingsChart.setTransparent(false);
            savingsChart.setXMLUrl(window.location.protocol + "//" + window.location.host + "/Profile/getGraphXMLData/" + @Model.fkiProjectID);
            savingsChart.render("chart-container");

            function svgString() {
                var ChartSVG = new Array(10);
                var text = document.createTextNode(savingsChart.getSVGString());
                document.getElementById("msg").appendChild(text);

                ChartSVG = chunkSubstr(document.getElementById("msg").innerHTML, 10);

                //alert("Reached : Before Ajax Call");

                var Details =
                  {
                      "fkiProjectID" : @Model.fkiProjectID,
                      "ChartSVG": ChartSVG
                  };

                $.ajax({
                    url: '/Profile/PrepareForPrint',
                    data: JSON.stringify(Details),
                    type: 'POST',
                    contentType: 'application/json; charset=utf-8',
                    success: function (data) {
                        var m = $('#PrintModel');
                        m.find('.modal-body').html(data);
                        m.modal('show');

                    }
                });
            }

            document.getElementById("get").addEventListener("click", svgString);
            //document.getElementById("rotativaexport").addEventListener("click", svgString);


        });

Controller

public ActionResult PrepareForPrint(CalculatedOutputViewModel model)
        {
            CalculatedOutputViewModel CVM = new CalculatedOutputViewModel();

            CVM.fkiProjectID = model.fkiProjectID;
            CVM.ChartSVG = model.ChartSVG;

            return PartialView("_partialPrintPDF", model);
        }

        public string ExportCombinedPDF(CalculatedOutputViewModel CVM)
        {
            List<PipelineDetails> PipeList = new List<PipelineDetails>();
            ProjectManager PM = new ProjectManager();

            PipeList = PM.GetPipelineList(CVM.fkiProjectID);

            string webgridstyle = PM.Pipeline_HtmlForExport(CVM.fkiProjectID);
            string ProjectHtml = PM.Project_HtmlForExport(CVM.fkiProjectID);
            string chartcontent = ExportRotativaPDF2(CVM);

            WebGrid grid = new WebGrid(source: PipeList, canPage: false, canSort: false);
            string gridHtml = grid.GetHtml(tableStyle: "webGrid",
                                           headerStyle: "webGridHeader",
                                           alternatingRowStyle: "webGridAlt",
                    columns: grid.Columns(
                     grid.Column("NodeNumber", "Node Nr."),
                     grid.Column("Accumulated_Length", "Accumulated Length"),
                     grid.Column("Elevation", "Elevation"),
                     grid.Column("Pipe_Outside_Diameter", "Pipe Outside Diameter"),
                     grid.Column("Wall_Thickness", "Wall Thickness"),
                     grid.Column("Control_Point_Description", "Control Point Description"),
                     grid.Column("Control_Point_Size", "Control Point Size"))).ToString();

            //string exportData = String.Format("<html><body>{0}{1} <p style='page-break-after:always;'></p> {2}{3}</body></html>", "<style>" + webgridstyle + "</style>", ProjectHtml, gridHtml, chartcontent);
            string exportData = String.Format("{0}{1} <br> {2} <br> {3}", "<style>" + webgridstyle + "</style>", ProjectHtml, gridHtml, chartcontent);

            return exportData;

        }

        public ActionResult DownloadPDF(CalculatedOutputViewModel CVM)
        {
            try
            {
                var model = new GeneratePDFModel();

                string pdfContent = ExportCombinedPDF(CVM);

                //get the information to display in pdf from database
                //for the time
                //Hard coding values are here, these are the content to display in pdf 
                var content = "<h2>WOW Rotativa<h2>" +
                 pdfContent;
                //var logoFile = @"/Images/logo.png";

                model.PDFContent = content;
                //model.PDFLogo = Server.MapPath(logoFile);

                //Use ViewAsPdf Class to generate pdf using GeneratePDF.cshtml view
                return new Rotativa.ViewAsPdf("GeneratePDF", model) { FileName = "firstPdf.pdf" };
            }
            catch (Exception ex)
            {
                throw;
            }
        }

Partial View

@model AirFlo_Size_Programme.Models.CalculatedOutputViewModel

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <meta name="viewport" content="width=device-width" />
</head>
<body>
@using (Html.BeginForm("DownloadPDF", "Profile"))
{
    for (var i = 0; i < Model.ChartSVG.Length; i++)
    {
        @Html.HiddenFor(model => model.ChartSVG[i])
    }

    @*@Html.HiddenFor(model => model.ChartSVG)*@
    @Html.HiddenFor(model => model.fkiProjectID)

    <div>
        @if (@Model.ChartSVG == null)
        {
            <button type="submit" data-loading-text="Preparing..." class="edit-user display-mode btn btn-default2">Prepare for Print</button>
        }
        else
        {
            <button type="submit" data-loading-text="Printing..." class="edit-user display-mode btn btn-default2">Print</button>
        }
    </div>



}
</body>
</html>

I know that this is not IDEAL...But it works.

Hope this helps anyone else if facing the same issue.

AxleWack
  • 1,801
  • 1
  • 19
  • 51