asp.net EPPlus PageRequestManagerParserErrorException error - c#

I have an UpdatePanel with a dynamically created table and I am trying to use the save stream as excel function of EPPlus. However I keep getting an error when I call my SaveToExcel() method.
The method works fine if I have it in an empty website so I believe it has something to do with the postback/UpdatePanel.
The error:
Microsoft JScript runtime error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed.
The code causing the error from the [dynamic]:
function Sys$WebForms$PageRequestManager$_endPostBack(error, executor, data) {
if (this._request === executor.get_webRequest()) {
this._processingRequest = false;
this._additionalInput = null;
this._request = null;
}
var handler = this._get_eventHandlerList().getHandler("endRequest");
var errorHandled = false;
if (handler) {
var eventArgs = new Sys.WebForms.EndRequestEventArgs(error, data ? data.dataItems : {}, executor);
handler(this, eventArgs);
errorHandled = eventArgs.get_errorHandled();
}
if (error && !errorHandled) {
throw error;
}
}
This is how i end my SaveToExcel() method:
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=Bulk Swap HDDs.xlsx");
package.SaveAs(Response.OutputStream);
Response.End();
Is there something really obvious I'm missing? If I place the SaveToExcel into another aspx page and just do a PostBackUrl="~/SaveToExcel.aspx", it also works fine (but then my submit button crashes).

Related

Blank PDF being generated from ActiveReports/WebAPI

