Save SSRS Report as pdf using Reporting Services - pdf

I've been trying to convert a SSRS Report to PDF and save to my local drive using the Reporting Web Services. Though I'm able to generate the corresponding pdf file but the contents of the file are missing. I've checked that the report I'm trying to convert is not an empty one. Only the header section is present there within the generated pdf files. Below is the code I'm using:
protected void GeneratePDFFromReport(object sender, EventArgs e)
{
RS2005.ReportingService2005 rs;
RE2005.ReportExecutionService rsExec;
// Create a new proxy to the web service
rs = new RS2005.ReportingService2005();
rsExec = new RE2005.ReportExecutionService();
// Authenticate to the Web service using Windows credentials
rs.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
rsExec.Credentials = new System.Net.NetworkCredential("username", "password", "domain");
//rsExec.Credentials = System.Net.CredentialCache.DefaultCredentials;
rs.Url = "http://servername/reportserver/reportservice2005.asmx";
rsExec.Url = "http://servername/reportserver/reportexecution2005.asmx";
string historyID = null;
string deviceInfo = null;
string format = "PDF";
Byte[] results;
string encoding = String.Empty;
string mimeType = "application/pdf";
string extension = String.Empty;
RE2005.Warning[] warnings = null;
string[] streamIDs = null;
// Path of the Report - XLS, PDF etc.
string fileName = #"C:\Report\MemberReport.pdf";
// Name of the report - Please note this is not the RDL file.
string _reportName = #"/ReportFolder/ReportName";
string _historyID = null;
bool _forRendering = false;
RS2005.ParameterValue[] _values = null;
RS2005.DataSourceCredentials[] _credentials = null;
RS2005.ReportParameter[] _parameters = null;
try
{
_parameters = rs.GetReportParameters(_reportName, _historyID, _forRendering, _values, _credentials);
RE2005.ExecutionInfo ei = rsExec.LoadReport(_reportName, historyID);
results = rsExec.Render(format, deviceInfo,
out extension, out encoding,
out mimeType, out warnings, out streamIDs);
try
{
FileStream stream = File.Create(fileName, results.Length);
stream.Write(results, 0, results.Length);
stream.Close();
}
catch { }
results = null;
}
catch (Exception ex)
{
throw ex;
}
}
Any help would highly be appreciated. Thanks.

Assuming that SSRS is working OK using browser, please modify your posted code as shown below:
1) Device info string, please set it as follows:
string deviceInfo = #"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>"; //Initial value was null
2) Create Header instance before using web call LoadReport:
ExecutionHeader execHeader = new ExecutionHeader();
RE2005.ExecutionHeaderValue = execHeader;

Related

Index Out of Bound exception while rendering RDLC Reports in ASP.NET Core

