Search results
Suggest a FeaturePDF

Add Web Report Designer in Blazor application

This section explains the steps required to add web Report Designer version higher than v8.1.xx to a Blazor application.

Prerequisites

Before getting started with bold web report designer, make sure your development environment includes the following requirements.

Create a Blazor application

  1. Start Visual Studio 2022 and click Create new project.
  2. Choose Blazor Web App, then click Next. Creating a new Blazor Web App Application Project
  3. Modify the project name to BlazorReportingTools, then click Next.
  4. From the dropdown menu for Framework, choose .NET 8.0 or .NET 9.0, and then click Create. Creating a new Blazor Web App .NET 8.0 Application Project

The source code for this Blazor reporting components app is available on GitHub.

List of dependency libraries

  1. In the Solution Explorer tab, right-click the project or solution, and choose Manage NuGet Packages. Alternatively, select the Tools > NuGet Package Manager > Manage NuGet Packages for Solution menu command.
  2. Search for the BoldReports.Net.Core package, and install them in your Blazor application. The following table provides details about the packages and their usage.
Package Purpose
BoldReports.Net.Core Creates a Web API service used to process the reports.
Microsoft.AspNetCore.Mvc.NewtonsoftJson ASP.NET Core MVC features that use Newtonsoft.Json. Includes input and output formatters for JSON and JSON Patch. The package version should be 8.0.0 or higher.
Microsoft.Data.SqlClient This is an optional package for the report viewer and designer. It should be referred in project when process the RDL report and which contains the SQL Server and SQL Azure data source. Also, the package version should be 5.1.0 or higher.

Refer to the NuGet Packages section to learn more details about installing and configuring Report Designer NuGet packages.

Add Web API Controller

  1. Right-click the project and select Add > New Item from the context menu.

  2. In the Add New Item dialog, select API Controller Empty class and name it as BoldReportsAPIController.cs. Adding a new controller to the project

  3. Click Add.

    While adding the API Controller class, it is mandatory to name it with the suffix Controller.

Configure Web API

The IReportDesignerController interface contains the required actions and helper methods declaration to process the designer file and data actions. The ReportDesignerHelper and ReportHelper class contains methods that help to process Post or Get request from the control and return the response.

Methods Description
PostDesignerAction Action (HttpPost) method for posting the request for designer actions.
UploadReportAction Action (HttpPost) method for posted file actions.
SetData Writes the resource into storage location.
GetData Reads the resource from storage location.
GetImage Action (HttpGet) method for getting resource of images in the report.
PostReportAction Action (HttpPost) method for posting the request for report process.
GetResource Action (HttpGet) method for getting resource for report.
OnInitReportOptions Report initialization method that occurs when the report is about to be processed.
OnReportLoaded Report loaded method that occurs when the report and sub report start loading.

ReportDesignerHelper

The class ReportDesignerHelper contains helper methods that help to process Post or Get request from the Report Designer control and returns the response to the Report Designer control. It has the following methods.

Methods Description
GetResource Returns the report resource for the requested key.
ProcessReport Processes the report request and returns the result.

ReportHelper

The class ReportHelper contains helper methods that help process Post or Get request for report preview action and returns the response to the Report Designer. It has the following methods.

