Example T1148046
Visible to All Users

Reporting for Web (ASP.NET MVC, ASP.NET Core and Angular) - How to Customize the DevExpress Report Wizard Customization and Hide Data Source Actions within our Report Designer

For more information on the capabilities outlined in this example (or if you are new to DevExpress Reports), please review the following blog post for important background information: DevExpress Web Report Designer — Custom Report Templates within the Report Wizard, Data Source UI Enhancements (v22.2)

DevExpress Reports ships with an easy-to-use/flexible Report Wizard. You can use the Report Wizard to generate reports yourself or make it available to end users (minimize development costs/maximize productivity). This example will show you how to add a custom report template to the Report Wizard and make modifications to a wizard-generated report. Our sample project includes separate projects for ASP.NET MVC, ASP.NET Core, and Angular client application with an ASP.NET Core backend.

To customize the DevExpress Report Wizard and add new wizard report templates (this example adds Instant Report and Custom Label Report templates to our default template list), you must:

  • Implement a descendant of the ReportWizardCustomizationService class and register it as a service.
  • Handle the Report Designer CustomizeWizard event to register a custom wizard page. (the reportWizardCustomization.js file contains JavaScript code required for registration).

By customizing our wizard’s default template set, you can address a variety of usage scenarios. To see what’s possible, execute the app, invoke the Report Wizard, and select a custom template included with this demo (Instant Report and Custom Label Report).

Report Wizard with Custom Template

To hide data source action from our Report Designer’s Field List panel, you must:

Note
To help illustrate available options, the Report Designer was configured to hide data source actions. As such, users cannot add, modify, or delete the data source used for this report.

Report Designer Field List with Hidden Actions

Once you generate a wizard-based report, switch to the Field List panel. Notice that data source actions have been hidden (via ReportDesignerDataSourceSettings).

Files to Review

Service that Customizes the Report Wizard

Service Registration

Custom Wizard Page for the Custom Label Report

Report Designer Data Source Settings

Documentation

More Examples

Does this example address your development requirements/objectives?

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

Example Code

