Example T1091839
Visible to All Users

BI Dashboard for ASP.NET Core - How to export all dashboard items into the same PDF document

This example shows how to add a custom Export to PDF button that exports all dashboard items into the same PDF document.

Client

On the client, the ViewerApiExtensionOptions.onDashboardTitleToolbarUpdated event is handled to modify the dashboard title and add the custom export button to it. This functionality is encapsulated into a custom dashboard extension (the ExportAllItemsExtension.js file).

To perform the export operation, the client sends a GET request to a custom Export Controller.

Server

The custom Export Controller processes requests from the client side. This controller uses the following classes:

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

AspNetCoreDashboard_ExportAllItems/wwwroot/js/ExportAllItemsExtension.js
JavaScript
var ExportAllItemsExtension = (function () { var _dashboardControl; var _exportRoute; // Viewer function customizeTitleToolbar(e) { e.options.actionItems.push({ icon: 'dx-dashboard-export-to-pdf', tooltip: 'Export All Items', type: 'button', click: performExport }); } function performExport(e) { var queryParameters = new URLSearchParams({ dashboardId: _dashboardControl.getDashboardId(), state: _dashboardControl.getDashboardState() }); window.open(`${_exportRoute}?${queryParameters}`); } // Event Subscription function ExportAllItemsExtension(dashboardControl, exportRoute) { this.name = "exportAllItems"; _dashboardControl = dashboardControl; _exportRoute = exportRoute; this.start = function () { var viewerApiExtension = _dashboardControl.findExtension('viewerApi'); if (viewerApiExtension) { viewerApiExtension.on('dashboardTitleToolbarUpdated', customizeTitleToolbar); } }; this.stop = function () { var viewerApiExtension = _dashboardControl.findExtension('viewerApi'); if (viewerApiExtension) { viewerApiExtension.off('itemCaptionToolbarUpdated', customizeTitleToolbar); } }; } return ExportAllItemsExtension; }());
AspNetCoreDashboard_ExportAllItems/Startup.cs
C#
using AspNetCoreDashboard_ExportAllItems.Classes; using DevExpress.AspNetCore; using DevExpress.DashboardAspNetCore; using DevExpress.DashboardCommon; using DevExpress.DashboardWeb; using DevExpress.DataAccess.Excel; using DevExpress.DataAccess.Sql; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.FileProviders; using Microsoft.Extensions.Hosting; using System; namespace AspNetCoreDashboard_ExportAllItems { public class Startup { public Startup(IConfiguration configuration, IWebHostEnvironment hostingEnvironment) { Configuration = configuration; FileProvider = hostingEnvironment.ContentRootFileProvider; DashboardExportSettings.CompatibilityMode = DashboardExportCompatibilityMode.Restricted; } public IFileProvider FileProvider { get; } 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 .AddResponseCompression() .AddDevExpressControls() .AddMvc(); services.AddScoped<DashboardConfigurator>((IServiceProvider serviceProvider) => { DashboardConfigurator configurator = new DashboardConfigurator(); CustomDashboardStorage customDashboardStorage = new CustomDashboardStorage(FileProvider.GetFileInfo("Data/Dashboards").PhysicalPath); configurator.SetDashboardStorage(customDashboardStorage); DataSourceInMemoryStorage dataSourceStorage = new DataSourceInMemoryStorage(); // Registers an SQL data source. DashboardSqlDataSource sqlDataSource = new DashboardSqlDataSource("SQL Data Source", "NWindConnectionString"); sqlDataSource.DataProcessingMode = DataProcessingMode.Client; SelectQuery query = SelectQueryFluentBuilder .AddTable("Categories") .Join("Products", "CategoryID") .SelectAllColumns() .Build("Products_Categories"); sqlDataSource.Queries.Add(query); dataSourceStorage.RegisterDataSource("sqlDataSource", sqlDataSource.SaveToXml()); // Registers an Object data source. DashboardObjectDataSource objDataSource = new DashboardObjectDataSource("Object Data Source"); dataSourceStorage.RegisterDataSource("objDataSource", objDataSource.SaveToXml()); // Registers an Excel data source. DashboardExcelDataSource excelDataSource = new DashboardExcelDataSource("Excel Data Source"); excelDataSource.FileName = FileProvider.GetFileInfo("Data/Sales.xlsx").PhysicalPath; excelDataSource.SourceOptions = new ExcelSourceOptions(new ExcelWorksheetSettings("Sheet1")); dataSourceStorage.RegisterDataSource("excelDataSource", excelDataSource.SaveToXml()); configurator.SetDataSourceStorage(dataSourceStorage); configurator.DataLoading += (s, e) => { if(e.DataSourceName == "Object Data Source") { e.Data = Invoices.CreateData(); } }; return configurator; }); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { 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.UseDevExpressControls(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapDashboardRoute("dashboardControl", "DefaultDashboard"); endpoints.MapRazorPages(); endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); } } }
AspNetCoreDashboard_ExportAllItems/Classes/CustomDashboardStorage.cs
C#
using DevExpress.DashboardWeb; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Xml.Linq; namespace AspNetCoreDashboard_ExportAllItems.Classes { public class CustomDashboardStorage : DashboardFileStorage { public CustomDashboardStorage(string path) : base(path) { } public XDocument GetDashboardXmlById(string dashboardID) { return this.LoadDashboard(dashboardID); } } }
AspNetCoreDashboard_ExportAllItems/Controllers/ExportController.cs
C#
using AspNetCoreDashboard_ExportAllItems.Classes; using AspNetCoreDashboard_ExportAllItems.Models; using DevExpress.DashboardAspNetCore; using DevExpress.DashboardCommon; using DevExpress.DashboardWeb; using DevExpress.Pdf; using Microsoft.AspNetCore.Mvc; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; namespace AspNetCoreDashboard_ExportAllItems.Controllers { public class ExportController : Controller { [HttpGet] public FileContentResult ExportAllItems([FromServices] DashboardConfigurator dashboardConfigurator, string dashboardId, string state) { CustomDashboardStorage storage = dashboardConfigurator.DashboardStorage as CustomDashboardStorage; Dashboard dashboard = new Dashboard(); dashboard.LoadFromXDocument(storage.GetDashboardXmlById(dashboardId)); MemoryStream resultStream = new MemoryStream(); using (PdfDocumentProcessor documentProcessor = new PdfDocumentProcessor()) { documentProcessor.CreateEmptyDocument(resultStream); for (int i = 0; i < dashboard.Items.Count; i++) { string dashboardItemName = dashboard.Items[i].ComponentName; DashboardState dashboardState = new DashboardState(); dashboardState.LoadFromJson(state); WebDashboardExporter exporter = new WebDashboardExporter(dashboardConfigurator); using (MemoryStream stream = new MemoryStream()) { exporter.ExportDashboardItemToPdf(dashboardId, dashboardItemName, stream, new System.Drawing.Size(1024, 768), dashboardState); documentProcessor.AppendDocument(stream); } } } return File(resultStream.ToArray(), "application/pdf", $"{dashboardId}.pdf"); } } }
AspNetCoreDashboard_ExportAllItems/Models/DashboardExportModel.cs
C#
using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace AspNetCoreDashboard_ExportAllItems.Models { public class DashboardExportModel { public string DashboardId { get; set; } public string DashboardState { get; set; } } }
AspNetCoreDashboard_ExportAllItems/Pages/_Layout.cshtml
Razor
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <title>Dashboard Web Application</title> <link href="css/site.min.css" rel="stylesheet" /> <script type="text/javascript"> function onBeforeRender(sender) { var dashboardControl = sender; var exportRoute = '@Url.Action("ExportAllItems", "Export")'; dashboardControl.registerExtension(new ExportAllItemsExtension(dashboardControl, exportRoute)); } </script> </head> <body> @RenderBody() <script src="js/site.min.js"></script> <script src="js/ExportAllItemsExtension.js"></script> </body> </html>
AspNetCoreDashboard_ExportAllItems/Pages/Index.cshtml
Razor
@page <div style="position: absolute; left: 0; top: 0; right: 0; bottom: 0;"> @(Html.DevExpress().Dashboard("dashboardControl1") .ControllerName("DefaultDashboard") .Width("100%") .Height("100%") .Extensions(extensions => { extensions.UrlState(urlState => { urlState.IncludeDashboardIdToUrl(true); urlState.IncludeDashboardStateToUrl(true); }); }) .OnBeforeRender("onBeforeRender") ) </div>

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.