I'm having a hard time getting a sub report to show up in my application using reportviewer. It works perfectly when debugging it locally. But when I upload it to the server, the sub reports are blank.
I've believe that SubreportProcessing event is not firing since I don't see the stored procedures getting fired from SQL Server Profiler. Here is my code that I'm using.
private void RunReport(string strFormat, int PlanID)
{
const string reportrdlc = "Reports\\Report_All_Sections.rdlc";
LocalReport report = new LocalReport {ReportPath = Server.MapPath(reportrdlc)};
report.SetBasePermissionsForSandboxAppDomain(new PermissionSet(PermissionState.Unrestricted));
report.DataSources.Clear();
report.SubreportProcessing += SetSubDataSource;
report.DataSources.Add(new ReportDataSource("DataSet_usp_GetSD", _wpt.Get_SD(PlanID).Copy()));
report.Refresh();
string mimeType;
string encoding;
string fileNameExtension;
string[] streams;
Warning[] warnings;
byte[] pdfContent = report.Render(strFormat, null, out mimeType, out encoding,
out fileNameExtension, out streams, out warnings);
System.IO.MemoryStream stream = new System.IO.MemoryStream(pdfContent);
Response.ContentType = strFormat == "EXCEL" ? "application/vnd.ms-excel" : "application/pdf";
Response.BinaryWrite(stream.ToArray());
Response.Flush();
Response.Close();
stream.Close();
}
public void SetSubDataSource(object sender, SubreportProcessingEventArgs e)
{
int PlanID = 1;
if (Request.QueryString["PlanID"] != null)
{
try
{
PlanID = Convert.ToInt32(Request.QueryString["PlanID"]);
}
catch (Exception Ex)
{
PlanID = 1;
}
}
switch (e.ReportPath)
{
case "Report_All_Mentor":
e.DataSources.Add(new ReportDataSource("DataSet_usp_GetMC", _wpt.Get_MC(PlanID).Copy()));
break;
case "Report_All_Intern":
e.DataSources.Add(new ReportDataSource("DataSet_usp_GetEA", _wpt.Get_EA(PlanID).Copy()));
break;
}
}
I seem to have the same issue. I believe that the problem is that when deployed reportPath contains the full path for the report, but when you are debugging locally it passes only the report name.
Is it possible that your SubreportProcessing event is indeed firing but in your switch statement non of the cases match the full path contained in the reportPath parameter.
I don't know how to resolve that but I think that might be the root cause.
Related
I know this question was asked & answered before, but the solutions don't work for me. I have to dynamically create a list of PDFs, and each row has a checkbox. You check the PDFs you want to download, whose ID get passed to a function to create the PDF. I store those PDF's in a list, which gets passed to the Zip function (DotNetZip). Problem is, when first generating a PDF, I get that error somewhere in the middle of creating it, about halfway through, when adding a new page in the PDF. Usually it's the same spot but occasionally it changes where it crashes. Could anyone look at my code and point out where I'm messing up?
protected void Download_PDF_Click(object sender, EventArgs e)
{
Response.Clear();
Response.BufferOutput = false;
HttpContext c = HttpContext.Current;
String archiveName = "Arhiva Inspectii.zip";
Response.ContentType = "application/zip";
Response.AddHeader("content-disposition", "filename=\"" + archiveName + "\"");
int nr_rows = tbl_inspectii.Rows.Count - 1;
foreach (String id_chbx in ID_Checkbox)
{
CheckBox chbx = tbl_inspectii.FindControl(id_chbx) as CheckBox;
String PDF_id = "";
if(chbx != null)
{
if(chbx.Checked)
{
PDF_id = chbx.ID.Replace("ChBx", string.Empty);
Create_PDF(PDF_id);
}
}
}
string destdir = Server.MapPath("~/Zip/") + archiveName;
using (ZipFile zip = new ZipFile())
{
zip.AddFiles(PDF_list, destdir);
zip.Save(destdir);
}
}
protected byte[] Create_PDF(String id_insp_max)
{
using (MemoryStream ms = new MemoryStream())
{
Document brosura = new Document(PageSize.A4);
brosura.SetMargins(40, 40, 40, 40);
PdfWriter wri = PdfWriter.GetInstance(brosura, ms);//new FileStream(Server.MapPath("Pdf/") + titlu_pdf + ".pdf", FileMode.Create)
HttpContext.Current.Response.AppendHeader("Content-Disposition", "inline; filename=\"" + titlu_pdf + ".pdf\"");
PdfWriter.GetInstance(brosura, HttpContext.Current.Response.OutputStream);
brosura.Open();
//lots of SQL, and brosura.Add();
//at some point, a brosura.Add() has the error halfway through the pdf
brosura.Close();
PDF_list.Add(titlu_pdf);
wri.Close();
return ms.ToArray();
}
}
Try to move the Response block after you closed the Document.
And try to add Response.End();
And why are you return the Array in Create_PDF but does not using it?
I'm trying to convert my report from rdl to rdlc to render to Word file by LocalReport. Every 2010 schema version reports work well except 2008 reports.
With 2008 reports, LocalReport just renders a no data file without any error or warning. When debug the project, I see that all the DataSets are added with correct name as DataSet definition in report file. And all DataSets have needed data.
I've tried not to add any DataSet to LocalReport.DataSources, but report just render successful with no data while with other working reports, it will throw exception "Cannot create a data reader for dataset '[a dataset name]'".
Here is my code:
LocalReport localReport = new LocalReport();
localReport.ReportPath = localReportPath;
localReport.SubreportProcessing += LocalReport_SubreportProcessing;
localReport.DataSources.Clear();
//Add datasource
foreach (var ds in report.ReportDataSets.Where(x => localReport.GetDataSourceNames().Contains(x.DataSetName)))
{
localReport.DataSources.Add(new ReportDataSource(ds.DataSetName, ds.Data));
}
localReport.Refresh();
//Add parameters
List<Microsoft.Reporting.WinForms.ReportParameter> paramaterList = new List<Microsoft.Reporting.WinForms.ReportParameter>();
foreach (var parameter in report.ReportParameters)
{
Microsoft.Reporting.WinForms.ReportParameter param = new Microsoft.Reporting.WinForms.ReportParameter()
{
Name = parameter.Name
};
param.Values.AddRange(parameter.Value.ToString().Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries));
paramaterList.Add(param);
}
localReport.SetParameters(paramaterList.ToArray());
const string devInfo = #"<DeviceInfo><SimplePageHeaders>True</SimplePageHeaders></DeviceInfo>";
Microsoft.Reporting.WinForms.Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;
var bytes = localReport.Render(format, devInfo, out mimeType, out encoding, out extension, out streamids, out warnings);
var outputPath = Path.GetTempPath();
if (!Directory.Exists(outputPath))
{
Directory.CreateDirectory(outputPath);
}
using (var fileStream = File.Create(outputPath + #"\" + report.ReportName + "." + extension, bytes.Length))
{
fileStream.Write(bytes, 0, bytes.Length);
fileStream.Close();
}
Has anyone met this before?
I'm totally not understand why? Please help me, I've been stuck on this for a week.
I am using Microsoft.Report.Viewer for generate PDF in my ASP .NET WEB API application. So far when my report get the data directly from database, there is no problem. The problem is, when I try to create a report with subreport within and the subreport data is got from code in a list form, I didn't get the expected result. What I do is create a report with subreport from this tutorial. But when I generate the PDF, what I get is this message .
Here is my code :
My Web API to generate the PDF :
[Route("GeneratePDFForDailyProgram")]
[HttpGet]
[AllowAnonymous]
public async Task<IHttpActionResult> GeneratePDFForDailyProgram(int id) {
string guid = Guid.NewGuid().ToString();
string fileName = string.Concat("Booking_No" + Convert.ToString(id) + "_" + guid.ToUpper() + ".pdf");
string filePath = HttpContext.Current.Server.MapPath("~/Content/Temp/" + fileName);
string name = Request.RequestUri.GetLeftPart(UriPartial.Authority) + System.Configuration.ConfigurationManager.ConnectionStrings[System.Configuration.ConfigurationManager.AppSettings["CUSTOMPORT"]];
string name2 = Request.GetRequestContext().VirtualPathRoot;
List<TourDestination> destination = new List<TourDestination>();
TourTransactionSummaryViewModel summaryViewModel = new TourTransactionSummaryViewModel();
try {
//summaryViewModel = await CalcSummaryViewModel(transaction, summaryViewModel, db);
summaryViewModel.DailyPrograms = DailyProgram(id);
destination = TourDestination(summaryViewModel.DailyPrograms);
List < Movement > movementList = summaryViewModel.DailyPrograms.FirstOrDefault().Movements.ToList();
Reports.ReportGenerator.GeneratePDFForDailyProgram(summaryViewModel.DailyPrograms, destination, filePath);
//await Reports.ReportGenerator.GeneratePDFForMovement(movementList, filePath);
HttpResponseMessage result = null;
result = Request.CreateResponse(HttpStatusCode.OK);
result.Content = new StreamContent(new FileStream(filePath, FileMode.Open));
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentDisposition.FileName = fileName;
result.Dispose();
string convertedFilePath = filePath.Replace(#"\\", #"\");
} catch (Exception ex) {
return BadRequest(ex.Message);
}
return Ok(name + name2 + "/Content/Temp/" + fileName);
}
As you can see from the code above, I use GeneratePDFForDailyProgram method to generate the PDF.
Here my GeneratePDFForDailyProgram method :
public static bool GeneratePDFForDailyProgram(TourTransactionSummaryViewModel.DailyProgram[] dailyPrograms, List<TourDestination> destination , string filePath) {
try {
string binPath = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "bin");
var assembly = Assembly.Load(System.IO.File.ReadAllBytes(binPath + "\\TripPlannerAPI.dll"));
using (Stream stream = assembly.GetManifestResourceStream(DailyProgramReport)) {
var viewer = new ReportViewer();
viewer.LocalReport.EnableExternalImages = true;
viewer.LocalReport.LoadReportDefinition(stream);
Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string filenameExtension;
viewer.LocalReport.SubreportProcessing += new Microsoft.Reporting.WebForms.SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
viewer.LocalReport.DataSources.Add(new ReportDataSource("DailyProgram", dailyPrograms));
byte[] bytes = viewer.LocalReport.Render(
"PDF", null, out mimeType, out encoding, out filenameExtension,
out streamids, out warnings);
using (FileStream fs = new FileStream(filePath, FileMode.Create)) {
fs.Write(bytes, 0, bytes.Length);
fs.Flush();
}
stream.Flush();
}
} catch (Exception ex) {
return false;
}
return true;
}
To run the SubReport, I use the eventhandler code :
private static void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e) {
DateTime movementDate = Convert.ToDateTime(e.Parameters[0].Values[0]);
TourTransactionsController controller = new TourTransactionsController();
var movement = controller.Movements();
List<Movement> movementList = new List<Movement>();
movementList.Add(new Movement {
Destination = "TEST",
MovementDescription = "TEST",
DateTime = Convert.ToDateTime("2017-09-25") //HARDCODE FOR TEST
});
e.DataSources.Clear();
e.DataSources.Add(new Microsoft.Reporting.WebForms.ReportDataSource() {
Name = "DSMovements",
Value = movementList
});
//throw new NotImplementedException();
}
What I did try :
Check the sub report name, and change it from report name to report file url. Still get the same message.
Generate the Sub Report directly, not from the main report. The subreport is successfully generated.
PS : When I debug my code, and put a breakpoint in my event handler LocalReport_SubreportProcessing the breakpoint is not hitting while debugging
My Questions are :
Why my breakpoint on the eventhandler is not hitting while debugging ?
Is it possible that eventhandler which is not hitting while debugging, could be the reason I got the message The subreport 'MovementReport' could not be
found at the specified location MovementReport.
Please verify that the subreport has been
published and that the name is correct. ?
Is there any other way for me to create a main report with data from db, and the subreport with data from code in list form ?
Any help is appreciated.
I have a master report file and a sub report file.
Master report file calls sub report file.
Let's have a look at the code first.
private void CreatePDF(string fileName)
{
try
{
// Variables
Warning[] warnings;
string[] streamIds;
string mimeType = string.Empty;
string encoding = string.Empty;
string extension = string.Empty;
string _strGijunMonth = DateTime.Parse(GijunMonth).ToString("yyyyMM");
byte[] bytes = null;
// Setup the report viewer object and get the array of bytes
ReportViewer viewer = new ReportViewer();
viewer.LocalReport.DataSources.Clear();
viewer.ProcessingMode = ProcessingMode.Local;
viewer.LocalReport.ReportEmbeddedResource = "MasterReport.rdlc";
viewer.LocalReport.EnableExternalImages = true;
DataTable _dt = base.GetDataTable(
"my_procedure"
, _strMainNo
);
_intTotalPage = _dt.Rows.Count * 2;
ReportDataSource _ds = new ReportDataSource();
_ds.Value = _dt;
_ds.Name = "SetData";
viewer.LocalReport.DataSources.Add(_ds);
// sub report event
viewer.LocalReport.SubreportProcessing += new SubreportProcessingEventHandler(LocalReport_SubreportProcessing);
// print
viewer.RefreshReport();
bytes = viewer.LocalReport.Render("PDF", null, out mimeType, out encoding, out extension, out streamIds, out warnings);
System.IO.FileStream newFile1 = new System.IO.FileStream(fileName, System.IO.FileMode.Create);
newFile1.Write(bytes, 0, bytes.Length);
newFile1.Close();
}
catch
{
throw;
}
}
void LocalReport_SubreportProcessing(object sender, SubreportProcessingEventArgs e)
{
try
{
string MAINT_NO = e.Parameters["MAINT_NO"].Values[0];
string _strGijunMonth = DateTime.Parse(GijunMonth).ToString("yyyyMM");
// get sub report procedure
DataSet _dsCust_Info = base.GetDataSet(
"my_sub_procedure"
, MAINT_NO
, _strGijunMonth
);
----> by somehow, it should throw error. If so, I should not print error page to pdf.
}
catch (Exception err)
{
}
}
My application calls "CreatePDF" method with file name argument.
Let's say that I have to print to PDF 5 pages.
While calling LocalReport_SubreportProcessing event, some of sub reports have error value in data. So, I throw an error in LocalReport_SubreportProcessing event.
For example, when I say that there are 5 pages and only 1, 2, 3 and 5 pages are okay and the number 4 page should not be printed as PDF.
I wonder how I can delete PDF page which is already created by ReportViewer.
As you can see, LocalReport_SubreportProcessing event comes after creating PDF file.
Anyone has any idea to fix this problem?
Maybe reportViewer.CancelRendering(0);
when you detect an error?
i am developing web application, in my app i have to print rdlc without preview.my code is following
LocalReport report = new LocalReport();
report.ReportEmbeddedResource = "TCESS.ESales.CommonLayer.Reports.HandlingBillReport.rdlc";
report.ReportPath="TCESS.ESales.CommonLayer.Reports.HandlingBillReport.rdlc";
SettlementOfAccountsDTO objSettlementOfAccountsDTO = ESalesUnityContainer.Container.Resolve<ISettlementOfAccountsService>().GetSettlementOfAccountsByAccId(32);
if (objSettlementOfAccountsDTO.Account_Id > 0)
{
SetReportParametersForBill(objSettlementOfAccountsDTO, AccountReportViewer, report);
}
Export(report);
m_currentPageIndex = 0;
Print();
private Stream CreateStream(string name, string fileNameExtension, Encoding encoding,
string mimeType, bool willSeek)
{
Stream stream = new FileStream(name + "." + fileNameExtension, FileMode.Create);
m_streams.Add(stream);
return stream;
}
private void Export(LocalReport report)
{
string deviceInfo =
"<DeviceInfo>" +
" <OutputFormat>EMF</OutputFormat>" +
" <PageWidth>8.5in</PageWidth>" +
" <PageHeight>11in</PageHeight>" +
" <MarginTop>0.25in</MarginTop>" +
" <MarginLeft>0.25in</MarginLeft>" +
" <MarginRight>0.25in</MarginRight>" +
" <MarginBottom>0.25in</MarginBottom>" +
"</DeviceInfo>";
Warning[] warnings;
m_streams = new List<Stream>();
report.Render("Image", deviceInfo, CreateStream, out warnings);
foreach (Stream stream in m_streams)
stream.Position = 0;
}
private void PrintPage(object sender, PrintPageEventArgs ev)
{
Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
ev.Graphics.DrawImage(pageImage, 0, 0);
m_currentPageIndex++;
ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
}
private void Print()
{
const string printerName = "\\\\193.168.0.20\\Printer_Q3";
if (m_streams == null || m_streams.Count == 0)
return;
PrintDocument printDoc = new PrintDocument();
printDoc.PrinterSettings.PrinterName = printerName;
if (!printDoc.PrinterSettings.IsValid)
{
string msg = String.Format("Can't find printer \"{0}\".", printerName);
Console.WriteLine(msg);
return;
}
int i=0;
foreach (Stream stream in m_streams)
{
Metafile pageImage = new Metafile(stream);
pageImage.Save(Server.MapPath("~/Images/"+i.ToString()+".jpg"));
i++;
}
//printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
//printDoc.Print();
}
i am getting error "The report definition for report ' ' has not been specified"
on line
report.Render("Image", deviceInfo, CreateStream, out warnings);
I just ran into this problem while instantiating a report to export and had to set this property like this:
wrvReport.LocalReport.ReportEmbeddedResource = "CommonLayer.Reports.SalesByPrice.rdlc";
The difference I see is the .LocalReport is the sub-property to set the embedded resource.
From MSDN:
An embedded report resource is a report definition that has been
stored as a resource in the calling assembly.
If the ReportPath property has been set, the ReportEmbeddedResource
property is ignored.
Therefore, setting the EmbeddedResource property is effectively doing nothing and your ReportPath is also failing because it expects a physical file system path.
I had the same problem. I solved it by setting "Copy to Output Directory = Copy if newer". Cheers.
I also had the same problem, that means that your code is not finding the rdlc file, you need to either use report.ReportEmbeddedResource or report.ReportPath. Looking at your code seems to me that you only need to use report.ReportEmbeddedResource, the other option is for a rdlc that is located in a specific location in your pc or in a network file system