Rdlc in ASP.NET MVC does not render properly - c#

I am using ASP.NET MVC and i want to render an rdlc in a view.
Here is my code to render the rdlc file.
[HttpPost]
public ActionResult DepartmentwiseInwardOutwardReport(int? fd, int? td, string fdt, string tdt)
{
TrackBL trackBL = new TrackBL();
IEnumerable<TrackModel> trackList = trackBL.GetDeptInwardOutwardReport(fd, td, fdt, tdt);
//return PartialView("_TrackingSearchReport", trackList);
LocalReport localReport = new LocalReport();
localReport.ReportPath = Server.MapPath("~/Content/Reports/FileMovement.rdlc");
ReportDataSource reportDataSource = new ReportDataSource("Customers", trackList);
reportDataSource.Name = "FTSDataSet_proc_File_InwardOutWardReport";
localReport.DataSources.Add(reportDataSource);
string reportType = "PDF";
string mimeType;
string encoding;
string fileNameExtension;
//The DeviceInfo settings should be changed based on the reportType
//http://msdn2.microsoft.com/en-us/library/ms155397.aspx
string deviceInfo =
"<DeviceInfo>" +
" <OutputFormat>PDF</OutputFormat>" +
" <PageWidth>8.5in</PageWidth>" +
" <PageHeight>11in</PageHeight>" +
" <MarginTop>0.5in</MarginTop>" +
" <MarginLeft>1in</MarginLeft>" +
" <MarginRight>1in</MarginRight>" +
" <MarginBottom>0.5in</MarginBottom>" +
"</DeviceInfo>";
Warning[] warnings;
string[] streams;
byte[] renderedBytes;
//Render the report
renderedBytes = localReport.Render(
reportType,
deviceInfo,
out mimeType,
out encoding,
out fileNameExtension,
out streams,
out warnings);
//Response.AddHeader("content-disposition", "attachment; filename=NorthWindCustomers." + fileNameExtension);
return File(renderedBytes, mimeType);
When i render this in the view, i am able to see 14 pages, i do have only 1 row to display as of now. two columns each are getting displayed in the page. I wanna display it like a report where all the columns are displayed next to other.
Am i missing some settings? ANy suggestions?

Im using RDLC in MVC3 and even MVC4, I dont have that problem that you are facing, even though I think its related to the RDLC report itself, maybe you have the width of the page very high so its warping it to 14 pages (sometimes with me it warps to 3 pages if I forget to set the orientation and I have a large number of columns.
If you set width of your report to be larger than the page you try to print on, the report will be automatically split to fit pages.

Related

How to change the database in an SSRS report at run-time

I am attempting to produce a c# program to run an SSRS report on any one of a number of identical databases, the target database to be specified at run-time. To this end, I create a solution and project, and in this project include an SSRS report. This report has a dataset LegislationData which invokes a stored procedure in a specimen database.
I am now trying to get this to run in the C# project. I create a form with a report viewer and a go button and attempt to set up the report. I envisaged some code along the following lines:-
MyReport my_report = new MyReport();
my_report.ConnectionString = "blah blah"; // or
my_report.DataSet.ConnectionString = "blah blah"; // or
my_report.LegislationData.ConnectionString = "blah blah"
and then
report_viewer.Report = my_report; // or
report_viewer.LocalReport = my_report; // or
report_viewer.SetReport(my_report);
but none of these things actually exist.
Can someone explain to me very slowly and in words of one syllable what I need to do here? I have looked at the answers to similar questions here and here but to be frank the answers make no sense.
The first thing you need to realise is that SSRS has to be added into your C# application as a web reference. There's a guide on how to do this here: https://msdn.microsoft.com/en-gb/library/ms169926.aspx. Basically it sounds worse than it is, and it should only take a few minutes to configure all this. I found that MSDN link was corrupted for me, so here's another place that discusses how to do this: https://sqluninterrupted.com/2012/03/04/adding-a-reporting-services-web-reference-to-net-application/.
Once you have your report running from a C# application you will need to decide what you want to do with the output, convert it to PDF, stream it to the screen, save it as Excel, etc.
I haven't done this before, but it looks as though you can embed a data source into your report that uses an expression based on a parameter. So you would pass in a parameter to run the report that would be a connection string. You would also need to pass in any other parameters you might have in your report.
So step 1 add the web reference for SSRS.
Step 2 add some code to run your report, e.g. here's an example that returns the report as a byte array in PDF format:
public byte[] RenderReport(ReportExecutionService rs, string reportName, int variant)
{
Console.WriteLine("Rendering " + reportName + "_" + variant.ToString("00"));
byte[] result = null;
string reportPath = "/Prototypes/Inheritance Letters/" + reportName;
const string format = "PDF";
const string devInfo = #"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
//Prepare report parameters
var parameters = new ParameterValue[2];
parameters[0] = new ParameterValue { Name = "row_id", Value = variant.ToString() };
parameters[1] = new ParameterValue { Name = "bulk_run", Value = "1" };
rs.ExecutionHeaderValue = new ExecutionHeader();
rs.LoadReport(reportPath, null);
rs.SetExecutionParameters(parameters, "en-gb");
try
{
string encoding;
string mimeType;
string extension;
Warning[] warnings;
string[] streamIDs;
result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
rs.GetExecutionInfo();
return result;
}
catch (SoapException e)
{
Console.WriteLine(e.Detail.OuterXml);
return null;
}
}
Step 3 pass the connection string as one of the parameters, and use an expression in an embedded data source in your report to pick this up and use it.
Step 4 decide what to do with the rendered output. For example, here I render a report then save the output to a PDF:
byte[] result = new Render().RenderReport(rs, "ACQ_Welcome_Letter", i);
new Render().CreatePDF(i, "Welcome Letter", "ACQ_Welcome_Letter" + "_" + fuelType, result);
Here's the CreatePDF method, it has a lot of other garbage in for my particular solution, but it gives you a taste of how to do this:
public string CreatePDF(int variant, string subFolder, string reportName, byte[] result)
{
//We want 16 variants, but we pass in a number from 1 to 48, so use modulo division to convert this back to a 1 to 16 range
variant = (variant - 1) % 16 + 1;
Console.WriteLine("Saving " + reportName + "_Variant_" + variant.ToString("00") + ".pdf");
try
{
//Determine the target folder/ filename for the PDF
//Snail Mail has its own folder, all PDFs go into that folder and then are manually processed
string folder = #"S:\Change Management Documents\SMETS1\Inheritance Comms\" + subFolder + #"\";
string filename = reportName + "_Variant_" + variant.ToString("00") + ".pdf";
//Remove any existing content
string[] filePaths = Directory.GetFiles(folder, filename);
foreach (string filePath in filePaths)
File.Delete(filePath);
//Now save the PDF
string path = folder + #"\" + filename;
FileStream stream = File.Create(path, result.Length);
stream.Write(result, 0, result.Length);
stream.Close();
return filename;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
return "";
}
}

Can't render chart in RDLC report

I'm using RDLC file to render a report (without SQL Server Reporting Services) and return it from my controller as a file. This is part of my MVC web application.
public ActionResult Index()
{
var report = new LocalReport();
report.ReportPath = Path.Combine(Server.MapPath("~/Reports"), "Report1.rdlc");
var reportData = new List<MonthlyData> {
new MonthlyData {RecordNo=1, Tid="123456", Active=10, Inactive=1}
};
ReportDataSource rd = new ReportDataSource("DataSet1", reportData);
report.DataSources.Add(rd);
string reportType = "PDF";
string mimeType;
string encoding;
string fileNameExtension;
string deviceInfo =
"<DeviceInfo>" +
" <OutputFormat>" + "PDF" + "</OutputFormat>" +
//" <PageWidth>8.5in</PageWidth>" +
//" <PageHeight>11in</PageHeight>" +
//" <MagroupinTop>0.5in</MagroupinTop>" +
//" <MagroupinLeft>1in</MagroupinLeft>" +
//" <MagroupinRight>1in</MagroupinRight>" +
//" <MagroupinBottom>0.5in</MagroupinBottom>" +
"</DeviceInfo>";
Warning[] warnings;
string[] streams;
byte[] renderedBytes;
renderedBytes = report.Render(
reportType,
deviceInfo,
out mimeType,
out encoding,
out fileNameExtension,
out streams,
out warnings);
return File(renderedBytes, mimeType);
}
This is the result:
table example in rdlc file
Everything works like a charm until I decide to add a chart.
rdlc file with chart
Now when I render it I get two exceptions:
Microsoft.Reporting.WebForms.LocalProcessingException: „An error occurred during local report processing.”
DefinitionInvalidException: The definition of the report 'C:\Users\agutowski\Documents\Visual Studio 2017\Projects\rdlcMvc\rdlcMvc\Reports\Report1.rdlc' is invalid.
and
Microsoft.Reporting.WebForms.LocalProcessingException: „An error occurred during local report processing.”
ReportProcessingException: The definition of this report is not valid or supported by this version of Reporting Services. The report definition may have been created with a later version of Reporting Services, or contain content that is not well-formed or not valid based on Reporting Services schemas. Details: The report definition has an invalid target namespace 'http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition' which cannot be upgraded.
I already tried different versions of Microsoft.ReportViewer.Common and Microsoft.ReportViewer.WebForms.
I solved it by using Microsoft.ReportingServices.ReportViewerControl.WebForms and Microsoft.SqlServer.Types NuGet packages instead of Microsoft.ReportViewer.Common and Microsoft.ReportViewer.WebForms.

How to preserve the transparent background of a report after it is rendered as an image?

I'm currently using this code to generate my charts to .PNG using .RDLC templates.
string deviceInfo = "<DeviceInfo>" + "<OutputFormat>PNG</OutputFormat>" + "</DeviceInfo>";
//rpv is an instance of Microsoft.Reporting.WinForms.ReportViewer class defined in code-behind
byte[] bytes = rpv.LocalReport.Render("Image",deviceInfo, out mimeType, out enc,out ext, out strmid, out wrngs);
using (FileStream fs = new FileStream(imagePath + "." + filenameExtension, FileMode.Create))
{
fs.Write(bytes, 0, bytes.Length);
}
The report is rendered in .PNG format which supports transparency. However, I noticed that the report's background transparency is not preserved even though I have set the BackgroundColor to No Color in the report designer
How to preserve the transparency of rdlc reports when it is rendered as an image?

Is there any way to ask a ReportViewer if the result of the query inside a Report will yield more than 65k rows?

I have my reports in a Reporting Services server, inside my .rdl there is a query that accepts parameters. I pass those parameters with an instance of ReportViewer. I have a method that downloads the result of the report in Excel format without using the ReportViewer directly. The method is the following:
private void CreateEXCEL(Dictionary<string, string> parametros, string nombreReporte)
{
// Variables
Warning[] warnings;
string[] streamIds;
string mimeType = string.Empty;
string encoding = string.Empty;
string extension = string.Empty;
// Setup the report viewer object and get the array of bytes
string ReportServerURL = ConfigurationManager.AppSettings["ReportServerCompletitudURL"];
string ReportName = ConfigurationManager.AppSettings["ReportNameRankingVentaPDV"] + "/" + nombreReporte;
MyReportViewer.Reset();
MyReportViewer.ProcessingMode = ProcessingMode.Remote;
MyReportViewer.ServerReport.ReportPath = ReportName;
MyReportViewer.ServerReport.ReportServerUrl = new Uri(ReportServerURL);
List<ReportParameter> parameters = new List<ReportParameter>();
foreach (var d in parametros)
{
parameters.Add(new ReportParameter(d.Key, d.Value));
}
MyReportViewer.ServerReport.SetParameters(parameters);
byte[] bytes = MyReportViewer.ServerReport.Render("EXCEL", null, out mimeType, out encoding, out extension, out streamIds, out warnings);
// Now that you have all the bytes representing the PDF report, buffer it and send it to the client.
Response.Buffer = true;
Response.Clear();
Response.ContentType = mimeType;
Response.AddHeader("content-disposition", "attachment; filename=" + nombreReporte + "." + extension);
Response.BinaryWrite(bytes); // create the file
Response.Flush(); // send it to the client to download
}
Now the idea is that I can't create a file with more that 65536 rows as an Excel file, the idea is to "Ask" if the result of the query inside the Report will yield more than 65k rows, then use csv format.
I dont see that reportviewer server control have a method that checks the result of the query.
I don't want to use pagebreaks inside the SSRS reports. Is there any way to ask in my code behind?
Not sure if this helps but this is a work around for exporting to excel.
Create a parent group on the tablix (or table, or list) and in the Group on: field enter the expression below.
Add Page break between each instance of a group
=CInt(Ceiling(RowNumber(nothing)/65000))
See Question on Here.
I found the solution to this particular problem like this:
Put this expression in my "Details" Group. In Disabled property: =IIF(rownumber(nothing) mod 10000=0,false,true) BreakLocation: End.
After this change, I can save this excel divided in different worksheets in the same excel sheet for every 10k rows. I tried doing the ceiling but if you have a rownumber expression inside that group it wont work.

How to rename dynamically an exported report in code or with reporting services itself?

I have tried to Google my problem, but I have found nothing about my problem.
I would like to rename dynamically my reports from Reporting Services when I export them using the ReportViewer. Basically, the format will be reportName + timestamp.
Is there anyway to do that using C# or Reporting Services itself?
Here's how I include the reportviewer on my pages:
<rsweb:ReportViewer ID="rv" runat="server" ShowToolBar="true" ShowParameterPrompts="false"
BackColor="#F0F8FF" Height="1200px" Width="100%" ProcessingMode="Remote" EnableViewState="true"
Visible="false" SizeToReportContent="True">
<LocalReport EnableExternalImages="True">
</LocalReport>
</rsweb:ReportViewer>
#Devester - Thx so much for your post of the solution to your own problem. It is appreciated and makes it easier for the rest of us!
So from your lead, I found that in my solution where I am using a local report (ie no Reporting Services), this was the only line I needed to add to change from the "MyReport.rdlc" normally exported to PDF as "MyReport.pdf" to something else:
this.rptViewer.LocalReport.DisplayName = _reportName +"_"+ DateTime.Now.ToString("yyyyMMdd HH:mm");
I solved the problem using a simple method and I hope to be able to help someone with the code below:
protected void btnCreate_Click(object sender, System.EventArgs e)
{
if (ddlExportFormat.SelectedIndex != 0)
{
ExportReport(ddlExportFormat.SelectedValue);
btnShow_Click(sender, e);
}
}
private void ExportReport(String format)
{
// Variables
Warning[] warnings;
string[] streamIds;
string mimeType = string.Empty;
string encoding = string.Empty;
string extension = string.Empty;
string fileName = _reportName +"_"+ DateTime.Now.ToString("yyyyMMdd HH:mm");
// Setup the report viewer object and get the array of bytes
ReportViewer viewer = new ReportViewer();
viewer.ProcessingMode = ProcessingMode.Local;
viewer.ServerReport.ReportServerUrl = new System.Uri(_reportServerUrl);
viewer.ServerReport.ReportPath = _reportPath;
if (this.PrepareReportParameters())
{
viewer.ServerReport.SetParameters(lstReportParameters);
}
byte[] bytes = viewer.ServerReport.Render(format, null, out mimeType, out encoding, out extension, out streamIds, out warnings);
// Now that you have all the bytes representing the PDF report, buffer it and send it to the client.
Response.Buffer = true;
Response.Clear();
Response.ContentType = mimeType;
Response.AddHeader("content-disposition", "attachment; filename=" + fileName + "." + extension);
Response.BinaryWrite(bytes); // create the file
Response.Flush(); // send it to the client to download
}
Credits to http://beta.codeproject.com/Questions/277989/How-to-export-rdlc-report-to-PDF-without-using-Rep
Its Just one line of Code
RptViewer.ServerReport.DisplayName = "Your File Name Goes Here";

Categories