Blazorise Reporting
Start with a small declarative Razor report, add application data and design tools when needed, and move to definition-based or imperative workflows as the report becomes part of a larger application.
Installation
Install the Blazorise.Reporting package, register the reporting services, and include the reporting stylesheet in your host page.
NuGet
Install extension from NuGet.Install-Package Blazorise.Reporting
Imports
In your main _Imports.razor add:
@using Blazorise.Reporting
Static files
Add the reporting stylesheet inside the<head> section of your host page.
<link href="_content/Blazorise.Reporting/blazorise.reporting.css?v=2.3.0.0" rel="stylesheet" />
Services
Add Reporting after Blazorise services are registered.
builder.Services
.AddBlazorise()
.AddBlazoriseReporting();
Overview
The <Report> component brings four parts together:
-
A
<ReportDefinition>describes pages, bands, elements, data-source metadata, formulas, running totals, and designer settings. - Runtime data supplies the values rendered by fields and repeated detail bands.
- Design mode edits the definition, while preview mode renders that same definition as HTML or PDF.
- Application code can capture, load, serialize, or construct the definition without changing the rendering model.
Examples
Declarative report
The easiest way to begin is to describe the report in Razor. A <ReportPage> contains ordered bands such as <ReportHeader>, <ReportDetail>, and <ReportFooter>. Elements such as <ReportText> are positioned inside those bands.
This first report contains one page, one report header, and two text elements. No data source, designer, persistence code, or explicit definition is required.
During initialization, the declarative components are converted into a <ReportDefinition>. With the default ReportDefinitionMode.SeedWhenEmpty, that generated definition becomes the initial report whenever no saved Definition is supplied.
<Report ShowToolbar="false"> <ReportPage Name="Welcome"> <ReportHeader Name="Welcome header" Height="90"> <ReportText Text="My first report" X="30" Y="18" Width="300" Height="27" FontSize="20" Bold FontColor="@ReportColors.Blue" /> <ReportText Text="This content is declared entirely in Razor." X="30" Y="51" Width="360" Height="18" /> </ReportHeader> </ReportPage> </Report>
Data binding
Add <ReportDataSources> when the report needs named data sources that are visible to the designer. An object data source exposes the object's scalar properties, nested objects, and collections as report fields.
A detail band repeats when its DataSource resolves to a collection. Fields inside that band are evaluated against the current collection item, while fields in report-level bands can use paths from the root data source.
This invoice adds an object data source, a repeating detail band, formatted fields, and report headers and footers while keeping the report template declarative.
Insert aggregate
Running total
Insert group
Connect data source
No provider settings defined.
Edit formula
| Item | Formula |
| Description | Select a field, function, or operator to insert it into the formula. |
<Report Data="" Editable PreviewFormats="ReportPreviewFormat.Html | ReportPreviewFormat.Pdf"> <ReportDataSources> <ReportObjectDataSource Name="Invoice" Data="" /> </ReportDataSources> <ReportPage Name="Invoice" Size="ReportPageSize.A4" Orientation="ReportOrientation.Portrait"> <ReportHeader Name="Invoice report header" Height="97.5"> <ReportText Text="Invoice summary" X="30" Y="18" Width="210" Height="25.5" FontSize="21" Bold /> <ReportText Text="Customer: {Customer.Name}" X="300" Y="54" Width="180" Height="21" Bold /> </ReportHeader> <ReportPageHeader Name="Invoice page header" Height="31.5"> <ReportText Text="Invoice" X="30" Y="7.5" Width="67.5" Height="18" Bold /> <ReportText Text="Description" X="112.5" Y="7.5" Width="165" Height="18" Bold /> <ReportText Text="Line total" X="405" Y="7.5" Width="90" Height="18" Bold TextAlignment="TextAlignment.End" /> </ReportPageHeader> <ReportDetail Name="Invoice lines" Height="39" DataSource="Invoice.Lines"> <ReportField Field="Sku" X="30" Y="10.5" Width="67.5" Height="18" /> <ReportField Field="Description" X="112.5" Y="10.5" Width="165" Height="18" /> <ReportField Field="Total" Format="@ReportFormats.Currency()" X="405" Y="10.5" Width="90" Height="18" /> </ReportDetail> <ReportFooter Name="Invoice report footer" Height="54"> <ReportLine X="30" Y="7.5" Width="465" Height="8" Thickness="1" /> <ReportText Text="Invoice total" X="30" Y="21" Width="135" Height="18" /> <ReportField Field="Header.Total" Format="@ReportFormats.Currency()" X="405" Y="21" Width="90" Height="18" Bold /> </ReportFooter> </ReportPage> </Report>
@code { private readonly InvoiceReportModel invoice = new() { Header = new() { Number = "INV-1001", Total = 1240.50m, }, Customer = new() { Name = "Northwind Traders", }, Lines = [ new() { Sku = "SRV-001", Description = "Implementation workshop", Total = 640.50m }, new() { Sku = "LIC-010", Description = "Reporting module license", Total = 500.00m }, new() { Sku = "SUP-003", Description = "Priority support", Total = 100.00m }, ], }; private sealed class InvoiceReportModel { public InvoiceHeaderModel Header { get; set; } public InvoiceCustomerModel Customer { get; set; } public List<InvoiceLineModel> Lines { get; set; } = []; } private sealed class InvoiceHeaderModel { public string Number { get; set; } public decimal Total { get; set; } } private sealed class InvoiceCustomerModel { public string Name { get; set; } } private sealed class InvoiceLineModel { public string Sku { get; set; } public string Description { get; set; } public decimal Total { get; set; } } }
Design preview
Set Editable when users should be able to move elements, edit properties, add pages or bands, connect data-source metadata, and switch between design and preview. Without it, the report opens as a viewer.
The designer does not maintain a separate visual-only template. Its commands update the current <ReportDefinition>, and preview renders the updated definition. Bind Definition when the application needs to observe those changes.
Persistence
The report definition is the long-lived document model. Use @bind-Definition to keep it in application state, and handle SaveRequested and LoadRequested when the default toolbar should integrate with browser storage, a database, or an application service.
Serialize definitions with ReportJsonSerializer. Runtime data objects are intentionally not serialized, so they must be supplied again after loading.
Bind the generated definition and respond to persistence requests from application code.
<Report Data="" @bind-Definition="" SaveRequested="" LoadRequested="" Editable PreviewFormats="ReportPreviewFormat.Html | ReportPreviewFormat.Pdf"> <ReportViewer PreviewFormat="ReportPreviewFormat.Html | ReportPreviewFormat.Pdf" DefaultPreviewFormat="ReportPreviewFormat.Html" /> <ReportDataSources> <ReportObjectDataSource Name="Invoice" Data="" /> </ReportDataSources> <ReportPage Name="Invoice"> <ReportHeader Name="Stateful report header" Height="72"> <ReportText Text="Persistent report definition" X="30" Y="18" Width="270" Height="24" FontSize="18" Bold FontColor="@ReportColors.Blue" /> <ReportText Text="Move elements, save the definition as JSON, and load it again from the toolbar." X="30" Y="45" Width="450" Height="18" /> </ReportHeader> <ReportDetail Name="Invoice lines" Height="30" DataSource="Invoice.Lines"> <ReportField Field="Description" X="30" Y="6" Width="270" Height="18" /> <ReportField Field="Total" Format="@ReportFormats.Currency()" X="420" Y="6" Width="90" Height="18" /> </ReportDetail> </ReportPage> </Report>
@code { private ReportDefinition definition; private string reportJson; private readonly InvoiceReportModel invoice = new() { Lines = [ new() { Description = "Implementation workshop", Total = 640.50m }, new() { Description = "Reporting module license", Total = 500.00m }, ], }; private Task SaveReport( ReportDefinition definition ) { reportJson = ReportJsonSerializer.Serialize( definition ); return Task.CompletedTask; } private Task<ReportDefinition> LoadReport() { ReportDefinition savedDefinition = string.IsNullOrWhiteSpace( reportJson ) ? null : ReportJsonSerializer.Deserialize( reportJson ); return Task.FromResult( savedDefinition ); } private sealed class InvoiceReportModel { public List<InvoiceLineModel> Lines { get; set; } = []; } private sealed class InvoiceLineModel { public string Description { get; set; } public decimal Total { get; set; } } }
Programmatic reports
Declarative components are optional. Advanced scenarios can construct a <ReportDefinition> directly, retrieve it from a service or database, and pass it to <Report>.
Use ReportDefinitionMode.UseDefinitionOnly when the supplied definition is the complete source of truth. Use ReportDefinitionMode.AlwaysUseDeclarative when Razor should remain authoritative, or keep the default ReportDefinitionMode.SeedWhenEmpty when Razor provides only the initial template.
Build the same page, band, and element model directly in C# and render it without declarative report children.
<Report Definition="" DefinitionMode="ReportDefinitionMode.UseDefinitionOnly" ShowToolbar="false" />
@code { private readonly ReportDefinition definition = new() { Name = "Programmatic report", Pages = [ new() { Name = "Summary", Bands = [ new() { Name = "Summary header", Type = ReportBandType.ReportHeader, Height = 90, Elements = [ new ReportTextElementDefinition { Name = "Title", Text = "Created from a ReportDefinition", X = 30, Y = 18, Width = 360, Height = 27, Font = new() { Size = 20, Bold = true, Color = ReportColors.Blue, }, }, new ReportTextElementDefinition { Name = "Description", Text = "No declarative report page or band components are required.", X = 30, Y = 51, Width = 420, Height = 18, }, ], }, ], }, ], }; }
Imperative control
Keep a component reference when report operations are initiated outside the built-in toolbar. GetDefinition returns a copy of the persistent definition, while LoadDefinition replaces it. GetState and LoadState additionally capture transient designer state such as mode, active page, selection, and clipboard.
Commands can also be invoked through ExecuteCommand. Use CanExecuteCommand and IsCommandActive when building application controls that mirror report toolbar behavior.
Continue learning
- Learn layout for pages, bands, measurements, panels, lines, rectangles, and layout tables.
- Explore data sources for object models, nested fields, collections, DataSet, DataTable, and CSV.
- Add expressions, formula fields, aggregates, and running totals.
- Configure the designer, toolbar, definition persistence, and interactive state.
- Configure HTML and PDF preview and export.
- Add application-specific toolbox items and renderers with Reporting plugins.
- Consult the API reference for the complete public surface.
API
See the documentation below for a complete reference to all of the props and classes available to the components mentioned here.