Integrating RDLC reports to .NET Core Projects

By Tharindu Jayasinghe

Integrating RDLC reports to .NET Core Projects

One of the biggest challenges faces by many developers when moving from standard .NET framework to .NET CORE is the lack of support for RDLC reports. Microsoft has not come up with a solution for this yet. (The time I write this). There are lot of discussions going on many forums asking Microsoft to come up with a solution for this.

https://forums.asp.net/t/2156712.aspx?Calling+RDLC+in+asp+net+core

There are couple of solutions available at the moment as mentioned in here. But there is no end to end solution how you are supposed to do that.

Out of this solutions I have picked ASP.NET Core reporting library in order to cater my requirement. https://www.nuget.org/packages/AspNetCore.Reporting

In this article I am going to explain how you can integrate .NET Core Reporting library to your .NET core API. (Similarly you can integrate it to you azure function app as well).

The benefit of this library:

  • Open source
  • Comes as a nugget package and easy to implement.

Issues in the library

  • Issue related to Caching when there are multiple RDLC files (When there are multiple rdlc files available, the render function does not use the correct rdlc file. It mixes the content with the first ran rdlc file. It seems to be like a caching issue in the memory used to render the rdlc file).

How to overcome the issue

You can run a separate process within the API or Azure function and delegate the report generation logic to that process and start the process within the api or function. I will write a supplementary blog post on how to do this soon. First let's see how we can generate a pdf using a single rdlc file.

Create .NET core API project.

First you need to create your .NET core Project. (API or Azure Function app)

Go to manage nuget packages and Install AspNetCore.Reporting library to the project.

You also need to add the System.Drawing.Common Nuget package into your project.

Also add System.Text.Encoding.CodePages Nuget to your project.

Now you can create your RDLC and generate a pdf out of it. In VS you don't get templates for RDLC files yet. So assume you have a RDLC file which supported in .NET framework. Copy it to your project. Make sure you set the property of RDLC file to copy always. This way if there are changes to the rdlc file the changed rdlc file will also be there in the output folder.

Following is my Solution file structure.

In order to add dataset to your rdlc file using a Dto Object that you have created you need to create a separate project with the Dtos and add a reference to the Api project. In my example I have a created a Report.Data (.NET Standard) project and added a reference to my Report Api Project.

Here's how to add DataSet using the Dtos you have created.

Once you add the dataset you can set the dataset fields to a table as shown below.

There are lot of customizations can be done with the RDLC designer. I'm assuming you are already familiar with it. If not please follow a tutorial regarding rdlc report designing. Now let's look at more importantly how you can call this rdlc file to generate a pdf file.

Report Controller class

public class ReportController : Controller
    {
        private IReportService _reportService;

        public ReportController(IReportService reportService)
        {
            _reportService = reportService;
        }

        [HttpGet("{reportName}")]
        public ActionResult Get(string reportName)
        {
            var returnString = _reportService.GenerateReportAsync(reportName);
            return File(returnString, System.Net.Mime.MediaTypeNames.Application.Octet, reportName + ".pdf");
        }
    }

Report Service class

public class ReportService : IReportService
    {
        public byte[] GenerateReportAsync(string reportName)
        {
            string fileDirPath = Assembly.GetExecutingAssembly().Location.Replace("ReportAPI.dll", string.Empty);
            string rdlcFilePath = string.Format("{0}ReportFiles\\{1}.rdlc", fileDirPath, reportName);
            Dictionary<string, string> parameters = new Dictionary<string, string>();
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Encoding.GetEncoding("windows-1252");
            LocalReport report = new LocalReport(rdlcFilePath);

            List<UserDto> userList = new List<UserDto>();
            userList.Add(new UserDto
            {
                FirstName = "Alex",
                LastName = "Smith",
                Email = "alex.smith@gmail.com",
                Phone = "2345334432"
            });

            userList.Add(new UserDto
            {
                FirstName = "John",
                LastName = "Legend",
                Email = "john.legend@gmail.com",
                Phone = "5633435334"
            });

            userList.Add(new UserDto
            {
                FirstName = "Stuart",
                LastName = "Jones",
                Email = "stuart.jones@gmail.com",
                Phone = "3575328535"
            });

            report.AddDataSource("dsUsers", userList);
            var result = report.Execute(GetRenderType("pdf"), 1, parameters);
            return result.MainStream;
        }

        private RenderType GetRenderType(string reportType)
        {
            var renderType = RenderType.Pdf;
            switch (reportType.ToLower())
            {
                default:
                case "pdf":
                    renderType = RenderType.Pdf;
                    break;
                case "word":
                    renderType = RenderType.Word;
                    break;
                case "excel":
                    renderType = RenderType.Excel;
                    break;
            }

            return renderType;
        }
    }

If you follow the steps correctly now you can call your controller method by browser url and the browser will give you the pdf generated as below.