2016-05-12 9 views
1

Ich entwickle eine Website mit asp.net/C#/HTML5/bootstrap. Eine der Anforderungen besteht darin, Dokumente in Excel und/oder PDF exportieren zu lassen. Ich bin in der Lage (erfolgreich) zu exportieren, das folgende Snippet verwenden (dies ist der Excel-Schnipsel):Exportieren mit HttpContext.Current.Response verursacht Probleme

 HttpContext.Current.Response.ContentType = "application/octet-stream"; 
     HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8; 
     HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + filename); 
     HttpContext.Current.Response.BinaryWrite(xlsBytes); 
     HttpContext.Current.Response.Flush(); 
     HttpContext.Current.Response.End(); 

Das Problem, das ich habe, ist, dass nach dieser läuft, wie es scheint die Seite Lebenszyklus tot zu stoppen in seinen Spuren. Als Beispiel klickt der Benutzer auf die Schaltfläche Export, die JavaScript-Aufrufe, die das Formular ein "Bitte warten" modalen Dialog und legt wirft:

<script src="../Scripts/waitingFor.js"></script> 

<script type="text/javascript"> 
    function pleaseWait() { 
     waitingDialog.show("Building File<br/>...this could take a minute", { dialogSize: "sm", progressType: "warning" }); 

     form = document.getElementById("frm_contentMaster"); 
     form.submit(); 
    } 
</script> 

Die Javascript-Include-Datei:

/** 
* Module for displaying "Waiting for..." dialog using Bootstrap 
* 
* @author Eugene Maslovich <[email protected]> 
*/ 

(function (root, factory) { 
    'use strict'; 

    if (typeof define === 'function' && define.amd) { 
     define(['jquery'], function ($) { 
      return (root.waitingDialog = factory($)); 
     }); 
    } 
    else { 
     root.waitingDialog = root.waitingDialog || factory(root.jQuery); 
    } 
}(this, function ($) { 

'use strict'; 

/** 
* Dialog DOM constructor 
*/ 
function constructDialog($dialog) { 
    // Deleting previous incarnation of the dialog 
    if ($dialog) { 
     $dialog.remove(); 
    } 
    return $(
     '<div id="waitingFor" class="modal fade" data-backdrop="static" data-keyboard="false" tabindex="-1" role="dialog" aria-hidden="true" style="padding-top:15%; overflow-y:visible;">' + 
      '<div class="modal-dialog modal-m">' + 
       '<div class="modal-content">' + 
        '<div class="modal-header" style="display: none;"></div>' + 
        '<div class="modal-body">' + 
         '<div class="progress progress-striped active" style="margin-bottom:0;">' + 
          '<div class="progress-bar" style="width: 100%"></div>' + 
         '</div>' + 
        '</div>' + 
       '</div>' + 
      '</div>' + 
     '</div>' 
    ); 
} 

// Dialog object 
var $dialog; 

return { 
    /** 
    * Opens our dialog 
    * @param message Custom message 
    * @param options Custom options: 
    * options.headerText - if the option is set to boolean false, 
    *  it will hide the header and "message" will be set in a paragraph above the progress bar. 
    *  When headerText is a not-empty string, "message" becomes a content 
    *  above the progress bar and headerText string will be set as a text inside the H3; 
    * options.headerSize - this will generate a heading corresponding to the size number. Like <h1>, <h2>, <h3> etc; 
    * options.headerClass - extra class(es) for the header tag; 
    * options.dialogSize - bootstrap postfix for dialog size, e.g. "sm", "m"; 
    * options.progressType - bootstrap postfix for progress bar type, e.g. "success", "warning"; 
    * options.contentElement - determines the tag of the content element. 
    *  Defaults to "p", which will generate a <p> tag; 
    * options.contentClass - extra class(es) for the content tag. 
    */ 
    show: function (message, options) { 
     // Assigning defaults 
     if (typeof options === 'undefined') { 
      options = {}; 
     } 
     if (typeof message === 'undefined') { 
      message = 'Loading'; 
     } 
     var settings = $.extend({ 
      headerText: '', 
      headerSize: 3, 
      headerClass: '', 
      dialogSize: 'm', 
      progressType: '', 
      contentElement: 'p', 
      contentClass: 'content', 
      onHide: null // This callback runs after the dialog was hidden 
     }, options), 
     $headerTag, $contentTag; 

     $dialog = constructDialog($dialog); 

     // Configuring dialog 
     $dialog.find('.modal-dialog').attr('class', 'modal-dialog').addClass('modal-' + settings.dialogSize); 
     $dialog.find('.progress-bar').attr('class', 'progress-bar'); 
     if (settings.progressType) { 
      $dialog.find('.progress-bar').addClass('progress-bar-' + settings.progressType); 
     } 

     // Generate header tag 
     $headerTag = $('<h' + settings.headerSize + ' />'); 
     $headerTag.css({ 'margin': 0 }); 
     if (settings.headerClass) { 
      $headerTag.addClass(settings.headerClass); 
     } 

     // Generate content tag 
     $contentTag = $('<' + settings.contentElement + ' />'); 
     if (settings.contentClass) { 
      $contentTag.addClass(settings.contentClass); 
     } 

     if (settings.headerText === false) { 
      $contentTag.html(message); 
      $dialog.find('.modal-body').prepend($contentTag); 
     } 
     else if (settings.headerText) { 
      $headerTag.html(settings.headerText); 
      $dialog.find('.modal-header').html($headerTag).show(); 

      $contentTag.html(message); 
      $dialog.find('.modal-body').prepend($contentTag); 
     } 
     else { 
      $headerTag.html(message); 
      $dialog.find('.modal-header').html($headerTag).show(); 
     } 

     // Adding callbacks 
     if (typeof settings.onHide === 'function') { 
      $dialog.off('hidden.bs.modal').on('hidden.bs.modal', function() { 
       settings.onHide.call($dialog); 
      }); 
     } 
     // Opening dialog 
     $dialog.modal(); 
    }, 
    /** 
    * Closes dialog 
*/ 
    hide: function() { 
     if (typeof $dialog !== 'undefined') { 
      $dialog.modal('hide'); 
     } 
    } 
}; 
})); 