On a project I am working on, I'm building a feature that lets users generate a report - in my case, it will go on an envelope - on-demand from information stored in our database. The problem I'm trying to solve, is that a blank PDF is being generated.
I've tried some sanity checks. First I set a breakpoint in Visual Studio and ensured that the models being passed to the report had fixed data; the reports were blank. Next, I tried including a static label that's not tied to any data, to determine if it's a report data-binding issue - the static label is not appearing in the generated report either.
More stymying, is that I've used similar code in the past without issue. I have no idea why a blank PDF file would be generated in this case.
I've read the 'Similar Questions' provided by StackOverflow, specifically this question from one year ago, but it had no answers, and thus nothing to learn from it. I've also tried the requisite Google searches, but found nothing relevant.
The only thing I cannot provide is the actual ActiveReport itself. I've checked this for Silly Programmer Errors™ like having everything hidden, or transparent labels, or similar silly things. Unfortunately, I've made no such errors.
Report Code:
public partial class EnvelopeReport : SectionReport
{
public EnvelopeReport()
{
InitializeComponent();
}
internal void RunReport(IEnumerable<PrintedAddress> model)
{
if (model != null)
{
DataSource = model;
}
Run();
}
private void OnReportStart(object sender, EventArgs e)
{
Document.Printer.PrinterName = string.Empty;
PageSettings.PaperKind = PaperKind.Number10Envelope;
PageSettings.Margins.Top = 0.25f;
PageSettings.Margins.Left = 0.5f;
PageSettings.Margins.Right = 0.5f;
PageSettings.Margins.Bottom = 0.25f;
}
}
Web API Controller Code:
[HttpGet]
public HttpResponseMessage EnvelopeReport(int addressId, string attentionTo, bool isConfidential)
{
Address address = AddressRepository.GetAddress(addressId, true);
List<PrintedAddress> models = new List<PrintedAddress>
{
new PrintedAddress(address, attentionTo, isConfidential)
};
var report = new EnvelopeReport();
report.RunReport(models);
var pdfExporter = new ActiveReportsPdfExporter();
var reportBytes = pdfExporter.ExportPdf(report);
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Content = new ByteArrayContent(reportBytes, 0, reportBytes.Length);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = "Envelope Report.pdf"
};
return response;
}
PDF Exporter:
public class ActiveReportsPdfExporter
{
private readonly PdfExport _pdfExport;
public ActiveReportsPdfExporter()
{
_pdfExport = new PdfExport();
}
public byte[] ExportPdf(SectionReport report)
{
using (var stream = new MemoryStream())
{
_pdfExport.Export(report.Document, stream);
return stream.ToArray();
}
}
public Stream ExportPdfToStream(SectionReport report)
{
var stream = new MemoryStream();
_pdfExport.Export(report.Document, stream);
return stream;
}
}
Client Service (Angular):
(function () {
angular.module('app').factory('addressSvc', [
'$http', addressSvc
]);
function addressSvc($http) {
var service = {
printAddress: function(addressId, attentionTo, someFlag) {
var args = {
'addressId': thingId,
'attentionTo': attentionTo,
'isConfidential': isConfidential
};
return $http.get('/api/common/EnvelopeReport', { 'params': args });
}
};
return service;
}
})();
Client Controller (Angular):
(function() {
angular.module('app').controller('someCtrl', [
'$window', 'addressSvc', controller
]);
function controller($window, addressSvc) {
var vm = this;
vm.attentionTo = ''; // Bound to UI.
vm.isConfidential = ''; // Also bound to UI.
vm.address = {}; // Unimportant how we get this.
vm.printAddress = printAddress;
function printAddress() {
addressSvc.printAddress(vm.address.id, vm.attentionTo, vm.isConfidential)
.then(function(result) {
var file = new Blob([result], {type: 'application/pdf'});
var fileURL = URL.createObjectURL(file);
if(window.navigator && window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveOrOpenBlob(file, 'Envelope.pdf');
} else {
$window.open(fileURL);
}
});
}
}
)();
Question: Why is this code generating an empty PDF? I've used the Report/API Controller structure successfully in the past to generate PDFs, but usually in the context of MVC, not Web API. Another potential point of failure is the client code - I've not previously passed reports between server and client this way.
So, it turns out my server-side code was completely sane. The Client code was off.
Instead of Blobbing the data returned from the server and all of that work, what I instead needed to do was build a URL...and call $window.open(url); This is because my server code as it stands will return the PDF file as-is.

Export to Excel Error

I am attempting to export a datagrid to excel via a popup. I am able to successfully export to excel when removing the code from my application, however, when attempting to export to excel using the exact same code within my application, I receive the following errors:
From my try/catch:
Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack.
...and from the console:
Error: Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed.
My server-side code is as follows:
protected void btnExportToExcel_Click(object sender, EventArgs e)
{
ExportDataSetToExcel();
}
private void ExportDataSetToExcel()
{
try
{
DataTable dt = new DataTable("GridView_Data");
foreach (TableCell cell in gvPatientRoster.HeaderRow.Cells)
{
dt.Columns.Add(cell.Text);
}
foreach (GridViewRow row in gvPatientRoster.Rows)
{
dt.Rows.Add();
for (int i = 0; i < row.Cells.Count; i++)
{
dt.Rows[dt.Rows.Count - 1][i] = row.Cells[i].Text;
}
}
if (dt != null && dt.Rows.Count > 0)
{
Response.ContentType = "application/vnd.ms-excel";
Response.AppendHeader("Content-Disposition",
string.Format("attachment; filename=PatientRoster.xls"));
System.IO.StringWriter tw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter hw =
new System.Web.UI.HtmlTextWriter(tw);
DataGrid dgGrid = new DataGrid();
dgGrid.DataSource = dt;
//Report Header
hw.WriteLine("<b><u><font size='5'>" +
"Patient Roster</font></u></b>");
hw.WriteLine("<br><br>");
//hw.Write(BuildCriteriaString());
hw.WriteLine("<br>");
// Get the HTML for the control.
dgGrid.HeaderStyle.Font.Bold = true;
dgGrid.DataBind();
dgGrid.RenderControl(hw);
// Write the HTML back to the browser.
this.EnableViewState = false;
Response.Write(tw.ToString());
Response.End();
}
}
catch (Exception ex)
{
lblErrorMessage.Text = ex.Message;
}
}
I added the following to the PageLoad() and the export now works:
ScriptManager scriptManager = ScriptManager.GetCurrent(this.Page);
scriptManager.RegisterPostBackControl(this.btnExportToExcel);
It looks like the UpdatePanel and ScriptManager were elements that I overlooked. When I separated the functionality from the main application, I did not include all HTML that was in the main application. Since the ScriptManager and UpdatePanel were not part of the isolated functionality, it worked properly. I will be sure to post the HTML next time
This was a solution from the following post:
Sys.WebForms.PageRequestManagerParserErrorException: The message received from the server could not be parsed
I would suggest using one of the many good, free C# "Export to Excel" libraries out there.
You've already written the code to read your DataView into a DataTable, and once it's in this format, using the following free C# library...
ExportToExcel library
...you'd be able to export the data into a "real" Excel 2007 file in one line of code....
// Export the DataTable into an Excel file, and write it to the web Response
CreateExcelFile.CreateExcelDocument(dt, "SomeFilename.xlsx", Response);
Okay, okay, two lines of code. I added a comment.
But you get the point !

Asp.net change hourglass cursor back without post back

I created an asp.net site for downloading documents. I handle this with Page.Response.
try {
...
EndpointAddress endPoint = new EndpointAddress("xxxxx.svc");
FileServiceClient fileServiceProxy = new FileServiceClient(binding, endPoint);
// WCF WebService call
Stream stream = fileServiceProxy.GetFileStream(filePath);
Page.Response.ContentType = "application/pdf";
Page.Response.AddHeader("Content-Disposition",string.Format ("attachment; fileName=\"{0}\"", Path.GetFileName(filePath)));
Page.Response.AddHeader("Accept-Ranges", "bytes");
if (buffer != null){
Page.Response.BinaryWrite(buffer);
}
Page.Response.Flush();
}
catch (Exception e)
{
Page.Response.Clear();
Page.Response.ClearContent();
Page.Response.ClearHeaders();
}
finally
{
Page.Response.End();
}
And while the file is loading from a webservice I want to display a hourglass cursor. Showing loading cursor is working.
protected void Page_Load(object sender, EventArgs e)
{
btnDownload.Attributes.Add("onclick", "document.body.style.cursor = 'wait';");
}
But I can't change it back to normal cursor. I think because I don't fire a post back or don't reload the site.
What can I do to set default cursor if buttonClick event is over without site reload!?
Update: Updated the code with the wcf webservice call. I call the webservice with file path and get a stream back which I write to Page.Response.BinaryWriter
# Frédéric Hamidi THX for the link. I change my approach and display a jquery waiting dialog until file transfer is finished.
File download dialog

Upload file to Sharepoint 2013 using web service - Object reference not set to an instance of an object

I'm trying to upload file to Sharepoint 2013 using web service copy.asmx
I've created simple project with the following method:
public bool UploadFile(string file, string destination)
{
bool success = false;
CopySoapClient client = new CopySoapClient();
if (client.ClientCredentials != null)
{
client.ClientCredentials.Windows.ClientCredential = new NetworkCredential("admin", "password", "domain");
}
try
{
client.Open();
string filename = Path.GetFileName(file);
string destinationUrl = destination +#"/"+ filename;
string[] destinationUrls = { destination };
FieldInformation i1 = new FieldInformation { DisplayName = "Title", InternalName = "Title", Type = FieldType.Text, Value = filename};
FieldInformation[] info = { i1 };
CopyResult[] result;
byte[] data = File.ReadAllBytes(file);
uint ret = client.CopyIntoItems(file, destinationUrls, info, data, out result);
if (result != null && result.Length > 0 && result[0].ErrorCode == 0)
success = true;
}
finally
{
if (client.State == System.ServiceModel.CommunicationState.Faulted)
client.Abort();
if (client.State != System.ServiceModel.CommunicationState.Closed)
client.Close();
}
return success;
}
CopySoapClient is part Copy service reference
http://SPSITE/_vti_bin/copy.asmx
The method is called using following parameters:
UploadFile(#"C:\temp\test.txt", "http://SPSITE/sites/Connector/documents/test.txt");
The problem is, when program executes
uint ret = client.CopyIntoItems(file, destinationUrls, info, data, out result);
the web service returns in result "Unknown error" with description "Object reference not set to an instance of an object."
I really don't know what I'm missing. Can anyone help me out?
Thank you.
P.S. I've noticed in examples provided on the Internet that people are using a Copy class from copy.asmx. But I only have CopySoapClient class.
you used the right web services but on wrong SharePoint site. Try to make this web services reference on the same sharepoint site you have posted here as target library.
missing the OPTIONAL element of <Fields> and <FieldInformation >, resulted ErrorCode="Unknown" ErrorMessage="Object reference not set to an instance of an object." . even though, Field and FieldInformation supposed to be optional. It could be the server side configuration. Anyway, it works for me now, adding all attributed, required/optional.

Code executes even after Response.End()

I have to reload my page after I write some html, script to my page using Response.Write. After using Response.Write I am using Response.Flush(), followed by Response.End(). The code works properly in one server and when I deploy it to another server it is not working.
As far as I know the code execution must stop once it executes the Response.End, but it is now behaving in the desired way.
Response.ClearContent();
Response.Write("Write some html, script content here");
Response.Flush();
Response.End();
Using Respose.Redirect(Request.RawUrl) will not work and will throw an exception stating that the redirection cannot happen once the headers are posted...
Can some one tell me, why the code execution is not stopped by Response.End() ??
EDIT: Actual Code
protected void Page_Load(object sender, EventArgs e)
{
if (Session["localTime"] == null && String.IsNullOrEmpty(Request.Params["localTime"]))
{
// then clear the content and write some html, a javascript code which submits the local time
Response.ClearContent();
Response.Write(#"<form id='local' method='post' name='local'>
<input type='hidden' id='localTime' name='localTime' />
<script type='text/javascript'>
document.getElementById('localTime').value = new Date();
document.getElementById('local').submit();
</script>
</form>");
//
Response.Flush();
// end the response so PageLoad, PagePreRender etc won't be executed
Response.End();//Page must reload after this line.
}
else
{
// if the request contains the localtime, then save it in Session
if (Request.Params["localTime"] != null)
{
Session["localTime"] = Request.Params["localTime"];
Response.Write(Request.Params["localTime"] + " ~2");
// and redirect back to the original url
Response.Redirect(Request.RawUrl);
}
}
}

Categories