SSRS report external image source - reporting-services

I am trying to create a solution to show dynamic images in SSRS reports. I have .NET process that generates Base64 strings that after decoding returned to the client. Here is C# code:
byte[] imageBytes = Convert.FromBase64String(image);
MemoryStream exportStream = new MemoryStream(imageBytes, 0, imageBytes.Length);
exportStream.Position = 0;
return Ok(exportStream);
where image is the Base64 string.
It works fine when a client is a Browser. But in the report it shows Red X when I am running it in the report builder. Published report shows nothing at all. Seems like the report doesn't fully understand the return format or something else. Please share any idea.
Thanks
Image properties:

Related

SSRS -External image not rendering on HTML report

I am working on SSRS Report. I have a report with an external image embedded in it
This renders fine inside the report viewer.
but when I render report in HTML 4.0 format in my application via web url (without using report viewer).The report that comes back from all the data except the image is not in the html
see the image tag looks like the following:-
<img onerror="this.errored=true;" class="r1" src="http://ges-server-pc/ReportServer_SQLEXPRESS?%2FGES-MVC%2FGES_FWCR&rs%3ASessionID=vdpuofii3xtph545xelnym45&rs%3AFormat=HTML4.0&rs%3AImageID=1403af250c474da8a5f851b63a8a377b">
how can I render extrenal image on Report which is in format= HTML 4.0
Can Anybody have solution for the same It will be appreciable
Thanks in advance
Here is one way to ensure that your application can reliably display images dynamic rendered in a report by SSRS.
When you are using the report viewer control, a lot is done behind the scenes to keep an active session and allow access to all artifacts generated by reports requested by the user. When you are using the ReportExecution api directly there are some advanced reporting features that are just not supported. Interactive sorting, sizing, drilldown and this issue just to name a few.
Always ensuring dynamic images from reports are available to your client is pretty easy. I had to cross this hurdle a way back and I'll share the way I solved it.
In a nutshell, you are going to have to intercept the render, iterate the streams, and save each resource to a temp folder and tell ssrs to look for the image in your temp folder that is behind the web app that your end user has authenticated with.
DeviceInfo
The device info structure, mostly overlooked, is going to come in handy. In this structure you will find a StreamRoot property. You can find documents on this. It basically allows you to override the location from which SSRS will stream resources as needed. This is how you tell SSRS to look for your external images in a new location.
For each report rendered I create a temp folder using a guid prior to rendering. Also, prior to rendering you need to set the StreamRoot to this temp folder.
string physicalTempFolder = MakeNewTempFolderInTempOffOfWebRoot();
string virtualTempFolder = Path.Combine(yourWebRoot,"Temp",Path.GetDirectoryName(physicalTempFolder));
Now you have a physical and virtual pointer to your repo where the images will be saved for your report. Now update the StreamRoot in SSRS. This tells SSRS that we want to override the default location for dynamic images and whatnot.
StringBuilder devInfo = new StringBuilder();
if (YourRenderFormat=="HTML")
{
devInfo.Append("<DeviceInfo>");
devInfo.Append("<StreamRoot>" + virtualTempFolder+ "</StreamRoot>");
devInfo.Append("</DeviceInfo>");
}
With the needed device info structure build we can pass it into the render method.
string extension;
string mimeType;
string reportEncoding;
string[] streamIDs = null;
ReportExecution2005.Warning[] warnings = null;
ReportExecution2005.ExecutionHeader execHeader = new ReportExecution2005.ExecutionHeader();
ReportExecution2005.ExecutionInfo rpt = _execService.LoadReport(YourReportPath, null);
if(YourParamas!=null)
_execService.SetExecutionParameters(YourParams, "en-us");
_execService.ExecutionHeaderValue = execHeader;
_execService.ExecutionHeaderValue.ExecutionID = rpt.ExecutionID;
result = _execService.Render(format, devInfo.ToString(), out extension, out mimeType, out reportEncoding, out warnings, out streamIDs);
The render method returns the streamIDs out parameter and it is key here. Next after we call render, simply iterate all the streams that are images and call ssrs's RenderStream() method to get the images and save to your physical temp folder.
if (YourRenderFormat=="HTML"))
{
string imageEncoding = "";
// For each image stream returned by the call to render,
// render the stream and save it to the application root
string FilePath = physicalTempFolder;
byte[] image;
// For each image stream returned by the call to render,
// render the stream and save it to the application root
foreach (string streamID in streamIDs)
{
image = _execService.RenderStream("HTML4.0", streamID, null, out imageEncoding, out mimeType);
//All files are unique
File.WriteAllBytes(Path.Combine(physicalTempFolder,streamID),image);
}
}
return result;

Formatting XAxis labels when rendering chart on server using phantomjs and JSON

I'm using phantomjs to render png images of a highchart using a json file from a commandline script.
As it's JSON obviously I can't using the xAxis.labels.formatter as I would in a web client version, but as these are for automated reports we don't want to have to generate them through a browser.
Is there anyway of formatting the xAxis labels to be something like the result of:
Highcharts.dateFormat('%d/%m/%y %H:%M',this.value)
Currently they are showing up as what I assume is the default. e.g. 10 Feb
This doesn't even tell us what year it is.
I'm using the default "highcharts-convert.js" file as the first parameter to phantomjs
Second paramater is my highcharts configuration as a json object
Third is the name of the output file
Is it possible to do it in the callback script if so how would I pass a function to the formatter?
I've tried iterating over the collection of labels but this didn't work:
function(chart) {
$.each( chart.xAxis.labels, function( index, value ){
chart.xAxis.labels[index] = Highcharts.dateFormat('%d/%m/%y %H:%M',value);
});
}
Or are there any other alternatives that are open to me?
You can simple use xAxis.labels.format, see more info.
And demo from docs.

SSRS: Next and Previous page buttons don't work

I have a vs2012 web project using NET 3.5 and the SSRS reportviewer control (v11) running on MSSQL 2008. When the report displays the next page button doesn't work. It appears to respond to the click (ie the button is enabled and the page load event in the code behind is called) but it doesn't display a new page. When I access the report directly thru the SSRS reportserver URL, I get the same page but it works without any problems. Also, when I export the report to a PDF using the built in export option on the same screen, the correct, entire report is there. I believe viewstate is enabled...no mvc. Here is the relevant code:
ReportViewer1.ProcessingMode = Microsoft.Reporting.WebForms.ProcessingMode.Remote;
ReportViewer1.ServerReport.ReportServerUrl = new Uri(WebConfigurationManager.AppSettings["SSRSUrl"]);
param[0] = new ReportParameter("SubTitle", subTitle);
param[1] = new ReportParameter("Query", query);
param[2] = new ReportParameter("Parameters", reportParameterString);
param[3] = new ReportParameter("Title2", title2);
ReportViewer1.ShowParameterPrompts = false;
if (!IsPostBack) ReportViewer1.ServerReport.SetParameters(param);
ReportViewer1.ServerReport.Refresh();

Telerik Reporting - Passing object to UriReportSource Html5 reporting

I'm wondering how to passing the object data source into html5 report viewer.
I have view like this:
#{
var theData = new UriReportSource();
theData.Uri = "TestingReport.trdx";
//this is should passing the data right?
theData.Parameters.Add("passing", Model.pasing);
theData.Parameters.Add("anotherPassing", Model.another);
}
#(
Html.TelerikReporting().ReportViewer()
.TemplateUrl("../ReportViewer/templates/telerikReportViewerTemplate.html").Id("ReportId")
.ReportSource(theData)
.ViewMode(ViewModes.PRINT_PREVIEW)
.ScaleMode(ScaleModes.SPECIFIC)
.Scale(1.0)
.ServiceUrl("/api/reports/")
)
I already wired up the .trdx report into object data source.
And this documentation is not helping, it's use TypeDataSource.
.ServiceUrl() is what your looking for.
Url.Content("/api/reports/") is what Telerik has in their examples as the argument to ServiceUrl. It assumes the api is implemented in the same application as the client (viewer).
To go across domains the server has to apply CORS to the API
e.g.
.ServiceUrl(Url.Content("(prefix + server):9176/api/reports/"))` (a different web api application on localhost) is the call to make on the client.

Why do I sometimes get an error in Reporting Services when I export a report containing .jpg images to MS Word

When you create a report using SQL Server Reporting Services 2008 (SP1), that uses .jpg images sometimes you get the following error when you export the report to word.
Index was outside the bounds of the array.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Exception: Index was outside the bounds of the array.
Having discussed this with Microsoft support (a helpful chap called Mikael Ljunghorn) it would appear to be related to whether the .jpg image you are using in your report is encoded using 'progressive' encoding.
To prevent this from occuring, try to avoid using progressive encoded .jpg images in your report.
Mikael also suggested that the following workaround to convert a jpg image to a png sidestepping the conversion problem in word:
1)
Add this custom code block through the Report > Report Properties > Code window.
Function ConvertToPNG(ByVal bytes As Byte()) As Byte()
Dim inStream As New System.IO.MemoryStream(bytes)
Dim bmp As New System.Drawing.Bitmap(inStream)
Dim outStream As New System.IO.MemoryStream()
bmp.Save(outStream, System.Drawing.Imaging.ImageFormat.PNG)
Return outStream.GetBuffer()
End Function
2)
Wrap the database image Value expression in this call: =Code.ConvertToPNG(Fields!ImageBlobField.Value)