Skip to main content
A newer version of this page is available. .

Create a Blazor Reporting Application

  • 7 minutes to read

This tutorial describes how to create a sample Blazor application that contains the Document Viewer and Report Designer controls.

View Example: Reporting Components for Blazor - Getting Started

Prerequisites

  1. Install the .NET Core 3.1 SDK.
  2. Install Visual Studio 2019 with the ASP.NET and web development workload.

Create a New Blazor Application

Perform the following steps to create a sample Blazor application in Visual Studio:

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

    Create a new project

    Click Next.

  2. Specify the project name and location.

    blazor-configure-new-project

    Click Create.

  3. Specify the framework version.

    blazor-create-new-blazor-app

    Click Create.

Install NuGet Packages

  1. Go to nuget.devexpress.com, log in as a registered DevExpress customer and click Obtain Feed URL.

    blazor-nuget-feed

    Copy the feed URL to clipboard.

  2. Select Tools -> NuGet Package Manager -> Package Manager Settings to invoke the Options dialog.

  3. Navigate to NuGet Package Manager -> Package Sources. Click the plus sign at the top right corner to add a new NuGet package source. Use the following package settings:

    Name Source
    DevExpress https://nuget.devexpress.com/{your feed authorization key}/api

    blazor-nuget-package-source

    Click OK.

  4. Select Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution…. Switch to the Browse tab, select the created DevExpress package source and find the DevExpress.Blazor.Reporting NuGet package.

    To install the latest Release package version, clear the Include prereleases checkbox. To test a Beta version of the DevExpress.Blazor.Reporting NuGet package, enable the Include prerelease option.

    blazor-nuget-package-reporting

    Click Install.

Add Dependencies

  1. Modify the Startup.cs file. Call the AddDevExpressBlazorReporting method that sets up the DevExpress control services and the UseDevExpressBlazorReporting method that registers DevExpress middleware components:

    using DevExpress.AspNetCore;
    using DevExpress.Blazor.Reporting;
    // ...
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDevExpressBlazorReporting();
        // ...
    }
    
    using DevExpress.AspNetCore;
    using DevExpress.Blazor.Reporting;
    // ...
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseDevExpressBlazorReporting();
        // ...
    }        
    
  2. Modify the _Imports.razor file to register DevExpress.Blazor.Reporting namespace:

    @using DevExpress.Blazor.Reporting        
    

Add the Report Storage

  1. Implement the ReportStorageWebExtension descendant that saves and loads reports. The code below is a sample storage that uses the file system to store reports:

    using System;
    using Microsoft.AspNetCore.Hosting;
    using System.Collections.Generic;
    using System.IO;
    using System.Linq;
    using DevExpress.XtraReports.UI;
    
    namespace BlazorApp1
    {
        public class ReportStorageWebExtension1 : DevExpress.XtraReports.Web.Extensions.ReportStorageWebExtension
        {
            readonly string ReportDirectory;
            const string FileExtension = ".repx";
            public ReportStorageWebExtension1(IWebHostEnvironment env)
            {
                ReportDirectory = Path.Combine(env.ContentRootPath, "Reports");
                if (!Directory.Exists(ReportDirectory))
                {
                    Directory.CreateDirectory(ReportDirectory);
                }
            }
    
            private bool IsWithinReportsFolder(string url, string folder)
            {
                var rootDirectory = new DirectoryInfo(folder);
                var fileInfo = new FileInfo(Path.Combine(folder, url));
                return fileInfo.Directory.FullName.ToLower().StartsWith(rootDirectory.FullName.ToLower());
            }
    
            public override bool CanSetData(string url)
            {
                // Determines whether it is possible to store a report by a given URL. 
                // For instance, make the CanSetData method return false for reports that should be read-only in your storage. 
                // This method is called only for valid URLs (for example, if the IsValidUrl method returns true) before the SetData method is called.
    
                return true;
            }
    
            public override bool IsValidUrl(string url)
            {
                // Determines whether the URL passed to the current Report Storage is valid. 
                // For instance, implement your own logic to prohibit URLs that contain white spaces or other special characters. 
                // This method is called before the CanSetData and GetData methods.
    
                return Path.GetFileName(url) == url;
            }
    
            public override byte[] GetData(string url)
            {
                // Returns report layout data stored in a Report Storage using the specified URL. 
                // This method is called only for valid URLs after the IsValidUrl method is called.
                try
                {
                    if (Directory.EnumerateFiles(ReportDirectory).Select(Path.GetFileNameWithoutExtension).Contains(url))
                    {
                        return File.ReadAllBytes(Path.Combine(ReportDirectory, url + FileExtension));
                    }
                }
                catch (Exception ex)
                {
                    throw new DevExpress.XtraReports.Web.ClientControls.FaultException("Could not get report data.", ex);
                }
                throw new DevExpress.XtraReports.Web.ClientControls.FaultException(string.Format("Could not find report '{0}'.", url));
            }
    
            public override Dictionary<string, string> GetUrls()
            {
                // Returns a dictionary of the existing report URLs and display names. 
                // This method is called when running the Report Designer, 
                // before the Open Report and Save Report dialogs are shown and after a new report is saved to storage.
    
                return Directory.GetFiles(ReportDirectory, "*" + FileExtension)
                                        .Select(Path.GetFileNameWithoutExtension)
                                        .ToDictionary<string, string>(x => x);
            }
    
            public override void SetData(XtraReport report, string url)
            {
                // Stores the specified report to a Report Storage using the specified URL. 
                // This method is called only after the IsValidUrl and CanSetData methods are called.
                if (!IsWithinReportsFolder(url, ReportDirectory))
                    throw new DevExpress.XtraReports.Web.ClientControls.FaultException("Invalid report name.");
                report.SaveLayoutToXml(Path.Combine(ReportDirectory, url + FileExtension));
            }
    
            public override string SetNewData(XtraReport report, string defaultUrl)
            {
                // Stores the specified report using a new URL. 
                // The IsValidUrl and CanSetData methods are never called before this method. 
                // You can validate and correct the specified URL directly in the SetNewData method implementation 
                // and return the resulting URL used to save a report in your storage.
                SetData(report, defaultUrl);
                return defaultUrl;
            }
        }
    }
    
  1. Modify the Startup.cs file and add the code that registers the ReportStorageWebExtension1:

    using DevExpress.XtraReports.Web.Extensions;
    // ...
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDevExpressBlazorReporting();
        // Register the storage after the AddDevExpressBlazorReporting method call.
        services.AddScoped<ReportStorageWebExtension, ReportStorageWebExtension1>();
        // ...
    
    }
    

    Important

    Register the ReportStorageWebExtension after the AddDevExpressBlazorReporting method.

  2. Add a new Reports folder to a project.

    Tip

    The name Reports is specified in the ReportStorageWebExtension implementation.