My ASP.NET Core MVC project has several reports. To render the reports as PDF, I'm using AspNetCore.Reporting library.
This library works fine for a single report but due to some cache issues it throws an exception while generating another report. The solution I found on the internet was to run report generation as a new process but I don't know how to implement that.
I found the suggestion to use Tmds.ExecFunction to run report generation as a seperate process. But I dont know how to pass parameters to the function.
Here is my code:
string ReportName = "invoiceDine";
DataTable dt = new DataTable();
dt = GetInvoiceItems(invoiceFromDb.Id);
Dictionary<string, string> param = new Dictionary<string, string>();
param.Add("bParam", $"{invoiceFromDb.Id}");
param.Add("gParam", $"{salesOrderFromDb.Guests}");
param.Add("tParam", $"{invoiceFromDb.Table.Table}");
param.Add("dParam", $"{invoiceFromDb.Time}");
param.Add("totalP", $"{invoiceFromDb.SubTotal}");
param.Add("t1", $"{tax1}");
param.Add("t2", $"{tax2}");
param.Add("tA1", $"{tax1Amount}");
param.Add("tA2", $"{tax2Amount}");
param.Add("AT1", $"{totalAmountWithTax1}");
param.Add("AT2", $"{totalAmountWithTax2}");
param.Add("terminalParam", $"{terminalFromDb.Name}");
param.Add("addressParam", $"{t.Address}");
param.Add("serviceParam", "Service Charges of applicable on table of " + $"{personForServiceCharges}" + " & Above");
var result = reportService.GenerateReport(ReportName, param, "dsInvoiceDine", dt);
return File(result,"application/Pdf");
This is my version of the function:
``` public byte[] GenerateReport(string ReportName, Dictionary<string,string> Parameters,string DataSetName,DataTable DataSource )
{
string guID = Guid.NewGuid().ToString().Replace("-", "");
string fileDirPath = Assembly.GetExecutingAssembly().Location.Replace("POS_Website.dll", string.Empty);
string ReportfullPath = Path.Join(fileDirPath, "\\Reports");
string JsonfullPath = Path.Join(fileDirPath,"\\JsonFiles");
string rdlcFilePath = string.Format("{0}\\{1}.rdlc", ReportfullPath, ReportName);
string generatedFilePath = string.Format("{0}\\{1}.pdf", JsonfullPath, guID);
string jsonDataFilePath = string.Format("{0}\\{1}.json", JsonfullPath, guID);
File.WriteAllText(jsonDataFilePath, JsonConvert.SerializeObject(DataSource));
FunctionExecutor.Run((string[] args) =>
{
// 0 : Data file path - jsonDataFilePath
// 1 : Filename - generatedFilePath
// 2 : RDLCPath - rdlcFilePath
ReportResult result;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
Encoding.GetEncoding("windows-1252");
LocalReport report = new LocalReport(args[2]);
DataTable dt = JsonConvert.DeserializeObject<DataTable>(File.ReadAllText(args[0]));
report.AddDataSource(args[3], dt);
result = report.Execute(RenderType.Pdf, 1,Parameters);
using (var fs = new FileStream(args[1], FileMode.Create, FileAccess.Write))
{
fs.Write(result.MainStream);
}
}, new string[] {jsonDataFilePath, generatedFilePath, rdlcFilePath, DataSetName });
var memory = new MemoryStream();
using (var stream = new FileStream(Path.Combine("", generatedFilePath), FileMode.Open))
{
stream.CopyTo(memory);
}
File.Delete(generatedFilePath);
File.Delete(jsonDataFilePath);
memory.Position = 0;
return memory.ToArray();
}
But it throws exception "Field marshaling is not supported by ExecFunction" on line:
var result = reportService.GenerateReport(ReportName, param, "dsInvoiceDine", dt);
No Need to run report generation as a seperate process. Just Dont Pass extension as 1
in:
var result = localReport.Execute(RenderType.Pdf, 1, param);
The Solution is:
int ext = (int)(DateTime.Now.Ticks >> 10);
var result = localReport.Execute(RenderType.Pdf, ext, param);

Report Viewer and Web Api

In MVC I could generate .xsl or .pdf file with no issues with File(), but with the web Api nothing is happening when the action is fired! This is what I have tried so far.
I have tried a couple of solutions in here including this one Web API and report viewer
but nothing has worked for me.
public HttpResponseMessage Export(ExportVolunteerSearchFilter searchModel)
{
if (searchModel.Equals(null))
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
var volunteers = _volunteersService.ExportAllVolunteersData(searchModel);
ReportViewer ReportViewer1 = new ReportViewer();
ReportViewer1.SizeToReportContent = true;
ReportViewer1.LocalReport.ReportPath =
System.Web.HttpContext.Current.Server.MapPath("~/Reports/VolunteersReport.rdlc");
ReportViewer1.LocalReport.EnableExternalImages = true;
ReportViewer1.LocalReport.DataSources.Clear();
ReportDataSource _rsource = new ReportDataSource("DataSet1", volunteers);
ReportViewer1.LocalReport.DataSources.Add(_rsource);
ReportViewer1.LocalReport.Refresh();
Warning[] warnings;
string[] streamIds;
string mimeType = string.Empty;
string encoding = string.Empty;
string extension = string.Empty;
string fileName = "reportVolunteer";
HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
var stream = new FileStream(System.Web.HttpContext.Current.Server.MapPath("~/Reports/VolunteersReport.rdlc"), FileMode.Open);
response.Content = new StreamContent(stream);
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
response.Content.Headers.ContentDisposition.FileName = fileName;
response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/xls");
return response;
}
I have done it as:-
response.Content = new PushStreamContent(
async (outstream) =>
{
await getDataMethod(outstream)
},
new MediaTypeHeadrerValue(mediaType:"application/xls"));
response.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileName = $"test.xls"
};
return response;

Downloaded file from folder includes %2F char on .NET Core

This must be a dumb question.
I have a web API Rest on c# that have an endpoint to generate and download an excel file. I use NPOI library.
It works fine if the file is generated within the root of my site. But when I try to move my file to a folder, file name include folder and de %2F char. I suppose this is an URL encode problem, but don't know how to fix it. This is my code.
[AllowAnonymous]
[HttpGet("ExportExcel")]
public async Task<IActionResult> ExportExcel(int activos = 1, int idarticulo = -1, string filtro = "", string ordenar = "", int ordenarsentido = 1)
{
var memory = new MemoryStream();
var newFile = #"Export/Articulos.xlsx";
//IArticulosService articulosService = new ArticulosService(_validation.sConnectionString, _validation.sEmpresa);
var mycon = _validation.GetConnectionStringFromClientID("ClientId1");
IArticulosService articulosService = new ArticulosService(mycon, "Ciatema");
try
{
// Genero el excel con el listado
articulosService.ExportarExcel(newFile, activos, filtro, ordenar, ordenarsentido);
using (var stream = new FileStream(newFile, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", newFile);
}
catch (QueryFormatException ex)
{
return BadRequest(ex.Message);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
Donwload filename is: Export%2FArticulos.xlsx when i need it to be only Articulos.xlsx.
Thanks!
you should be passing file name only instead of complete path in your return File method like below
return File(memory, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Path.GetFileName(newFile));

Calling Webmethod containing byte array (as in paramaeter)parameter with ksoap2 on android

There is WEB service written on C# with next method:
[WebMethod]
public string ByteArrTest(byte[] Buffer)
{
if (Buffer == null) return "buffer is null";
else return Buffer.Length.ToString() + " is buffer length";
}
i 'ld like call this method from android device using Ksoap2 library alike belove (simplified):
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(
SoapEnvelope.VER11);
envelope.dotNet = true;
new MarshalBase64().register(envelope);
envelope.encodingStyle = SoapEnvelope.ENC;
SoapObject request = new SoapObject(this.getNameSpace(), this.getMethodName());
PropertyInfo pi4 = new PropertyInfo();
pi4.setName("Buffer");
byte [] b="this text".getBytes();
pi4.setValue(b);
pi4.setType(byte[].class);
// request.addProperty("buffer", "bytes".getBytes);
request.addProperty(pi4);
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport =
new HttpTransportSE(this.getURL());//
androidHttpTransport.call(this.getSoapAction(), envelope);
Object response = envelope.getResponse();
//next implementation
Responce always is "buffer is null"
what is incorrect or wrong?
Thanks for any attention
Posting the whole of your method in Android calling the web service would help more.
I'm using KSoap in an Android project I'm currently working on and I'm retrieving strings. Heres one of my methods modified to match what you need:
private static String NAMESPACE = "http://tempuri.org/";
private static String SOAP_ACTION = "http://tempuri.org/";
private static final String URL = "Your url link to your web services asmx file";
public static String ByteArrTestCall(byte[] t) {
String resTxt = null;
SoapObject request = new SoapObject(NAMESPACE, "ByteArrTest");
// Add the property to request object
request.addProperty("Buffer", t);
SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
envelope.dotNet = true;
envelope.setOutputSoapObject(request);
HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
androidHttpTransport.debug = true;
try
{
androidHttpTransport.call(SOAP_ACTION+"ByteArrTest", envelope);
SoapPrimitive receivedString = (SoapPrimitive) envelope.getResponse();
resTxt = receivedString.toString();
}
catch(Exception e)
{
resTxt = androidHttpTransport.requestDump;
return e.toString() + resTxt;
}
return resTxt;
}

SQL Server Reporting - Credentials

I have been working on SQL Server Reporting Services 2008, and i am connecting to report server from asp.net using below code:
ReportExecutionService rs = new ReportExecutionService();
System.Net.CredentialCache.DefaultNetworkCredentials.Domain = ConfigurationManager.AppSettings["Domain"].ToString();
System.Net.CredentialCache.DefaultNetworkCredentials.UserName = ConfigurationManager.AppSettings["UserName"].ToString();
System.Net.CredentialCache.DefaultNetworkCredentials.Password = ConfigurationManager.AppSettings["Password"].ToString();
rs.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
// Render arguments
byte[] result = null;
string reportpath = reportPath;
string format = "PDF";
string historyID = null;
string devInfo = #"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
string encoding;
string mimeType;
string extension;
ParameterValue[] parameters = new ParameterValue[1];
parameters[0] = new ParameterValue();
parameters[0].Name = reportParameterBidName.Trim();
parameters[0].Value = reportParameterBidValue.Trim();
Warning[] warnings = null;
string[] streamIDs = null;
ExecutionInfo execInfo = new ExecutionInfo();
ExecutionHeader execHeader = new ExecutionHeader();
rs.ExecutionHeaderValue = execHeader;
execInfo = rs.LoadReport(reportpath, historyID);
rs.SetExecutionParameters(parameters, "en-us");
String SessionId = rs.ExecutionHeaderValue.ExecutionID;
try
{
result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
return result;
}
catch (SoapException e)
{
return null;
}
Now it works well with my local server, when i upload it to final server it does not work and throws unable to connect error. If i use VPN and use same credentials then too it is working.
Please advise on this.