Mvc/ReportWizardCustomizationServiceMvcExample/Services/InstantReportWizardCustomizationService.cs
C#
using DevExpress.XtraReports.UI; using DevExpress.XtraReports.Web.ReportDesigner.DataContracts; using DevExpress.XtraReports.Web.ReportDesigner.Services; using DevExpress.XtraReports.Wizards; using ReportWizardCustomizationServiceMvcExample.PredefinedReports; using System; using System.Linq; using System.Threading.Tasks; public class InstantReportWizardCustomizationService : ReportWizardCustomizationService { public enum CustomReportType { CustomLabelReport, InstantReport } public override XtraReport TryCreateCustomReport(XtraReportModel model, object dataSource, string dataMember, CustomWizardData customWizardData, XtraReport report) { if (Enum.TryParse(customWizardData.ReportTemplateID, out CustomReportType customReportType)) { if (customReportType == CustomReportType.InstantReport) { return new InstantReport() { Name = customWizardData.ReportTemplateID, DisplayName = customWizardData.ReportTemplateID }; } else if (customReportType == CustomReportType.CustomLabelReport) { var labelReport = new LabelReport(); labelReport.ApplyCustomData(customWizardData.Data); return labelReport; } } return base.TryCreateCustomReport(model, dataSource, dataMember, customWizardData, report); } public override Task<XtraReport> TryCreateCustomReportAsync(XtraReportModel model, object dataSource, string dataMember, CustomWizardData customWizardData, XtraReport report) { return Task.FromResult(TryCreateCustomReport(model, dataSource, dataMember, customWizardData, report)); } public override void CustomizeReportTypeList(ReportWizardTemplateCollection predefinedTypes) { predefinedTypes.Remove(predefinedTypes.Where(x => x.ID == nameof(ReportType.CrossTab)).First()); predefinedTypes.Add(new DevExpress.XtraReports.Web.ReportDesigner.DataContracts.ReportWizardTemplate() { CanInstantlyFinish = true, ID = nameof(CustomReportType.InstantReport), Text = "Instant Report", ImageTemplateName = "instant-report" }); predefinedTypes.Add(new DevExpress.XtraReports.Web.ReportDesigner.DataContracts.ReportWizardTemplate() { CanInstantlyFinish = true, ID = nameof(CustomReportType.InstantReport), Text = "Instant Report", ImageClassName = "instant-report-image" }); predefinedTypes.Add(new DevExpress.XtraReports.Web.ReportDesigner.DataContracts.ReportWizardTemplate() { ID = nameof(CustomReportType.CustomLabelReport), Text = "Custom Label Report", ImageTemplateName = "dxrd-svg-wizard-LabelReport" }); } public override Task CustomizeReportTypeListAsync(ReportWizardTemplateCollection predefinedTypes) { CustomizeReportTypeList(predefinedTypes); return Task.CompletedTask; } public override void CustomizeReportOnFinish(XtraReport report) { if (report.Bands.GetBandByType(typeof(ReportHeaderBand)) == null) report.Bands.Add(new ReportHeaderBand() { Controls = { new XRLabel() { Text = string.Format("Instant Report {0:MMM dd}", System.DateTime.Today), SizeF= new System.Drawing.SizeF(650F, 100F), Font = new DevExpress.Drawing.DXFont("Arial", 24) } } }); ; ; } public override Task CustomizeReportOnFinishAsync(XtraReport report) { CustomizeReportOnFinish(report); return Task.CompletedTask; } }
Mvc/ReportWizardCustomizationServiceMvcExample/Global.asax.cs
C#
using System; using System.Collections.Generic; using System.Linq; using System.IO; using System.Web; using System.Web.Http; using System.Web.Mvc; using System.Web.Routing; using DevExpress.Web.Mvc; using ReportWizardCustomizationServiceMvcExample.Services; using DevExpress.XtraReports.Web.ReportDesigner.Services; using DevExpress.XtraReports.Web.ReportDesigner; namespace ReportWizardCustomizationServiceMvcExample { // Note: For instructions on enabling IIS6 or IIS7 classic mode, // visit http://go.microsoft.com/?LinkId=9394801 public class MvcApplication : System.Web.HttpApplication { protected void Application_Start() { DevExpress.XtraReports.Configuration.Settings.Default.UserDesignerOptions.DataBindingMode = DevExpress.XtraReports.UI.DataBindingMode.Expressions; DevExpress.XtraReports.Web.WebDocumentViewer.Native.WebDocumentViewerBootstrapper.SessionState = System.Web.SessionState.SessionStateBehavior.Required; DevExpress.XtraReports.Web.QueryBuilder.Native.QueryBuilderBootstrapper.SessionState = System.Web.SessionState.SessionStateBehavior.Required; DevExpress.XtraReports.Web.ReportDesigner.Native.ReportDesignerBootstrapper.SessionState = System.Web.SessionState.SessionStateBehavior.Required; DevExpress.XtraReports.Web.Extensions.ReportStorageWebExtension.RegisterExtensionGlobal(new CustomReportStorageWebExtension(Server.MapPath("/Reports"))); DevExpress.XtraReports.Web.ReportDesigner.DefaultReportDesignerContainer.RegisterDataSourceWizardConnectionStringsProvider<CustomDataSourceWizardConnectionStringsProvider>(); DevExpress.XtraReports.Web.ReportDesigner.DefaultReportDesignerContainer.RegisterDataSourceWizardJsonConnectionStorage<CustomDataSourceWizardJsonDataConnectionStorage>(true); DevExpress.XtraReports.Web.WebDocumentViewer.DefaultWebDocumentViewerContainer.Register<DevExpress.DataAccess.Web.IJsonDataConnectionProviderFactory, CustomJsonDataConnectionProviderFactory>(); DefaultReportDesignerContainer.Register<ReportWizardCustomizationService, InstantReportWizardCustomizationService>(); DevExpress.XtraReports.Web.ReportDesigner.DefaultReportDesignerContainer.RegisterObjectDataSourceWizardTypeProvider<ObjectDataSourceWizardCustomTypeProvider>(); System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12; MVCxReportDesigner.StaticInitialize(); DevExpress.XtraReports.Web.ClientControls.LoggerService.Initialize((ex, message) => System.Diagnostics.Debug.WriteLine("[{0}]: Exception occurred. Message: '{1}'. Exception Details:\r\n{2}", DateTime.Now, message, ex)); AreaRegistration.RegisterAllAreas(); GlobalConfiguration.Configure(WebApiConfig.Register); FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); RouteConfig.RegisterRoutes(RouteTable.Routes); ModelBinders.Binders.DefaultBinder = new DevExpress.Web.Mvc.DevExpressEditorsBinder(); DevExpress.Web.ASPxWebControl.CallbackError += Application_Error; } protected void Application_Error(object sender, EventArgs e) { Exception exception = System.Web.HttpContext.Current.Server.GetLastError(); //TODO: Handle Exception } } }
AspNetCore/RWCSAspNetCoreExample/Startup.cs
C#
using System; using System.IO; using DevExpress.AspNetCore; using DevExpress.AspNetCore.Reporting; using DevExpress.Security.Resources; using DevExpress.XtraReports.Web.Extensions; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using ReportWizardCustomizationServiceAspNetCoreExample.Services; using ReportWizardCustomizationServiceAspNetCoreExample.Data; using DevExpress.XtraReports.Web.ReportDesigner.Services; namespace ReportWizardCustomizationServiceAspNetCoreExample { public class Startup { public Startup(IConfiguration configuration, IWebHostEnvironment hostingEnvironment) { Configuration = configuration; } public IConfiguration Configuration { get; } // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddDevExpressControls(); services.AddScoped<ReportStorageWebExtension, CustomReportStorageWebExtension>(); services .AddMvc() .AddNewtonsoftJson(); services.ConfigureReportingServices(configurator => { configurator.ConfigureReportDesigner(designerConfigurator => { designerConfigurator.RegisterDataSourceWizardConnectionStringsProvider<CustomSqlDataSourceWizardConnectionStringsProvider>(); designerConfigurator.RegisterDataSourceWizardJsonConnectionStorage<CustomDataSourceWizardJsonDataConnectionStorage>(true); designerConfigurator.RegisterObjectDataSourceWizardTypeProvider<ObjectDataSourceWizardCustomTypeProvider>(); }); configurator.ConfigureWebDocumentViewer(viewerConfigurator => { viewerConfigurator.UseCachedReportSourceBuilder(); viewerConfigurator.RegisterJsonDataConnectionProviderFactory<CustomJsonDataConnectionProviderFactory>(); viewerConfigurator.RegisterConnectionProviderFactory<CustomSqlDataConnectionProviderFactory>(); }); configurator.UseAsyncEngine(); }); services.AddDbContext<ReportDbContext>(options => options.UseSqlite(Configuration.GetConnectionString("ReportsDataConnectionString"))); services.AddScoped<ReportWizardCustomizationService, InstantReportWizardCustomizationService>(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory, ReportDbContext db) { db.InitializeDatabase(); var contentDirectoryAllowRule = DirectoryAccessRule.Allow(new DirectoryInfo(Path.Combine(env.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(env.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.UseAuthorization(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Designer}/{id?}"); }); } } }
Mvc/ReportWizardCustomizationServiceMvcExample/Views/Home/Designer.cshtml
Razor
@using ReportWizardCustomizationServiceMvcExample.Models @model ReportDesignerModel <script type="text/html" id="instant-report"> <svg viewBox="-2 -5 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g id="Layer_1" transform="translate(-2, -5)" style="enable-background:new 0 0 32 32"> <g id="Check"> <polygon class="dxd-icon-fill" points="27,5 11,21 5,15 2,18 11,27 30,8 " fill="#727272" /> </g> </g> </svg> </script> <script type="text/html" id="wizard-labels-page"> <div class="dxrd-wizard-type-page dxrd-wizard-type-page-labels"> <div class="page-title">Custom Wizard Page</div> <div class="dx-fieldset"> <div class="dx-field"> <div class="dx-field-label">Report Name</div> <div class="dx-field-value"> <div data-bind="dxTextBox: { value: label4Value }"></div> </div> </div> <div class="dx-field"> <div class="dx-field-label">Label1: </div> <div class="dx-field-value"> <div data-bind="dxTextBox: { value: label1Value }"></div> </div> </div> <div class="dx-field"> <div class="dx-field-label">Label2: </div> <div class="dx-field-value"> <div data-bind="dxTextBox: { value: label2Value }"></div> </div> </div> <div class="dx-field"> <div class="dx-field-label">Label3: </div> <div class="dx-field-value"> <div data-bind="dxTextBox: { value: label3Value }"></div> </div> </div> </div> </div> </script> <link href="~/Content/reportWizardCustomization.css" rel="stylesheet" /> <script src="~/Scripts/reportWizardCustomization.js"></script> @Html.DevExpress().ReportDesigner(settings => { settings.Name = "ReportDesigner1"; settings.ClientSideEvents.CustomizeWizard = "CustomizeReportWizard"; settings.SettingsDataSource.AllowAddDataSource = false; settings.SettingsDataSource.AllowEditDataSource = false; settings.SettingsDataSource.AllowRemoveDataSource = false; // Add the created data source to the list of default data sources. foreach (var dataSourceItem in Model.DataSources) settings.DataSources.Add(dataSourceItem.Key, dataSourceItem.Value); }).BindToUrl("TestReport").GetHtml()
AspNetCore/RWCSAspNetCoreExample/Views/Home/Designer.cshtml
Razor
@using ReportWizardCustomizationServiceAspNetCoreExample.Models @model ReportDesignerCustomModel @{ var designerRender = Html.DevExpress().ReportDesigner("reportDesigner") .Height("100%") .ClientSideEvents((events) => { events.CustomizeWizard("CustomizeReportWizard"); }) .Bind(Model.ReportDesignerModel); @designerRender.RenderHtml() } @section Scripts { <link href="~/css/dx-reporting-skeleton-screen.css" rel="stylesheet" /> <link rel="stylesheet" href="~/css/viewer.part.bundle.css" /> <link rel="stylesheet" href="~/css/designer.part.bundle.css" /> <link rel="stylesheet" href="~/css/ace/ace.bundle.css" /> <link rel="stylesheet" href="~/css/dx.material.blue.light.bundle.css" /> <script src="~/js/reporting.thirdparty.bundle.js"></script> <script src="~/js/viewer.part.bundle.js"></script> <script src="~/js/designer.part.bundle.js"></script> <script src="~/js/reportWizardCustomization.js"></script> <script type="text/html" id="instant-report"> <svg viewBox="-2 -5 32 32" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <g id="Layer_1" transform="translate(-2, -5)" style="enable-background:new 0 0 32 32"> <g id="Check"> <polygon class="dxd-icon-fill" points="27,5 11,21 5,15 2,18 11,27 30,8 " fill="#727272" /> </g> </g> </svg> </script> <script type="text/html" id="wizard-labels-page"> <div class="dxrd-wizard-type-page dxrd-wizard-type-page-labels"> <div class="page-title">Custom Wizard Page</div> <div class="dx-fieldset"> <div class="dx-field"> <div class="dx-field-label">Report Name</div> <div class="dx-field-value"> <div data-bind="dxTextBox: { value: label4Value }"></div> </div> </div> <div class="dx-field"> <div class="dx-field-label">Label1: </div> <div class="dx-field-value"> <div data-bind="dxTextBox: { value: label1Value }"></div> </div> </div> <div class="dx-field"> <div class="dx-field-label">Label2: </div> <div class="dx-field-value"> <div data-bind="dxTextBox: { value: label2Value }"></div> </div> </div> <div class="dx-field"> <div class="dx-field-label">Label3: </div> <div class="dx-field-value"> <div data-bind="dxTextBox: { value: label3Value }"></div> </div> </div> </div> </div> </script> <link href="~/css/reportWizardCustomization.css" rel="stylesheet" /> @designerRender.RenderScripts() }
Angular/RWCSAngularExample/ClientApp/src/app/reportdesigner/report-designer.html
HTML
<dx-report-designer [reportUrl]="reportUrl" height="calc(100vh - 90px)"> <dxrd-request-options [getDesignerModelAction]="getDesignerModelAction" [host]="hostUrl"></dxrd-request-options> <dxrd-designer-model-settings [allowMDI]="true"> <dxrd-datasource-settings [allowAddDataSource]="false" [allowEditDataSource]="false" [allowRemoveDataSource]="false"></dxrd-datasource-settings> </dxrd-designer-model-settings> <dxrd-callbacks (CustomizeWizard)="OnCustomizeReportWizard($event)"> </dxrd-callbacks> </dx-report-designer>
Angular/RWCSAngularExample/ClientApp/src/app/reportdesigner/report-designer.ts
TypeScript
import { Component, Inject, ViewEncapsulation } from '@angular/core'; import { WizardPageBase } from '@devexpress/analytics-core/analytics-wizard'; import { addToBindingsCache } from '@devexpress/analytics-core/analytics-utils' import * as ko from 'knockout'; import * as $ from 'jquery'; @Component({ selector: 'report-designer', encapsulation: ViewEncapsulation.None, templateUrl: './report-designer.html', styleUrls: [ '../../../node_modules/ace-builds/css/ace.css', '../../../node_modules/ace-builds/css/theme/dreamweaver.css', '../../../node_modules/ace-builds/css/theme/ambiance.css', "../../../node_modules/devextreme/dist/css/dx.material.blue.light.css", "../../../node_modules/@devexpress/analytics-core/dist/css/dx-analytics.common.css", "../../../node_modules/@devexpress/analytics-core/dist/css/dx-analytics.material.blue.light.css", "../../../node_modules/@devexpress/analytics-core/dist/css/dx-querybuilder.css", "../../../node_modules/devexpress-reporting/dist/css/dx-webdocumentviewer.css", "../../../node_modules/devexpress-reporting/dist/css/dx-reportdesigner.css" ] }) export class ReportDesignerComponent { getDesignerModelAction = "DXXRD/GetDesignerModel"; reportUrl = "TestReport"; OnCustomizeReportWizard(event) { this.CustomizeReportWizard(event.args); } beforeInitializeWizard(args) { class LabelPage extends WizardPageBase { canNext() { return false; } canFinish() { return true; } commit() { return $.Deferred().resolve({ Label1: this.label1Value(), Label2: this.label2Value(), Label3: this.label3Value(), ReportName: this.label4Value(), }).promise(); } label1Value = ko.observable('Label1'); label2Value = ko.observable('Label2'); label3Value = ko.observable('Label3'); label4Value = ko.observable('SomeReportName'); } args.wizard.pageFactory.registerMetadata('CustomLabelPage', { create: () => new LabelPage(), getState: (state) => state, setState: (data, state) => { state.customData = JSON.stringify(data); }, resetState: (state, defaultState) => { state.customData = undefined; }, template: 'wizard-labels-page', navigationPanelText: 'Specify label values' }); } afterInit(args) { const defaultGetNextPageId = args.wizard.iterator.getNextPageId; args.wizard.iterator.getNextPageId = function (pageId) { if (pageId === 'selectReportTypePage' && args.wizard.iterator._getCurrentState().reportTemplateID === 'CustomLabelReport') { return 'CustomLabelPage'; } else { return defaultGetNextPageId.apply(this, [pageId]); } }; } beforeFinishWizard(args) { args.state.customData = args.state.customData || 'CustomizeEmptyReport'; } CustomizeReportWizard(event) { if (event.Type === 'ReportWizard') { addToBindingsCache('dxTextBox: { value: label4Value }', function ($context, $element) { return { 'dxTextBox': function () { return { 'value': $context.$data.label4Value } } } }); addToBindingsCache('dxTextBox: { value: label1Value }', function ($context, $element) { return { 'dxTextBox': function () { return { 'value': $context.$data.label1Value } } } }); addToBindingsCache('dxTextBox: { value: label2Value }', function ($context, $element) { return { 'dxTextBox': function () { return { 'value': $context.$data.label2Value } } } }); addToBindingsCache('dxTextBox: { value: label3Value }', function ($context, $element) { return { 'dxTextBox': function () { return { 'value': $context.$data.label3Value } } } }); event.Wizard.events.addHandler('beforeInitialize', this.beforeInitializeWizard); event.Wizard.events.addHandler('afterInitialize', this.afterInit); event.Wizard.events.addHandler('beforeFinish', this.beforeFinishWizard); } } constructor(@Inject('BASE_URL') public hostUrl: string) { } }
Mvc/ReportWizardCustomizationServiceMvcExample/Scripts/reportWizardCustomization.js
JavaScript
function beforeInitializeWizard(args) { class LabelPage extends DevExpress.Analytics.Wizard.WizardPageBase { canNext() { return false; } canFinish() { return true; } commit() { return $.Deferred().resolve({ Label1: this.label1Value(), Label2: this.label2Value(), Label3: this.label3Value(), ReportName: this.label4Value(), }).promise(); } label1Value = ko.observable('Label1'); label2Value = ko.observable('Label2'); label3Value = ko.observable('Label3'); label4Value = ko.observable('SomeReportName'); } args.wizard.pageFactory.registerMetadata('CustomLabelPage', { create: () => new LabelPage(), getState: (state) => state, setState: (data, state) => { state.customData = JSON.stringify(data); }, resetState: (state, defaultState) => { state.customData = undefined; }, template: 'wizard-labels-page', navigationPanelText: 'Specify label values' }); } function afterInit(args) { const defaultGetNextPageId = args.wizard.iterator.getNextPageId; args.wizard.iterator.getNextPageId = function (pageId) { if(pageId === 'selectReportTypePage' && args.wizard.iterator._getCurrentState().reportTemplateID === 'CustomLabelReport') { return 'CustomLabelPage'; } else { return defaultGetNextPageId.apply(this, [pageId]); } }; } function CustomizeReportWizard(s, e) { if(e.Type === 'ReportWizard') { DevExpress.Analytics.Widgets.Internal.addToBindingsCache('dxTextBox: { value: label4Value }', function($context, $element) { return { 'dxTextBox': function() { return { 'value': $context.$data.label4Value } } } }); DevExpress.Analytics.Widgets.Internal.addToBindingsCache('dxTextBox: { value: label1Value }', function($context, $element) { return { 'dxTextBox': function() { return { 'value': $context.$data.label1Value } } } }); DevExpress.Analytics.Widgets.Internal.addToBindingsCache('dxTextBox: { value: label2Value }', function($context, $element) { return { 'dxTextBox': function() { return { 'value': $context.$data.label2Value } } } }); DevExpress.Analytics.Widgets.Internal.addToBindingsCache('dxTextBox: { value: label3Value }', function($context, $element) { return { 'dxTextBox': function() { return { 'value': $context.$data.label3Value } } } }); e.Wizard.events.addHandler('beforeInitialize', beforeInitializeWizard); e.Wizard.events.addHandler('afterInitialize', afterInit); e.Wizard.events.addHandler('beforeFinish', (result) => { result.state.customData = result.state.customData || 'CustomizeEmptyReport'; }); } }
Mvc/ReportWizardCustomizationServiceMvcExample/PredefinedReports/LabelReport.cs
C#
using System.Text.Json; namespace ReportWizardCustomizationServiceMvcExample.PredefinedReports { public partial class LabelReport : DevExpress.XtraReports.UI.XtraReport { public LabelReport() { InitializeComponent(); } public void ApplyCustomData(string customDataJson) { Labels labels = JsonSerializer.Deserialize<Labels>(customDataJson); xrLabel1.Text = labels.Label1; xrLabel2.Text = labels.Label2; xrLabel3.Text = labels.Label3; Name = labels.ReportName; DisplayName = labels.ReportName; } } public class Labels { public string Label1 { get; set; } public string Label2 { get; set; } public string Label3 { get; set; } public string ReportName { get; set; } } }
AspNetCore/RWCSAspNetCoreExample/Controllers/HomeController.cs
C#
using System.Collections.Generic; using System.Threading.Tasks; using DevExpress.DataAccess.Sql; using Microsoft.AspNetCore.Mvc; using DevExpress.XtraReports.UI; using DevExpress.XtraReports.Web.ReportDesigner; using DevExpress.AspNetCore.Reporting.QueryBuilder; using DevExpress.AspNetCore.Reporting.ReportDesigner; using DevExpress.AspNetCore.Reporting.WebDocumentViewer; namespace ReportWizardCustomizationServiceAspNetCoreExample.Controllers { public class HomeController : Controller { public IActionResult Index() { return View(); } public IActionResult Error() { Models.ErrorModel model = new Models.ErrorModel(); return View(model); } public async Task<IActionResult> Designer( [FromServices] IReportDesignerClientSideModelGenerator clientSideModelGenerator, [FromQuery] string reportName) { Models.ReportDesignerCustomModel model = new Models.ReportDesignerCustomModel(); model.ReportDesignerModel = await CreateDefaultReportDesignerModel(clientSideModelGenerator, reportName, null); model.ReportDesignerModel.DataSourceSettings.AllowAddDataSource = false; model.ReportDesignerModel.DataSourceSettings.AllowEditDataSource = false; model.ReportDesignerModel.DataSourceSettings.AllowRemoveDataSource = false; return View(model); } public static Dictionary<string, object> GetAvailableDataSources() { var dataSources = new Dictionary<string, object>(); // Create a SQL data source with the specified connection string. SqlDataSource 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); return dataSources; } public static async Task<ReportDesignerModel> CreateDefaultReportDesignerModel(IReportDesignerClientSideModelGenerator clientSideModelGenerator, string reportName, XtraReport report) { reportName = string.IsNullOrEmpty(reportName) ? "TestReport" : reportName; var dataSources = GetAvailableDataSources(); if(report != null) { return await clientSideModelGenerator.GetModelAsync(report, dataSources, ReportDesignerController.DefaultUri, WebDocumentViewerController.DefaultUri, QueryBuilderController.DefaultUri); } return await clientSideModelGenerator.GetModelAsync(reportName, dataSources, ReportDesignerController.DefaultUri, WebDocumentViewerController.DefaultUri, QueryBuilderController.DefaultUri); } } }

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.