Skip to main content
All docs
V24.1

Add a Document Viewer and Report Designer (JavaScript-Based) to a Project (Blazor WebAssembly Standalone Application Created with a Visual Studio Template)

  • 8 minutes to read

Tip

To create a Blazor Reporting application, use preconfigured DevExpress templates to create an application with minimal effort and maximum efficiency. For more information, review the following help topics:

Prerequisites

  1. .NET 6.0 or later SDK.
  2. Visual Studio 2022 with the ASP.NET and web development workload.

Create a New Project

This section describes how to create a new Blazor project. If you want to add Report Designer and Document Viewer to an existing application, go to Step 2.

  1. Click Create a new project on Visual Studio’s start page, select the Blazor WebAssembly Standalone App template, and click Next.

  2. Specify the project name and location, and click Next.

  3. Specify additional options, and click Create.

For more information on available Blazor templates, refer to the following topic: Tooling for ASP.NET Core Blazor.

Obtain Your NuGet Feed Credentials

You need to obtain your personal NuGet feed credentials to access required NuGet packages from your project. You can use the NuGet feed URL or feed authorization key to manage DevExpress packages.

  1. Make sure your DevExpress account has access to Blazor Reporting Controls. This products are included in the Universal, DXperience, ASP.NET, and Reporting subscriptions. Refer to the following page for more information: DevExpress Subscriptions.

  2. Use your DevExpress credentials to log into nuget.devexpress.com.

  3. Obtain your NuGet feed credentials and copy them to the clipboard.

    You can find the same URL on the Download Manager page.