Methods Description
GetResource Returns the report resource for the requested key.
ProcessReport Processes the report request and returns the result.
  1. Open the BoldReportsAPIController and add the following codes.

    using BoldReports.Web.ReportViewer;
    using Microsoft.AspNetCore.Hosting;
    using BoldReports.Web.ReportDesigner;
    using Microsoft.Extensions.Caching.Memory;
    
    namespace BlazorReportingTools
    {
        [Route("api/{controller}/{action}/{id?}")]
        public class BoldReportsAPIController : ControllerBase, IReportDesignerController
        {
            private Microsoft.Extensions.Caching.Memory.IMemoryCache _cache;
            private IWebHostEnvironment _hostingEnvironment;
    
            public BoldReportsAPIController(Microsoft.Extensions.Caching.Memory.IMemoryCache memoryCache, IWebHostEnvironment hostingEnvironment)
            {
                _cache = memoryCache;
                _hostingEnvironment = hostingEnvironment;
            }
    
            /// <summary>
            /// Get the path of specific file
            /// </summary>
            /// <param name="itemName">Name of the file to get the full path</param>
            /// <param name="key">The unique key for report designer</param>
            /// <returns>Returns the full path of file</returns>
            [NonAction]
            private string GetFilePath(string itemName, string key)
            {
                string dirPath = Path.Combine(this._hostingEnvironment.WebRootPath, "Cache", key);
    
                if (!System.IO.Directory.Exists(dirPath))
                {
                    System.IO.Directory.CreateDirectory(dirPath);
                }
    
                return Path.Combine(dirPath, itemName);
            }
    
            /// <summary>
            /// Action (HttpGet) method for getting resource of images in the report.
            /// </summary>
            /// <param name="key">The unique key for request identification.</param>
            /// <param name="image">The name of requested image.</param>
            /// <returns>Returns the image as HttpResponseMessage content.</returns>
            public object GetImage(string key, string image)
            {
                return ReportDesignerHelper.GetImage(key, image, this);
            }
    
            /// <summary>
            /// Send a GET request and returns the requested resource for a report.
            /// </summary>
            /// <param name="resource">Contains report resource information.</param>
            /// <returns> Resource object for the given key</returns>
            public object GetResource(ReportResource resource)
            {
                return ReportHelper.GetResource(resource, this, _cache);
            }
    
            /// <summary>
            /// Report Initialization method that is triggered when report begin processed.
            /// </summary>
            /// <param name="reportOptions">The ReportViewer options.</param>
            [NonAction]
            public void OnInitReportOptions(ReportViewerOptions reportOption)
            {
                //You can update report options here
            }
    
            /// <summary>
            /// Report loaded method that is triggered when report and sub report begins to be loaded.
            /// </summary>
            /// <param name="reportOptions">The ReportViewer options.</param>
            [NonAction]
            public void OnReportLoaded(ReportViewerOptions reportOption)
            {
                //You can update report options here
            }
    
            /// <summary>
            /// Action (HttpPost) method for posting the request for designer actions.
            /// </summary>
            /// <param name="jsonData">A collection of keys and values to process the designer request.</param>
            /// <returns>Json result for the current request.</returns>
            [HttpPost]
            public object PostDesignerAction([FromBody] Dictionary<string, object> jsonResult)
            {
                return ReportDesignerHelper.ProcessDesigner(jsonResult, this, null, this._cache);
            }
    
            /// <summary>Action (HttpPost) method for posting the request for designer actions.</summary>
            /// <returns>Json result for the current request.</returns>
            public object PostFormDesignerAction()
            {
                return ReportDesignerHelper.ProcessDesigner(null, this, null, this._cache);
            }
    
            public object PostFormReportAction()
            {
                return ReportHelper.ProcessReport(null, this, this._cache);
            }
    
            /// <summary>
            /// Action (HttpPost) method for posting the request for report process.
            /// </summary>
            /// <param name="jsonResult">The JSON data posted for processing report.</param>
            /// <returns>The object data.</returns>
            [HttpPost]
            public object PostReportAction([FromBody] Dictionary<string, object> jsonResult)
            {
                return ReportHelper.ProcessReport(jsonResult, this, this._cache);
            }
    
            /// <summary>
            /// Sets the resource into storage location.
            /// </summary>
            /// <param name="key">The unique key for request identification.</param>
            /// <param name="itemId">The unique key to get the required resource.</param>
            /// <param name="itemData">Contains the resource data.</param>
            /// <param name="errorMessage">Returns the error message, if the write action is failed.</param>
            /// <returns>Returns true, if resource is successfully written into storage location.</returns>
             [NonAction]
             bool IReportDesignerController.SetData(string key, string itemId, ItemInfo itemData, out string errorMessage)
            {
                errorMessage = string.Empty;
                if (itemData.Data != null)
                {
                    System.IO.File.WriteAllBytes(this.GetFilePath(itemId, key), itemData.Data);
                }
                else if (itemData.PostedFile != null)
                {
                    var fileName = itemId;
                    if (string.IsNullOrEmpty(itemId))
                    {
                        fileName = System.IO.Path.GetFileName(itemData.PostedFile.FileName);
                    }
    
                    using (System.IO.MemoryStream stream = new System.IO.MemoryStream())
                    {
                        itemData.PostedFile.OpenReadStream().CopyTo(stream);
                        byte[] bytes = stream.ToArray();
                        var writePath = this.GetFilePath(fileName, key);
    
                        System.IO.File.WriteAllBytes(writePath, bytes);
                        stream.Close();
                        stream.Dispose();
                    }
                }
                return true;
            }
    
            /// <summary>
            /// Gets the resource from storage location.
            /// </summary>
            /// <param name="key">The unique key for request identification.</param>
            /// <param name="itemId">The unique key to get the required resource.</param>
            ///  <returns>Returns the resource data and error message.</returns>
            [NonAction]
            public ResourceInfo GetData(string key, string itemId)
            {
                var resource = new ResourceInfo();
                try
                {
                    var filePath = this.GetFilePath(itemId, key);
                    if (itemId.Equals(Path.GetFileName(filePath), StringComparison.InvariantCultureIgnoreCase) && System.IO.File.Exists(filePath))
                    {
                        resource.Data = System.IO.File.ReadAllBytes(filePath);
                    }
                    else
                    {
                        resource.ErrorMessage = "File not found from the specified path";
                    }
                }
                catch (Exception ex)
                {
                    resource.ErrorMessage = ex.Message;
                }
                return resource;
            }
    
            /// <summary>
            /// Action (HttpPost) method for posted or uploaded file actions.
            /// </summary>
            [HttpPost]
            public void UploadReportAction()
            {
                ReportDesignerHelper.ProcessDesigner(null, this, this.Request.Form.Files[0], this._cache);
            }
        }
    }
    • To request the report processing unit properly, we changed the router API attribute to include the controller and action names using [Route("api/{controller}/{action}/{id?}")].
  2. To invoke this Web API with the controller and action, we have to include AddControllers() and AddMemoryCache() builder services and MapControllers() in the Program.cs file.

    builder.Services.AddControllers();
    builder.Services.AddMemoryCache();
    
    ...
    ...
    ...
    
    app.MapControllers();
  3. You can replace the below template code in the Program.cs file.

    using BlazorReportingTools.Components;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add services to the container.
    builder.Services.AddControllers();
    builder.Services.AddMemoryCache();
    builder.Services.AddRazorComponents()
        .AddInteractiveServerComponents();
    
    var app = builder.Build();
    
    // Configure the HTTP request pipeline.
    if (!app.Environment.IsDevelopment())
    {
        app.UseExceptionHandler("/Error", createScopeForErrors: true);
        // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
        app.UseHsts();
    }
    
    app.UseHttpsRedirection();
    
    app.UseStaticFiles();
    
    app.UseAntiforgery();
    app.MapControllers();
    
    app.MapRazorComponents<App>()
        .AddInteractiveServerRenderMode();
    
    app.Run();

