Progress® Telerik® Reporting R1 2020

How To: Host Reports Service In ASP.NET Core 3+

This article guides you how to host a Reports Web Service in order to expose the Reports Generation Engine into an ASP.NET Core 3+ Web Application.

The guide is separated into sections for readability reasons. Along with the steps it elaborates on the concepts and reasons behind each step.

Prerequisites

Creating a Sample ASP.NET Core 3 Project

  1. Open Visual Studio 2019.

  2. From the File menu, select New > Project.

  3. In the Add a new Project dialog select ASP.NET Core Web Application project template. Choose a name and location for the project and click Create.

  4. In the Create a new ASP.NET Core web application dialog select from the drop downs .NET Core and ASP.NET Core 3.0 or later. Next, from the list of templates select Empty project template and click Create.

Add Report Definitions

It is recommended to use declarative definitions (TRDP/TRDX) authored using the Standalone Report Designer or the Web Report Designer in order to take advantage of their design-time tooling because the VS integrated report designer tooling is still not available in .NET Core projects.

Existing .NET Framework report libraries can be migrated to declarative report definitions as well. The other available approach is designing reports in a separate Telerik Report Library created against .NET Framework 4.0+ which later must be migrated to a .NET Standard or .NET Core library. For more information, please refer to Guidance for using reports from an existing .NET Framework 4+ report library in a .NET Core application knowledge based article. Design-time support is not yet provided for .Net Core Telerik Report Library (Class Library) projects storing the report definitions.

In this tutorial the resulting service will use the sample report definitions deployed with the Telerik Reporting product installer: Add a new folder to your solution called Reports and copy all sample reports into it. Find the sample reports in {Telerik Reporting installation path}\Report Designer\Examples. Later in the tutorial we will make sure that the ReportsController is able to resolve the definitions for the requested reports from this project folder.

Add the required dependencies

The recommended way of adding the necessary dependencies is to use the Progress Telerik proprietary NuGet feed and reference the dependencies as NuGet packages. This would also add the indirect dependencies to your project bringing easier dependency management.

Alternatively, the assemblies are available in the \Bin\netcoreapp3.0\ folder of Telerik Reporting installation directory. However, this would require to manually add all indirect dependencies listed in the Requirements section of the .NET Core Support section.

The Reporting engine relies on the GDI+ API which is available on the Windows OS. On Linux and macOS we use library called libgdiplus instead. The GDI+ API is required for measuring, laying out, rendering the text glyphs and images.

This guide will use the recommended NuGet package references approach:

  1. Reference the Telerik.Reporting.Services.AspNetCore (or Telerik.Reporting.Services.AspNetCore.Trial) package.

  2. Optionally, for export to Office OpenXML document formats (XLSX, DOCX and PPTX) install the Telerik.Reporting.OpenXmlRendering (or Telerik.Reporting.OpenXmlRendering.Trial) NuGet package and the DocumentFormat.OpenXML NuGet package version 2.7.2.0 and above.

  3. The Reporting tool uses Newtonsoft.Json so you need to add Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package. The exact version will be determined from the NuGet package manager based on the exact .NET Core version of your application.

Add Configuration Settings (Optional)

The report generation engine can retrieve Sql Connection Strings and specific Report Generation Engine Settings that provide flexibility of the deployed application.

.NET Core applications provide a new way of storing the configuration - a key-value JSON-based file named appSettings.json. To activate JSON file configuration, call the AddJsonFile extension method on an instance of ConfigurationBuilder.

In this guide we will create a helper class loading the json-formatted setting:

C#
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;

static class ConfigurationHelper
{
    public static IConfiguration ResolveConfiguration(IWebHostEnvironment environment)
    {
        var reportingConfigFileName = System.IO.Path.Combine(environment.ContentRootPath, "appsettings.json");
        return new ConfigurationBuilder()
            .AddJsonFile(reportingConfigFileName, true)
            .Build();
    }
}

Finally, all configurations should be placed in appsettings.json (add one in the project root if such does not exist). For example, ConnectionStrings setting should be configured in JSON-based format like this:

JSON
{
  ...
  "ConnectionStrings": {
    "Telerik.Reporting.Examples.CSharp.Properties.Settings.TelerikConnectionString": "Data Source=.\\SQLEXPRESS;Initial Catalog=AdventureWorks;Integrated Security=true"
  }
}