I‘ m NPOI mit der Excel-Datei im Code erstellen hinter (vereinfachte Funktion):

using NPOI.SS.UserModel; 
using NPOI.XSSF.UserModel; 

protected void exportExcel() 
{ 
    XSSFWorkbook wb = new XSSFWorkbook(); 

    XSSFSheet sh = (XSSFSheet)wb.CreateSheet("Legend"); 

    //***************************************** 
    //* Workbook Download & Cleanup 
    //***************************************** 
    MemoryStream stream = new MemoryStream(); 
    wb.Write(stream); 
    stream.Dispose(); 

    var xlsBytes = stream.ToArray(); 
    string filename = "Behavior Stats YTD.xlsx"; 

    MemoryStream newStream = new MemoryStream(xlsBytes); 

    HttpContext.Current.Response.ContentType = "application/octet-stream"; 
    HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8; 
    HttpContext.Current.Response.AddHeader("content-disposition", "attachment; filename=" + filename); 
    HttpContext.Current.Response.BinaryWrite(xlsBytes); 
    HttpContext.Current.Response.Flush(); 
    HttpContext.Current.Response.End(); 
} 

Dies schafft die Excel-Datei und schiebt es den Benutzer, aber der Lebenszyklus des Codes hinter nicht cont inue - es stoppt sofort nach dem Ende-Befehl. Wenn ich die HttpContext-Zeilen auskommentiere, wird offensichtlich das Excel-Blatt nicht erstellt, aber der Lebenszyklus der Seite wird fortgesetzt - der Rest des Codes wird ausgeführt, die Seite wird aktualisiert und der modale Please Wait-Dialog verschwindet.

Also verwende ich das falsch? Die meisten Beispiele, die ich beim Export gesehen habe, verwenden diese Methode. Gibt es eine andere Möglichkeit, die ich exportieren kann, die sauberer und/oder sicherer ist? Gibt es nur eine einfache Änderung, die ich machen muss, damit der Lebenszyklus weitergeht? Wer hat Flüssigseife hergestellt und warum?

Jede Hilfe, die Sie zur Verfügung stellen können, wäre sehr, sehr geschätzt.

Antwort

0

Es funktioniert genau so, wie es sollte. Sie sagen dem Browser, dass die Antwort eine Datei ist. Die Antwort kann immer nur eine Sache sein. Sie können keinen Seiteninhalt und keine Datei in derselben Antwort haben.

Sie können die beiden trennen, indem Sie die Datei in einem IFrame herunterladen. Stellen Sie zuerst Ihren Datei-Download-C# -Code auf eine eigene Seite. Rufen Sie dann diese Seite von einem IFrame mit einer JavaScript-Funktion auf.

function DownloadExcel() { 
    var downloadFrame = document.createElement("IFRAME"); 

    if (downloadFrame != null) { 
     downloadFrame.setAttribute("src", '/DownloadExcel.aspx'); 
     downloadFrame.style.width = "0px"; 
     downloadFrame.style.height = "0px"; 
     document.body.appendChild(downloadFrame); 
    } 
} 
+0

Ich kann Ihnen aufrichtig nicht genug danken, dies hat mich Kopfschmerzen für die längste Zeit verursacht und Ihre Lösung ist einfach und elegant. Ich schätze auch die Erklärung dessen, worum es in der Antwort geht - aus irgendeinem Grund, dass die Dinge in meinem Kopf "klickten" und ich konnte sehen, warum es nicht funktionierte. Danke nochmal und fröhliche Codierung !! –

+0

Gern geschehen. Freue mich zu helfen! –