Initialize the Report Designer

In this section, we are going to integrate Bold Reports® JavaScript controls by creating an interop file to initialize the report designer with basic parameters.

  1. Right-click the project and select Add > Class from the context menu.

  2. In the Add New Item dialog, select class and name it as BoldReportDesignerOptions.cs. Adding a new class file to the project

  3. Click Add.

  4. Add the following code to the BoldReportDesignerOptions.cs file to hold the RDL report rendering properties.

     namespace BlazorReportingTools
     {
         public class BoldReportDesignerOptions
         {
             public string ServiceURL { get; set; }
         }
     }
  5. Create a boldreports-interop.js file inside the wwwroot/scripts folder and use the following code snippet to invoke the Bold Report Designer JavaScript control.

    // Interop file to render the Bold Report Designer component with properties.
    window.BoldReports = {
        RenderDesigner: function (elementID, reportDesignerOptions) {
            $("#" + elementID).boldReportDesigner({
                serviceUrl: reportDesignerOptions.serviceURL
            });
        }
    }
  6. Reference the following online CDN links along with the boldreports-interop.js interop file in the head section of the Components/App.razor file to use our JavaScript reporting controls in the Blazor application.

         <!-- Report Designer component styles -->
         <link href="https://cdn.boldreports.com/9.1.7/content/v2.0/tailwind-light/bold.report-designer.min.css" rel="stylesheet" />
         <link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.37.0/codemirror.min.css" rel="stylesheet" />
         <link href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.37.0/addon/hint/show-hint.min.css" rel="stylesheet" />
    
         <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
    
         <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.37.0/codemirror.min.js" type="text/javascript"></script>
         <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.37.0/addon/hint/show-hint.min.js" type="text/javascript"></script>
         <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.37.0/addon/hint/sql-hint.min.js" type="text/javascript"></script>
         <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.37.0/mode/sql/sql.min.js" type="text/javascript"></script>
         <script src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.37.0/mode/vb/vb.min.js" type="text/javascript"></script>
    
         <!-- Report Designer component dependent scripts -->
         <script src="https://cdn.boldreports.com/9.1.7/scripts/v2.0/common/bold.reports.common.min.js"></script>
         <script src="https://cdn.boldreports.com/9.1.7/scripts/v2.0/common/bold.reports.widgets.min.js"></script>
    
         <!-- Report Viewer and Designer component scripts -->
         <script src="https://cdn.boldreports.com/9.1.7/scripts/v2.0/bold.report-viewer.min.js"></script>
         <script src="https://cdn.boldreports.com/9.1.7/scripts/v2.0/bold.report-designer.min.js"></script>
    
    
        <!-- Blazor interop file -->
        <script src="scripts/boldreports-interop.js"></script>
  7. Inject IJSRuntime and add InteractiveServer rendermode and invoke this JavaScript interop and the created BoldReportsAPI URL in the Components/Pages/Home.razor file to visualize the report designer.

    @page "/"
    @rendermode InteractiveServer
    
    @using Microsoft.JSInterop
    @using Microsoft.AspNetCore.Components
    @inject IJSRuntime JSRuntime
    @using BlazorReportingTools;
    
    <div id="designer" style="width: 100%;height: 950px"></div>
    
    @code {
        // ReportDesigner options
        BoldReportDesignerOptions designerOptions = new BoldReportDesignerOptions();
    
        // Used to render the Bold Report Designer component in Blazor page.
        public async void RenderReportDesigner()
        {
            designerOptions.ServiceURL = "https://demos.boldreports.com/services/api/ReportingAPI";
            await JSRuntime.InvokeVoidAsync("BoldReports.RenderDesigner", "designer", designerOptions);
        }
        // Initial rendering of Bold Report Designer
        protected override void OnAfterRender(bool firstRender)
        {
            RenderReportDesigner();
        }
    }

Here we created and used BoldReportDesignerOptions to pass the parameters for report designer. In the future, if we need any additional parameters, we can just include them in the BoldReportDesignerOptions.cs file.

Run the Application

Click Run or F5 button to launch the application.

Report Designer Output

Note: You can refer to our feature tour page for the Blazor Report Designer to see its innovative features. Additionally, you can view our Blazor Report Designer examples which demonstrate the rendering of SSRS RDLC and RDL reports.

See Also

Bold Reports® Licensing