Create a Sample Report

Note

To perform this step, you should install DevExpress Reporting on your machine. Refer to the following topic for more information: Install DevExpress .NET Products.

  1. Select Project -> Add New Item… to invoke the Add New Item dialog. Navigate to the Reporting node and select the DevExpress v.20.2 Report item template.

    Name the report HelloWorld.vsrepx and click Add.

  2. Select Blank In the invoked Report Wizard page and click Finish. The newly created report is loaded in the Visual Studio Report Designer.

  3. Modify a newly created report in Visual Studio Report Designer. Add a label and type in the Hello, World! text:

  4. Click the report’s smart tag (a button in the upper left corner of the Designer window) and select Save…:

    save-report-defintion-visual-studio-design-time

    In the invoked Save As dialog, specify the Reports project folder and the HelloWorld.repx file name.

Create Routing to Controller Actions

Modify the Startup.cs file. Add the following code to map requests to controller actions:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // ...
        app.UseEndpoints(endpoints =>
            {
            endpoints.MapControllers();
            // ...                
            });
    }

Add Document Viewer to a Page

Create a new Razor component (select Project -> Add New Item.. -> Razor Component). Save it as the DocumentVIewer.razor file, and open and overwrite its content with the following:

@page "/documentviewer"

<DxDocumentViewer ReportName="HelloWorld" Height="1000px" Width="100%">
        <DxDocumentViewerTabPanelSettings Width="340" />
</DxDocumentViewer>

The DxDocumentViewer component invokes the default WebDocumentViewerController that processes requests from the Document Viewer and loads the HelloWorld report to create a document.

Add Report Designer to a Page

Create a new Razor component (select Project -> Add New Item.. -> Razor Component). Save it as the ReportDesigner.razor file, and open and overwrite its content with the following:

@page "/reportdesigner"

    <DxReportDesigner ReportName="HelloWorld" Height="1000px" Width="100%" AllowMDI="true">     
        <DxReportDesignerWizardSettings UseFullscreenWizard="true" />
    </DxReportDesigner>

The DxReportDesigner loads the HelloWorld report.

Note

If you implement a custom report that inherits from XtraReport and want to open it in the End-User Report Designer, add a constructor without parameters to this report.

Modify the NavMenu.razor file to include links to the newly created pages:

<div class="@NavMenuCssClass" @onclick="ToggleNavMenu">
    <ul class="nav flex-column">
    @* ... *@
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="documentviewer">
                <span class="oi oi-document" aria-hidden="true"></span>
                 Document Viewer
            </NavLink>
        </li>
        <li class="nav-item px-3">
            <NavLink class="nav-link" href="reportdesigner">
                <span class="oi oi-wrench" aria-hidden="true"></span>
                 Report Designer
            </NavLink>
        </li>
    </ul>
</div>

Run the Project

Run the project. The Document Viewer and Report Designer components load the HelloWorld.repx report: