What are the best ways to use repository/service and dependency injection with reports?
e.g. If I have an ... ICustomerReportDataService.GetCustomers(<some parameters>) that backs my report, what is the best way to get this into my report?
Note that ICustomerReportDataService is an interface that will eventually be served by the IOC container (that does not have a parameterless constructor)
6 Answers, 1 is accepted
You can use a service to supply data for reports, where the data retrieval method operating with the service is wrapped by an ObjectDataSource. Consider the example in Connecting Telerik Reporting to OData feeds.
Thus you will just have to pass proper parameters to control the data retrieval and display the report in a viewer.
Other approach is to use a custom report resolver, where to get the report and the data. Please check the following details elaborating on the HTML5 Report Viewer and Reporting REST service architecture.
In general, the HTML5 Report Viewer is a client-side widget served only by a running Reporting REST service, which is dedicated to display already created reports. It is the service that manages the report state and resources.
Details how to add the viewer via template are available in the HTML5 Report Viewer Quickstart article
How the viewer(client)-service pair works:
Basically, the client (viewer) sends string description of the requested report (the viewer's reportSource.report value) to the service, and depending on the report resolvers in the service's CreateReportResolver method this string description will be resolved to a report source object.
By default we provide ReportFileResolver and ReportTypeResolver. You can also create your own report resolvers as in the example in the How To: Implement a Custom Report Resolver article.
Depending on how the application will be hosted, you can use the corresponding cache storage for the service - REST Service storage. If the service will be hosted separately, and will use a different domain you may need to enable CORS to allow the communication between the clients(viewers) and the service.
I hope the provided information helps you.
Regards,
Stef
Telerik
I should also point out that I intend to use the older WebForms reporting stack in a web farms scenario; meaning out of proc sessions. I would also like to be able to host these reports in a .net client side application (e.g. WPF) in the future. (Hence why I would prefer to use an interface to actually create the report data, as the implementation for the client side implementation would be different)
How do I use the ObjectDataSource with an IOC container?
As far as I can tell, the ObjectDataSource requires an actual type with a parameterless constructor.
The ObjectDataSource component purpose is to specify the data object by its assembly qualified name, and a data retrieval method getting the actual data, where this information has small size on serializing the report. If you are going to use an already instantiated data object there is no need to wrap it in a data source component as it still will be serialized in memory along with the report.
Thus the suggested approaches are:
- Use an ObjectDataSource wrapping your custom data access layer's methods, where the data access layer works with the already injected types as the example in Connecting Telerik Reporting to OData feeds.
- Do not use data source components. Instead after injecting the dependencies work with the already created data objects and use them as data items' DataSource properties. For example:
var data = GetActuakDataObjectHere();
//get an instance of the report
var report=
new
MyReport();
//modify the report to set Datasource properties
report.DataSource = data;
//set data source of a nested data item like a Table item
(report.Items.Find(
"table1"
,
true
)[0]
as
Telerik.Reporting.Table).DataSource = data;
//display the report
var IRS =
new
InstanceReportsource { ReportDocument = report};
reportViewer1.ReportSource = IRS;
In case you need a desktop application to allow users to create reports, test using the Standalone Designer tool, which configuration can be extended to load external assemblies holding the custom data access layer. The designed reports will be saved in XML format in TRDX files. The XML can be later deserialized as Telerik.Reporting.Report object and further modified and processed before displaying, if needed.
Regards,
Stef
Telerik
Hi Stef,
My data is not already instantiated as it requires parameters to generate which are fed from the report (or from outside sources i.e. url query parameters, but these will most likely be passed via the report viewer)
In all the above replies it still does not address how to my data generating service from my IOC container? Also, what affects does out of proc sessions have on this? (As my data generating service, does require constructor parameters. The actual result objects can be made into CLR objects thou)
Reports are templates which must be designed with the fields existing in the assigned data object's schema. Thus controlling what data types will be used must be done before the report requests its data. From reports you can control the amount, order of data by providing report parameters.
About the session state mode in the application, when you use the ASP.NET WebForms ReportViewer it preserves the displayed report's state and resources in memory (the ASP.NET Session). Thus these report resources get serialized with the rules of the ASP.NET Session, and to avoid issues reports must be built based on the Design Considerations for Out-proc Session State.
If you need further help, please open a support ticket and send us a demo project including test data and the mechanism for deciding which type will be used.
Regards,
Stef
Telerik