Install
$ agentstack add skill-devexpress-agent-skills-devexpress-reports-aspnetcore ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
DevExpress ASP.NET Core Reporting — Viewer & Designer Integration
Integrates the DevExpress Web Document Viewer (read-only preview) and Web Report Designer (full end-user designer) into ASP.NET Core MVC and Razor Pages applications. The viewer renders reports in the browser via server-side document generation; the designer lets end-users create and save reports without developer involvement.
This skill covers UI component integration only. For creating reports programmatically (bands, controls, data binding, expressions, export), use the devexpress-reports-core skill.
When to Use This Skill
- Add a Document Viewer to an ASP.NET Core MVC or Razor Pages application
- Add an End-User Report Designer to an ASP.NET Core application
- Configure Program.cs services and middleware for reporting
- Set up npm bundling (bundleconfig.json, libman.json) for reporting assets
- Implement
ReportStorageWebExtensionorIReportProvider - Customize viewer/designer toolbar, tab panel, export options, parameter editors
- Configure security: authorization, CSRF protection, CSP nonce
- Deploy reporting to Linux or macOS (Skia renderer setup)
- Troubleshoot blank viewers, HTTP errors, or script loading failures
- Set up multi-server (web farm/garden) document storage
Prerequisites & Installation
NuGet Packages
| Package | Purpose | |---------|---------| | DevExpress.AspNetCore.Reporting | Document Viewer + Report Designer server-side | | BuildBundlerMinifier | Bundles npm output into wwwroot/ | | Microsoft.Web.LibraryManager.Build | Copies icon fonts to wwwroot/ | | DevExpress.Drawing.Skia | Required on Linux and macOS hosts |
npm Packages (package.json)
{
"dependencies": {
"bootstrap": "^4.3.1",
"devextreme-dist": "26.1-stable",
"@devexpress/analytics-core": "26.1-stable",
"devexpress-reporting": "26.1-stable"
}
}
> npm and NuGet versions must match. All DevExpress packages — both npm and NuGet — must use the same major.minor version (e.g., 26.1). A mismatch causes configurator.UseDevelopmentMode() to report version errors and the viewer to silently fail.
Mandatory Setup Order
Complete all steps in order before running the app. Missing any step causes the viewer/designer to fail silently or throw 500 errors.
Step 1 — Install NuGet packages (DevExpress.AspNetCore.Reporting, BuildBundlerMinifier, Microsoft.Web.LibraryManager.Build)
Step 2 — Install Node.js (LTS) if not already installed
Step 3 — Add package.json with npm dependencies above; right-click → Restore Packages or run npm install. npm install must complete before dotnet build — LibMan's filesystem provider requires node_modules to exist.
Step 4 — Add bundleconfig.json (see [references/getting-started.md](references/getting-started.md) for full content). This defines CSS/JS bundles that are copied to wwwroot/ at build time.
Step 5 — Add libman.json (see [references/getting-started.md](references/getting-started.md)) to copy icon font files to wwwroot/css/icons/.
Step 6 — Program.cs — add three lines:
using DevExpress.AspNetCore;
using DevExpress.AspNetCore.Reporting; // required for ConfigureReportingServices
builder.Services.AddDevExpressControls();
builder.Services.ConfigureReportingServices(configurator => {
configurator.ConfigureWebDocumentViewer(c => c.UseCachedReportSourceBuilder());
});
// ... (after builder.Build())
app.UseDevExpressControls(); // must come BEFORE app.UseStaticFiles()
app.UseStaticFiles();
Step 7 — Add controllers (see Component Overview below)
Step 8 — _ViewImports.cshtml:
@using DevExpress.AspNetCore
Step 9 — _Layout.cshtml — add thirdparty bundle to ``:
Step 10 — View file — add reporting bundle + HTML helper (see Component Overview)
Before You Start — Ask the Developer
Before generating code, ask:
- Component: Document Viewer only, or also End-User Report Designer?
- App template: MVC (Model-View-Controller) or Razor Pages?
- Report source: Instance binding (
new MyReport()) for quickstart, or storage-backed (ReportStorageWebExtension) for load/save by name? - Target OS: Windows, Linux, or macOS? (Skia package required for non-Windows)
- Existing project or new? If existing, check for conflicting npm packages (jQuery, Knockout, Bootstrap, DevExtreme) already in bundleconfig.json.
- Security: Is authorization required on the reporting endpoints?
Component Overview
Document Viewer (read-only)
Requires: 1 controller, viewer-specific bundles.
// Controllers/ReportingControllers.cs
using DevExpress.AspNetCore.Reporting.WebDocumentViewer;
using DevExpress.AspNetCore.Reporting.WebDocumentViewer.Native.Services;
public class CustomWebDocumentViewerController : WebDocumentViewerController {
public CustomWebDocumentViewerController(IWebDocumentViewerMvcControllerService s)
: base(s) { }
}
@* Views/Home/Index.cshtml — viewer page *@
@Html.DevExpress().WebDocumentViewer("DocumentViewer").Height("1000px").Bind(new TestReport())
End-User Report Designer
Requires: 3 controllers + ReportStorageWebExtension, designer-specific bundles.
// Controllers/ReportingControllers.cs — all three required
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;
public class CustomWebDocumentViewerController : WebDocumentViewerController {
public CustomWebDocumentViewerController(IWebDocumentViewerMvcControllerService s) : base(s) { }
}
public class CustomReportDesignerController : ReportDesignerController {
public CustomReportDesignerController(IReportDesignerMvcControllerService s) : base(s) { }
}
public class CustomQueryBuilderController : QueryBuilderController {
public CustomQueryBuilderController(IQueryBuilderMvcControllerService s) : base(s) { }
}
@* Views/Home/Index.cshtml — designer page *@
@(Html.DevExpress().ReportDesigner("reportDesigner")
.Height("1000px")
.Bind(new TestReport()))
> Critical: For multi-line fluent chains, always wrap in @(...). Without it, trailing method calls render as literal text in the page output. > > Critical: Do NOT load viewer.part.bundle.js on a designer page. The designer bundle already includes the viewer scripts. Loading both causes Component dx-filtereditor-plain is already registered and DxReportDesigner undefined.
Documentation & Navigation Guide
Full MVC Setup (bundleconfig.json, libman.json, Program.cs, controllers, views)
📄 [references/getting-started.md](references/getting-started.md) 📄 [references/getting-started-razor-pages.md](references/getting-started-razor-pages.md)
Report Storage and Name Resolution (ReportStorageWebExtension, IReportProvider)
📄 [references/report-storage.md](references/report-storage.md)
When you need to: enable Save/Load/Open in the designer; serve reports by name string; use Bind("ReportName") vs. Bind(new Report()).
Viewer Customization (toolbar, tab panel, export options, parameters, client-side events)
📄 [references/viewer-customization.md](references/viewer-customization.md)
Designer Customization (toolbar, toolbox, wizards, data sources, parameter editing)
📄 [references/designer-customization.md](references/designer-customization.md)
Security (authorization, CSRF, CSP nonce, token auth, multi-tenancy)
📄 [references/security.md](references/security.md)
Troubleshooting (symptom→fix table, development mode, logging, web farms)
📄 [references/troubleshooting.md](references/troubleshooting.md)
Quick Start Example
See [examples/quickstart-viewer.cs](examples/quickstart-viewer.cs) and [examples/quickstart-designer.cs](examples/quickstart-designer.cs) for complete, runnable projects.
Minimal Program.cs (MVC, Document Viewer):
using DevExpress.AspNetCore;
using DevExpress.AspNetCore.Reporting;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();
builder.Services.AddDevExpressControls();
builder.Services.ConfigureReportingServices(configurator => {
if (builder.Environment.IsDevelopment())
configurator.UseDevelopmentMode();
configurator.ConfigureWebDocumentViewer(c => c.UseCachedReportSourceBuilder());
});
var app = builder.Build();
app.UseDevExpressControls();
app.UseStaticFiles();
app.UseRouting();
app.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
app.Run();
Key API Surface
Program.cs Registration
| Method | Namespace | Purpose | |--------|-----------|---------| | AddDevExpressControls() | DevExpress.AspNetCore | Register core DX services | | ConfigureReportingServices(Action) | DevExpress.AspNetCore.Reporting | Register viewer/designer services | | UseDevExpressControls() | DevExpress.AspNetCore | Add middleware — before UseStaticFiles | | UseCachedReportSourceBuilder() | (on WebDocumentViewerConfigurationBuilder) | Enable document caching | | UseDevelopmentMode() | (on ReportingConfigurationBuilder) | Verbose error output + version check |
Controller Routes
| Controller | Route | Required For | |-----------|-------|-------------| | WebDocumentViewerController | DXXRDV | Viewer + Designer | | ReportDesignerController | DXXRD | Designer only | | QueryBuilderController | DXXQB | Designer only |
Report Name Resolution (choose one)
| Service | Use When | |---------|---------| | IReportProvider | Viewer-only; map name → XtraReport instance | | ReportStorageWebExtension | Designer present; full save/load/list | | IWebDocumentViewerReportResolver | Highest priority; viewer-only; no async support |
Common Patterns
Pattern 1: Serve a report by name (IReportProvider)
// Services/ReportProvider.cs
using DevExpress.XtraReports.Services;
public class ReportProvider : IReportProvider {
public XtraReport GetReport(string id, ReportProviderContext context) {
return id switch {
"SalesReport" => new SalesReport(),
"InvoiceReport" => new InvoiceReport(),
_ => throw new InvalidOperationException($"Report '{id}' not found.")
};
}
}
// Program.cs
builder.Services.AddScoped();
@Html.DevExpress().WebDocumentViewer("DocumentViewer").Height("1000px").Bind("SalesReport")
Pattern 2: Async export from a controller action
public async Task ExportPdf(string reportName) {
var report = new SalesReport();
report.RequestParameters = false;
await report.CreateDocumentAsync(); // never use CreateDocument() in web apps
using var stream = new MemoryStream();
report.ExportToPdf(stream);
return File(stream.ToArray(), "application/pdf", "report.pdf");
}
Pattern 3: Pass parameters to viewer at load time
@Html.DevExpress().WebDocumentViewer("DocumentViewer")
.Height("1000px")
.Bind("SalesReport?StartDate=2025-01-01&Region=North")
// In IReportProvider.GetReport — parse and apply:
public XtraReport GetReport(string id, ReportProviderContext context) {
var uri = new Uri("http://x/" + id);
var qs = Microsoft.AspNetCore.WebUtilities.QueryHelpers.ParseQuery(uri.Query);
var report = new SalesReport();
var startDateValue = qs["StartDate"];
if (!string.IsNullOrWhiteSpace(startDateValue) &&
DateTime.TryParse(startDateValue, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out var startDate))
report.Parameters["StartDate"].Value = startDate;
report.Parameters["StartDate"].Visible = false;
return report;
}
Troubleshooting
| Symptom | Cause | Fix | |---------|-------|-----| | Viewer blank, no errors in console | UseDevExpressControls() missing or after UseStaticFiles() | Move app.UseDevExpressControls() before app.UseStaticFiles() | | "Unable to process binding" in browser | Script load order wrong — DevExtreme or Analytics not loaded before viewer init | Ensure thirdparty.bundle.js loads in layout `, not in @section Scripts {} | | Component dx-filtereditor-plain is already registered | Both viewer and designer bundles loaded on designer page | Remove viewer bundle from designer page — designer bundle includes viewer scripts | | DevExpress is not defined | dx.all.js missing from bundle or loaded after reporting scripts | Verify dx.all.js is first entry in designer.part.bundle.js / viewer.part.bundle.js | | Literal fluent-call text in page (e.g. .Height("...")) | Multi-line Razor helper not wrapped in @(...) | Wrap: @(Html.DevExpress().ReportDesigner(...).Height(...).Bind(...)) | | HTTP 400 on DXXRDV | Anti-forgery token rejection | Add [IgnoreAntiforgeryToken] to viewer/designer controllers | | HTTP 404 on DXXRDV / DXXRD | Controller missing or MapDefaultControllerRoute() absent | Add controllers; in Razor Pages apps also call endpoints.MapDefaultControllerRoute() | | HTTP 500, no details | Server exception; development mode off | Add configurator.UseDevelopmentMode() and set "DevExpress": "Debug" in appsettings.json | | DllNotFoundException for Skia at runtime | Missing DevExpress.Drawing.Skia on Linux/macOS | dotnet add package DevExpress.Drawing.Skia | | "Report not found: ReportName" | Designer binding by name with no storage resolving it | Use Bind(new MyReport()) for quickstart, or implement ReportStorageWebExtension.GetData("ReportName") | | FaultException compile error in storage class | WCF type used in storage; not available in ASP.NET Core | Replace FaultException with InvalidOperationException | | npm package version ≠ NuGet version | devextreme-dist or @devexpress/analytics-core version mismatch | Align all to same major.minor (26.1). Enable UseDevelopmentMode() to confirm. | | Build error: libman.json file not found | npm install did not run before build | Run npm install first; LibMan filesystem provider requires node_modules | | ko is not defined in browser console | Knockout missing from bundle or loaded after dx.all.js | Ensure knockout-latest.js is in thirdparty.bundle.js **before** dx.all.js in viewer.part.bundle.js. Order: jQuery → Knockout → Bootstrap → (then) dx.all.js → analytics-core → webdocumentviewer | | DevExtreme library is included before Knockout warning in console | dx.all.js loads before Knockout | Move Knockout into thirdparty.bundle.js (first bundle, loaded in layout ). dx.all.js must come after Knockout — it goes in viewer.part.bundle.js` (loaded per-page) |
Constraints & Rules
CRITICAL — follow in every interaction:
- Build verification: Run
dotnet build --projectafter changes. Do not report success without seeing a clean build. - npm before build: Run
npm installbeforedotnet buildwhenlibman.jsonuses the filesystem provider.node_modulesmust exist for LibMan to copy icon files. - Namespace for ConfigureReportingServices: Always add
using DevExpress.AspNetCore.Reporting;. Without it,ConfigureReportingServicesis not resolved. - UseDevExpressControls order: Must come before
app.UseStaticFiles(). Reversing this causes the viewer to silently fail. - Designer bundle self-containment:
designer.part.bundle.jsmust includedx.all.js+dx-analytics-core.min.js+dx-webdocumentviewer.min.js+dx-querybuilder.min.js+dx-reportdesigner.min.js— all in that order. Do not load a separate viewer bundle on the designer page. - Thirdparty bundle in layout head:
thirdparty.bundle.js
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: DevExpress
- Source: DevExpress/agent-skills
- License: MIT
- Homepage: https://www.devexpress.com
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.