The above type of connection string lacks information about the data provider and will use System.Data.SqlClient as provider invariant name. When it's necessary to specify a different data provider, the following notation is also supported:

JSON
{
  ...
  "ConnectionStrings": {
    "Telerik.Reporting.Examples.CSharp.Properties.Settings.TelerikConnectionString": {
      "connectionString": "Data Source=.\\SQLEXPRESS;Initial Catalog=AdventureWorks;Integrated Security=true",
      "providerName": "System.Data.SqlClient"
    }
  }
}

The two types of connection string notations specified above can coexist in a single ConnectionStrings section.

The last supported type of ConnectionStrings configuration uses an array to provide information about each connection string:

JSON
{
  ...
  "ConnectionStrings": [
    {
      "name": "Telerik.Reporting.Examples.CSharp.Properties.Settings.TelerikConnectionString",
      "connectionString": "Data Source=.\\SQLEXPRESS;Initial Catalog=AdventureWorks;Integrated Security=true",
      "providerName": "System.Data.SqlClient"
    }
  ]
}

Setup the Startup.cs file for the Reports service

The ConfigureServices method inside the Startup.cs in the project should be modified in order to enable the Reports Service functionality.

  1. Make sure the application is configured for WebAPI controllers:

    C#
    services.AddControllers();
  2. In .NET Core 3 by default Synchronous operations are disallowed. Synchronous operations are necessary to download resources such as images used in the reports. They need to be manually allowed, for example by setting the AllowSynchronousIO to True in the container services.

    C#
    services.Configure<IISServerOptions>(options =>
    {
        options.AllowSynchronousIO = true;
    });
  3. Call the AddNewtonsoftJson on the IMvcBuilder object to place the NewtonsoftJson serialization.

    C#
    services.AddRazorPages()
        .AddNewtonsoftJson();
  4. Add the dedicated configuration object needed from the Reports Service in the dependency container. Note how the reports resolver will target the Reports folder we created earlier.

    C#
    // Configure dependencies for ReportsController.
    services.TryAddSingleton<IReportServiceConfiguration>(sp =>
        new ReportServiceConfiguration
        {
            ReportingEngineConfiguration = ConfigurationHelper.ResolveConfiguration(sp.GetService<IWebHostEnvironment>()),
            HostAppId = "ReportingCore3App",
            Storage = new FileStorage(),
            ReportResolver = new ReportFileResolver(
                System.IO.Path.Combine(sp.GetService<IWebHostEnvironment>().ContentRootPath, "Reports"))
        });

Make sure the endpoints configuration inside the Configure method of the Startup.cs are configured for API controllers by adding the following line in the lambda expression argument:

C#
app.UseEndpoints(endpoints =>
{
    endpoints.MapControllers();
    // ... 
});

Setting up the REST service

  1. Create folder Controllers. Right-click on the project name and select Add > New folder. Name it Controllers.

  2. Implement a Reports controller. Right-click on the Controllers folder and add a new item: Add > New item > Web API Controller Class item. Name it ReportsController. This will be our Telerik Reporting REST service in the project.

  3. Inherit the ReportsControllerBase type and inject the configuration settings in the constructor. This is how a basic implementation of the controller should look like:

    C#
    namespace AspNetCoreDemo.Controllers
    {
        using Microsoft.AspNetCore.Mvc;
        using System.Net;
        using System.Net.Mail;
        using Telerik.Reporting.Services;
        using Telerik.Reporting.Services.AspNetCore;
    
        [Route("api/reports")]
        public class ReportsController : ReportsControllerBase
        {
            public ReportsController(IReportServiceConfiguration reportServiceConfiguration)
                : base(reportServiceConfiguration)
            {
            }
    
            protected override HttpStatusCode SendMailMessage(MailMessage mailMessage)
            {
                throw new System.NotImplementedException("This method should be implemented in order to send mail messages");
    
                //using (var smtpClient = new SmtpClient("smtp01.mycompany.com", 25))
                //{
                //    smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
                //    smtpClient.EnableSsl = false;
    
                //    smtpClient.Send(mailMessage);
                //}
                //return HttpStatusCode.OK;
            }
        }
    }

Test the service implementation

To ensure that the service operates run the application and navigate to URL {applicationRoot}/api/reports/formats. It should return a JSON representing the supported rendering extensions.

In this article
Not finding the help you need?