Create DevExpress NuGet Source

  1. In Visual Studio, select ToolsNuGet Package ManagerPackage Manager Settings.

    Getting Started - Package Manager Settings

  2. Navigate to NuGet Package ManagerPackage Sources. Click the plus button at the top right corner to add a new NuGet package source. Use the following package settings:

    • Name: DevExpress

    • Source: DevExpress NuGet Gallery (https://nuget.devexpress.com/api/v3/index.json) if you use the feed key to authenticate. Otherwise, use the NuGet Feed URL (https://nuget.devexpress.com/{your feed authorization key}/api/v3/index.json).

    Click OK.

    Make sure the nuget.org package source is also enabled.

    Getting Started - NuGet Feed API

If you registered the DevExpress NuGet feed with an authorization key, the login form is displayed when you invoke the NuGet Package Manager window for the first time. Enter your credentials as follows:

Install NuGet Packages

Install NuGet packages required for DevExpress Reporting:

  1. Select ToolsNuGet Package ManagerManage NuGet Packages for Solution.

  2. Once the dialog appears on screen, open the Browse tab, select the All as a package source, and install the following NuGet packages:

    • DevExpress.Drawing.Skia
    • DevExpress.Blazor.Reporting.JSBasedControls
    • SkiaSharp.Views.Blazor
    • SkiaSharp.NativeAssets.WebAssembly
    • HarfBuzzSharp.NativeAssets.WebAssembly

    Note

    JSON data source uses the System.Text.Json processing library. Set the DevExpress.DataAccess.Native.Json.JsonLoaderHelper.ProcessingLibrary property to NewtonsoftJson to use the Newtonsoft.Json library instead. Then, install the Newtonsoft.Json NuGet package.

    Getting Started - Install Package

  3. In the Solution Explorer, right-click the project and select Edit Project File. Add the following native dependency to the application project file:

    <ItemGroup>
        <NativeFileReference Include="$(HarfBuzzSharpStaticLibraryPath)\2.0.23\*.a" />
    </ItemGroup>
    
  4. Build the project.

Register DevExpress Resources

  1. In the _Imports.razor file, register DevExpress.Blazor and DevExpress.Blazor.Reporting namespaces:

    @using DevExpress.Blazor.Reporting
    @using DevExpress.Blazor
    
  2. In the Program.cs file, register services required for Blazor Reporting. To do this, call the AddDevExpressBlazorReportingWebAssembly method:

    using BlazorApp1;
    using Microsoft.AspNetCore.Components.Web;
    using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
    using DevExpress.Blazor.Reporting;
    
    var builder = WebAssemblyHostBuilder.CreateDefault(args);
    builder.RootComponents.Add<App>("#app");
    builder.RootComponents.Add<HeadOutlet>("head::after");
    
    builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
    
    builder.Services.AddDevExpressBlazorReportingWebAssembly(configure => {
        configure.UseDevelopmentMode();
    });
    
    await builder.Build().RunAsync();
    

Add a Document Viewer to a Page

Create a new razor file (DocumentViewer.razor) in the Pages folder. Use the code below to generate a page with a Document Viewer component.

@page "/documentviewer"

<DxDocumentViewer ReportName="TestReport">
</DxDocumentViewer>

Add a Report Designer to a Page

Create a new razor file (ReportDesigner.razor) in the Pages folder. Use the code below to generate a page with a Report Designer component.

@page "/reportdesigner"

<DxReportDesigner ReportName="TestReport">
</DxReportDesigner>

Add navigation links to the NavMenu.razor page:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="documentviewer">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Document Viewer
    </NavLink>
</div>
<div class="nav-item px-3">
    <NavLink class="nav-link" href="reportdesigner">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Report Designer
    </NavLink>
</div>

Add Code to Load Fonts

Before the application can run in a browser, register fonts to ensure that the Skia library can use them to draw report content. This example implements a custom service that loads fonts: FontLoader.

  1. Create the Services folder in the project. Create a new class file FontLoader.cs with the following content:

    using DevExpress.Drawing;
    
        public static class FontLoader {
            public async static Task LoadFonts(HttpClient httpClient, List<string> fontNames) {
                foreach(var fontName in fontNames) {
                    var fontBytes = await httpClient.GetByteArrayAsync($"fonts/{fontName}");
                    DXFontRepository.Instance.AddFont(fontBytes);
                }
            }
        }
    
  2. Add a LoadFonts method call to the MainLayout.razor page:

    // ...
    
    @code {
        [Inject] HttpClient Http { get; set; }
        List<string> RequiredFonts = new() {
            "arial.ttf", "arialbd.ttf"
        };
    
        protected async override Task OnInitializedAsync() {
            await FontLoader.LoadFonts(Http, RequiredFonts);
            await base.OnInitializedAsync();
        }
    }
    
  3. Copy the necessary font files (arial.ttf, arialbd.ttf) to the wwwroot/fonts folder.

Add Code to Load Reports

Reporting components require a service that translates names to report instances. This example implements a custom service with the IReportProviderAsync interface to perform this task.

  1. Add the CustomReportProvider.cs class file to the Services folder. Copy and paste the following content into the file:

    using DevExpress.XtraReports.Services;
    using DevExpress.XtraReports.UI;
    
    public class CustomReportProvider : IReportProviderAsync {
        private readonly HttpClient _httpClient;
        public CustomReportProvider(HttpClient httpClient) {
            _httpClient = httpClient;
        }
        public Task<XtraReport> GetReportAsync(string id, ReportProviderContext context) {
            return ReportsFactory.GetReport(id, _httpClient);
        }
    }
    
  2. The ReportsFactory class loads a report instance from a file. Add a ReportsFactory.cs class with the following code to your project:

    using DevExpress.XtraReports.UI;
    
    public static class ReportsFactory {
    
    
        public static readonly Dictionary<string, XtraReport> Reports = new()
        {
            ["EmptyReport"] = new XtraReport()
        };
    
        public async static Task<XtraReport> GetReport(string reportName, HttpClient _httpClient) {
                var reportBytes = await _httpClient.GetByteArrayAsync($"reports/{reportName}.repx");
                MemoryStream reportStream = new MemoryStream(reportBytes);
                return XtraReport.FromXmlStream(reportStream);
        }
    }
    
  3. Register the CustomReportProvider service at application startup:

    builder.Services.AddDevExpressBlazorReportingWebAssembly(configure => {
        configure.UseDevelopmentMode();
    });
    // ...
    builder.Services.AddScoped<IReportProviderAsync, CustomReportProvider>();
    // ...
    await builder.Build().RunAsync();
    

Create a Report

Use Microsoft Visual Studio, Visual Studio Code, or Report Designer on any supported platform to create a simple report bound to the JSON data source and save it to the TestReport.repx file.

Use the following JSON data URI:

https://raw.githubusercontent.com/DevExpress-Examples/DataSources/master/JSON/customers.json

When prompted for the JSON connection name, type JsonConnection1.

For more information, review the following help topics:

The following procedure shows you how to create a report in the Microsoft Visual Studio environment. To ensure that all the necessary templates are available in Visual Studio, DevExpress Reporting v24.1 must be installed before proceeding with this section.

  1. Press Ctrl+Shift+A or select PROJECT | Add New Item… in the main menu.
  2. Select the DevExpress Report item and proceed to the Report Wizard to create a TestReport report bound to the Employees data source:

    Show Visual Guide

    Blazor — Add a New Report
    Blazor Report Wizard — Select Type Blazor Report Wizard — Select Data Source Type Blazor Report Wizard — Select JSON URI Blazor Report Wizard — Select JSON Auth Blazor Report Wizard — JSON Connection String Name Blazor Report Wizard — Select JSON Root Blazor Report Wizard — Choose Fields Blazor Report Wizard — Select Group Field

  3. Upon completion, the wizard generates a TestReport.cs file and adds it to the project. Visual Studio Report Designer opens the newly created report.

    Newly Created Report

  4. Save the report to the TestReport.repx file:

    Save Report to File

  5. Copy the TestReport.repx file to the wwwroot/reports folder in your Blazor Webassembly project.

Add JSON Connection Provider

The connection string is not stored in the .repx file for security reasons. Only the connection name is saved. At runtime, the Document Viewer and Report Designer components query the CustomDataSourceWizardJsonDataConnectionStorage service to retrieve the connection by name. Do the following to be able to use JSON connections in your application:

  1. Add a service that implements the IDataSourceWizardJsonConnectionStorage interface. For this, add a CustomDataSourceWizardJsonDataConnectionStorage.cs class with the following code to your project:

    using DevExpress.DataAccess.Json;
    using DevExpress.DataAccess.Web;
    using DevExpress.DataAccess.Wizard.Services;
    
    public class CustomDataSourceWizardJsonDataConnectionStorage : IDataSourceWizardJsonConnectionStorage {
        public static JsonDataConnection GetDefaultConnection() {
            var uriJsonSource = new UriJsonSource()
            {
                Uri = new Uri(@"https://raw.githubusercontent.com/DevExpress-Examples/DataSources/master/JSON/customers.json"),
            };
            return new JsonDataConnection(uriJsonSource) { StoreConnectionNameOnly = true, Name = "JsonConnection1" };
        }
        public static List<JsonDataConnection> GetConnections() {
            var connections = new List<JsonDataConnection> {
                    GetDefaultConnection()
                };
            return connections;
        }
    
        bool IJsonConnectionStorageService.CanSaveConnection => false;
        bool IJsonConnectionStorageService.ContainsConnection(string connectionName) {
            return GetConnections().Any(x => x.Name == connectionName);
        }
    
        IEnumerable<JsonDataConnection> IJsonConnectionStorageService.GetConnections() {
            return GetConnections();
        }
    
        JsonDataConnection IJsonDataConnectionProviderService.GetJsonDataConnection(string name) {
            var connection = GetConnections().FirstOrDefault(x => x.Name == name);
            if (connection == null)
                throw new InvalidOperationException();
            return connection;
        }
    
        void IJsonConnectionStorageService.SaveConnection(string connectionName, JsonDataConnection connection, bool saveCredentials) { }
    }
    
  2. Add a service that implements the IJsonDataConnectionProviderFactory interface:

    using DevExpress.DataAccess.Json;
    using DevExpress.DataAccess.Web;
    
    public class CustomJsonDataConnectionProviderFactory : IJsonDataConnectionProviderFactory {
        public IJsonDataConnectionProviderService Create() {
            return new WebDocumentViewerJsonDataConnectionProvider(CustomDataSourceWizardJsonDataConnectionStorage.GetConnections());
        }
    }
    
    public class WebDocumentViewerJsonDataConnectionProvider : IJsonDataConnectionProviderService {
        readonly List<JsonDataConnection> jsonDataConnections;
        public WebDocumentViewerJsonDataConnectionProvider(List<JsonDataConnection> jsonDataConnections) {
            this.jsonDataConnections = jsonDataConnections;
        }
        public JsonDataConnection GetJsonDataConnection(string name) {
            var connection = jsonDataConnections.FirstOrDefault(x => x.Name == name);
            if (connection == null)
                throw new InvalidOperationException();
            return connection;
        }
    }
    
  3. Register services at application startup:

    builder.Services.AddDevExpressBlazorReportingWebAssembly(configure => {
        configure.UseDevelopmentMode();
    });
    // ...
    builder.Services.AddScoped<IReportProviderAsync, CustomReportProvider>();
    builder.Services.AddScoped<IDataSourceWizardJsonConnectionStorage, CustomDataSourceWizardJsonDataConnectionStorage>();
    builder.Services.AddScoped<IJsonDataConnectionProviderFactory, CustomJsonDataConnectionProviderFactory>();
    // ...
    await builder.Build().RunAsync();
    

Run the Project

Run the project and see the result. The Document Viewer displays a tabular report with data from the Employees data source:

Blazor WASM Standalone Document Viewer Result

The Report Designer displays a tabular report layout bound to the Employees data source:

Blazor WASM Standalone Report Designer Result

Troubleshooting

The following article lists common issues that can occur in a Web Reporting application and describes solutions: Troubleshooting

For information on how to identify the cause of an issue, refer to the following topic: Reporting Application Diagnostics.