Example T1272867
Visible to All Users

Reporting for React - Customize a Web Report Designer in a React App (Next.js)

This example incorporates the Web Report Designer into a client-side app built with React. The example consists of two parts:

This project contains code snippets used for client-side customization and reflected in our online help topics. Each code snippet is enclosed in a page.tsx file in a separate folder. After running the project, navigate the following locations to see the result:

Location Description
/client-side-api Performs some client-side actions.
/save-modified-report Saves a modified report in the currently active tab. Saves all modified reports.
/manage-properties-panel Hides or disables individual editors or sections in the Properties panel for the specified control type.
/report-designer-api Calls the Report Designer's RunWizard method to invoke New Report Wizard.
/open-report Adds a button that loads a specified report.
/save-report Adds a button that saves the current report.

Quick Start

Server

In the ServerSideApp/ServerSideApp folder, run the following command:

Code
dotnet run

The server starts at http://localhost:5000. To debug the server, run the application in Visual Studio.

Client

In the react-report-designer folder, run the following commands:

Code
npm install npm run dev

Open http://localhost:3000/ in your browser to view the result. The application displays the Web Report Designer.

Report Designer in JavaScript with React

Files to Review

Documentation

More Examples

Does this example address your development requirements/objectives?

(you will be redirected to DevExpress.com to submit your response)

Example Code

react-report-designer/app/page.tsx
Code
'use client'; import dynamic from 'next/dynamic' import RequestOptions from 'devexpress-reporting-react/dx-report-designer/options/RequestOptions'; const ReportDesigner = dynamic(() => import('devexpress-reporting-react/dx-report-designer'), {ssr: false}) function App() { return ( <ReportDesigner reportUrl="TestReport"> <RequestOptions host="http://localhost:5000/" getDesignerModelAction="DXXRD/GetDesignerModel" /> </ReportDesigner> ) } export default App
ServerSideApp/ServerSideApp/Program.cs
C#
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using DevExpress.AspNetCore; using DevExpress.AspNetCore.Reporting; using DevExpress.Security.Resources; using DevExpress.XtraReports.Web.Extensions; using Microsoft.AspNetCore.Builder; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using ServerSideApp.Services; using ServerSideApp.Data; var builder = WebApplication.CreateBuilder(args); builder.Services.AddDevExpressControls(); builder.Services.AddScoped<ReportStorageWebExtension, CustomReportStorageWebExtension>(); builder.Services.AddMvc(); builder.Services.ConfigureReportingServices(configurator => { if(builder.Environment.IsDevelopment()) { configurator.UseDevelopmentMode(); } configurator.ConfigureReportDesigner(designerConfigurator => { }); configurator.ConfigureWebDocumentViewer(viewerConfigurator => { viewerConfigurator.UseCachedReportSourceBuilder(); viewerConfigurator.RegisterConnectionProviderFactory<CustomSqlDataConnectionProviderFactory>(); }); }); builder.Services.AddDbContext<ReportDbContext>(options => options.UseSqlite(builder.Configuration.GetConnectionString("ReportsDataConnectionString"))); builder.Services.AddCors(options => { options.AddPolicy("AllowCorsPolicy", builder => { // Allow all ports on local host. builder.SetIsOriginAllowed(origin => new Uri(origin).Host == "localhost"); builder.AllowAnyHeader(); builder.AllowAnyMethod(); }); }); var app = builder.Build(); using(var scope = app.Services.CreateScope()) { var services = scope.ServiceProvider; services.GetService<ReportDbContext>().InitializeDatabase(); } var contentDirectoryAllowRule = DirectoryAccessRule.Allow(new DirectoryInfo(Path.Combine(builder.Environment.ContentRootPath, "Content")).FullName); AccessSettings.ReportingSpecificResources.TrySetRules(contentDirectoryAllowRule, UrlAccessRule.Allow()); DevExpress.XtraReports.Configuration.Settings.Default.UserDesignerOptions.DataBindingMode = DevExpress.XtraReports.UI.DataBindingMode.Expressions; app.UseDevExpressControls(); System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12; if(app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); // 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.UseRouting(); app.UseCors("AllowCorsPolicy"); app.UseAuthorization(); app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
ServerSideApp/ServerSideApp/Controllers/ReportingControllers.cs
C#
using System.Collections.Generic; using System.Threading.Tasks; using DevExpress.AspNetCore.Reporting.QueryBuilder; using DevExpress.AspNetCore.Reporting.QueryBuilder.Native.Services; using DevExpress.AspNetCore.Reporting.ReportDesigner; using DevExpress.AspNetCore.Reporting.ReportDesigner.Native.Services; using DevExpress.AspNetCore.Reporting.WebDocumentViewer; using DevExpress.AspNetCore.Reporting.WebDocumentViewer.Native.Services; using DevExpress.DataAccess.Sql; using DevExpress.XtraReports.Web.ReportDesigner.Services; using Microsoft.AspNetCore.Mvc; namespace ServerSideApp.Controllers { public class CustomReportDesignerController : ReportDesignerController { public CustomReportDesignerController(IReportDesignerMvcControllerService controllerService) : base(controllerService) { } [HttpPost("[action]")] public async Task<IActionResult> GetDesignerModel( [FromForm] string reportName, [FromServices] IReportDesignerModelBuilder reportDesignerModelBuilder) { var dataSources = new Dictionary<string, object>(); var ds = new SqlDataSource("NWindConnectionString"); // Create a SQL query to access the Products data table. SelectQuery query = SelectQueryFluentBuilder.AddTable("Products").SelectAllColumnsFromTable().Build("Products"); ds.Queries.Add(query); ds.RebuildResultSchema(); dataSources.Add("Northwind", ds); reportName = string.IsNullOrEmpty(reportName) ? "TestReport" : reportName; var designerModel = await reportDesignerModelBuilder .Report(reportName) .DataSources(dataSources) .BuildModelAsync(); return DesignerModel(designerModel); } } public class CustomQueryBuilderController : QueryBuilderController { public CustomQueryBuilderController(IQueryBuilderMvcControllerService controllerService) : base(controllerService) { } } public class CustomWebDocumentViewerController : WebDocumentViewerController { public CustomWebDocumentViewerController(IWebDocumentViewerMvcControllerService controllerService) : base(controllerService) { } } }

Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.