Display report (byte[]) in blazor viewer

3 Answers 196 Views
.NET Core Rendering Report Viewer - Blazor
David
Top achievements
Rank 1
Iron
David asked on 03 Apr 2023, 05:51 PM

Hello,

I have an WebAssembly blazor project and I am trying to display a report in a Telerik ReportViewer. I am not even sure if what i'm trying to accomplish can be done. I would like some help / idea on how I can accomplish that.

Here how my project is setup. The client side, make a call to a controller, which does some logic (go to the database, get some data) then send that data into the report. The controller return a byte[] which contains the report (in PDF format for now)

Here an example of the code in the Server Side

	[Route("api/[controller]")]
	[ApiController]
	public class ReportsController : Controller
	{
		[HttpPost("CreateReport")]
		public ActionResult CreateReport(ReportCriteria criteria)
		{
                        var datas = repo.GetData(criteria);
                         
                        var myReport = new MyOwnReport(); // instance of type Telerik.Reporting.Report
                        myReport.objDataSource.DataSource = datas;
                        myReport.txtTitleValue = "My Report Title";
                        ... // other manual operation on the report

			ReportProcessor reportProcessor = new ReportProcessor();
			InstanceReportSource instanceReportSource = new InstanceReportSource
			{
				ReportDocument = myReport 
			};

			RenderingResult result = reportProcessor.RenderReport("PDF", instanceReportSource, null);

			return Ok(result.DocumentBytes);
		}
	}


Is there any way that, on the client side, when I receive those bytes, I put those bytes directly on a Telerik Report Viewer ? Something like this, but using ur Telerik report? (where _report is the byte[])

<embed src="@_report" style="width: 100%; height: 100%;" />

 

Any idea how I can accomplish something like that? I feel like the Telerik reporting only work when all the logic is inside the "Telerik.Reporting.Report class" but its doesnt really work with the way our report are build.

Any help or tips or direction will be apreciated

 

Thank you 

David

 

3 Answers, 1 is accepted

Sort by
0
Accepted
Todor
Telerik team
answered on 06 Apr 2023, 10:50 AM

Hi David,

Telerik Web (including Blazor) Report Viewers need a Reporting REST Service for report rendering. They cannot display reports that are rendered otherwise. This is by design. If you already have a PDF report document, you may preview it, for example, in PDF Viewer.

You may check how to create a REST Service in the article ASP.NET Core Web API Implementation in .NET and .NET Core. It is a Web API Controller inheriting from our ReportsControllerBase class.

Just to remind you that the Reporting engine cannot be hosted in Blazor WebAssembly due to lacking GDI+ (System.Drawing) - Blazor WASM Project Throws System.Drawing.Common Is Not Supported on this Platform.

You may use either of our two Blazor viewers with the REST Service:

They may be hosted in a WebAssembly project and may use the same REST Service simultaneously.

If you need to modify the report definition in run-time, you have to use a Custom ReportSource Resolver, which Resolve method to return a valid server-side ReportSource, for example, the InstanceReportSource from your code snippet.

Here is also more information on the communication between the Report Viewers and the Reporting Service - Telerik Report Viewer and Telerik Reporting REST Service.

Regards,
Todor
Progress Telerik

Brand new Telerik Reporting course in Virtual Classroom - the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products. Check it out at https://learn.telerik.com/.
David
Top achievements
Rank 1
Iron
commented on 06 Apr 2023, 04:09 PM

Hi Todor, 

Thank you for your answer, I was able to get the Native Blazor Viewer to somewhat work. But now I have a problem with the parameters.

The viewer make 3 call to the server with different operationOrigin, but I only got my harcoded criteria during the first call. I used this to help me but I'm not sure I understand it correctly cause I can't seem to make it work.

Here is my ReportSourceResolver class

		public ReportSource Resolve(string reportId, OperationOrigin operationOrigin, IDictionary<string, object> currentParameterValues)
		{
			switch (reportId)
			{
				default:
					switch (operationOrigin)
					{
						case OperationOrigin.ResolveReportParameters:
							//HERE I GOT MY CRITERIA
							var instance = new InstanceReportSource
							{
								ReportDocument = new RapportCaisse(), 
							};

							return instance;
						case OperationOrigin.CreateReportInstance:
							//HERE NO CRITERIA
							return new InstanceReportSource
							{
								ReportDocument = new RapportCaisse()
							};
						case OperationOrigin.GenerateReportDocument:
							//HERE NO CRITERIA
							JObject jsonObject = currentParameterValues["criteria"] as JObject;
							RapportCaisseCriteria criteria = jsonObject.ToObject<RapportCaisseCriteria>();

							return _reportService.CreateRapportCaisseMaster2(criteria);
						default:
							throw new InvalidOperationException();
					}
			}

			//RapportCaisseCriteria criteria2 = new RapportCaisseCriteria();
			//return _reportService.CreateRapportCaisseMaster2(criteria2);
		}
	}

and here the client side

<ReportViewer
    ServiceType="@ReportViewerServiceType.REST"
    ServiceUrl="/reporting/api/test"
    ReportSource="@(new ReportSourceOptions("RapportCaisse", new Dictionary<string, object>
			{
				{
					"criteria" , new RapportCaisseCriteria() {
						Sommaire = false,
						AjouterDetailHeureTravaillee = true,
						DetailParPointDeVente = true,
						CodeEtablissement = "000012",
						DateDebut = DateTime.Now.AddYears(-3),
						DateFin = DateTime.Now,
						CodeRegroupements = new List<string>(),
						NumeroCaissiers = new List<short>()
					}
				}
			}))"
	@bind-ScaleMode="@ScaleMode"
    @bind-ViewMode="@ViewMode"
    @bind-ParametersAreaVisible="@ParametersAreaVisible"
    @bind-DocumentMapVisible="@DocumentMapVisible"
    @bind-Scale="@Scale">
</ReportViewer>

Even when I hardcode it (like the example above) the parameter dictionary is empty (no criteria key inside it) during the second (OperationOrigin = CreateReportInstance) and third call to the server (OperationOrigin =GenerateReportDocument). I only got the criteria and its value during the first call (OperationOrigin = ResolveReportParameters).

For now, the "report parameters" are before we show the report viewer, so I don't even want use the "parameters area" (we might use it later) so we just want to use the report with some parameter the client already choose in a step before.

If i hardcode the parameter server side (the two last line in the example above in comment) its work great, I can see my data and all. Any idea what i'm doing wrong?

Thank you

David

0
David
Top achievements
Rank 1
Iron
answered on 06 Apr 2023, 04:07 PM | edited on 06 Apr 2023, 04:08 PM
-
0
Todor
Telerik team
answered on 11 Apr 2023, 08:58 AM

Hello David,

I confirm that the observed behavior is expected. All the parameter values from the client-side reportSource are available during OperationOrigin.ResolveReportParameters even when there are no such parameters in the report definition. In the later calls to the Resolve method, you get the values only of the parameters that exist in the report definition. For that reason, I suspect that the parameter "criteria" doesn't exist in your report.

I tested locally with a report that had two parameters named "Parameter1" and "Parameter2". Their default values were "default1" and "default2". Here are the parameter values I received in the "currentParameterValues" of the Native Blazor Viewer's REST Service custom ReportSource resolver:

!!!OperationOrigin!!! ResolveReportParameters
	[Parameter1, viewer1]
	[Parameter2, viewer2]
	[criteria, {
  "sommaire": false,
  "ajouterDetailHeureTravaillee": true,
  "detailParPointDeVente": true,
  "codeEtablissement": "000012",
  "dateDebut": "2020-04-11T11:37:15.2477702+03:00",
  "dateFin": "2023-04-11T11:37:15.2477743+03:00",
  "codeRegroupements": [],
  "numeroCaissiers": []
}]
!!!OperationOrigin!!! CreateReportInstance
	[Parameter1, viewer1]
	[Parameter2, viewer2]
!!!OperationOrigin!!! GenerateReportDocument
	[Parameter1, viewer1]
	[Parameter2, viewer2]

When I added the "string" parameter "criteria" in the report, I received an error that the parameter value is not valid on the second request "!!!OperationOrigin!!! CreateReportInstance". The reason is the complex object that was passed, and when trying to match it with the parameter in the report definition, there is a failure. Note that the Report Parameters support only the listed types in Report Parameter Properties.

In summary, if you want to use the client ReportSource parameters to pass complex objects to the REST Service, you need to assure that you don't have such a parameter in the report definition, so you don't receive an error, and cache the value on the "ResolveReportParameters" request to be reused later. The parameter values are serialized, so you will have to deserialize the complex object server-side.

Regards,
Todor
Progress Telerik

Brand new Telerik Reporting course in Virtual Classroom - the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products. Check it out at https://learn.telerik.com/.
David
Top achievements
Rank 1
Iron
commented on 11 Apr 2023, 07:21 PM | edited

Alright, ty for all your answers

David

Tags
.NET Core Rendering Report Viewer - Blazor
Asked by
David
Top achievements
Rank 1
Iron
Answers by
Todor
Telerik team
David
Top achievements
Rank 1
Iron
Share this question
or