This section explains the steps required to add web Report Designer version higher than v8.1.xx
to a Blazor application.
Before getting started with bold web report designer, make sure your development environment includes the following requirements.
BlazorReportingTools
, then click Next.The source code for this Blazor reporting components app is available on GitHub.
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.
Right-click the project and select Add > New Item from the context menu.
In the Add New Item dialog, select API Controller Empty class and name it as BoldReportsAPIController.cs
.
Click Add.
While adding the API Controller class, it is mandatory to name it with the suffix
Controller
.
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. |
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. |
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. |
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);
}
}
}
[Route("api/{controller}/{action}/{id?}")]
.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();
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();
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.
Right-click the project and select Add > Class from the context menu.
In the Add New Item dialog, select class and name it as BoldReportDesignerOptions.cs
.
Click Add.
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; }
}
}
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
});
}
}
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>
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.
Click Run
or F5
button to launch the application.
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.