[]
In this tutorial, we will guide you through building an AI-assisted reporting solution made up of two cooperating projects:
An ASP.NET Core back end that exposes an AI reporting endpoint using the ActiveReports AI middleware. It receives a dataset description from the client, sends it to an LLM provider (OpenAI, Azure OpenAI, Google Gemini, or a local Ollama model), and returns ready-to-use report items (tables, tablixes, or charts).
A client-side ActiveReportsJS Web Report Designer that calls that endpoint to let end-users generate report layouts from their data with a single click, instead of building them field-by-field.
By the end of this tutorial, you will have learned how to:
Create an ASP.NET Core minimal API project and install the ActiveReports AI NuGet packages
Configure an AI provider (OpenAI, Azure OpenAI, Google Gemini, or Ollama) and the AI reporting middleware in Program.cs
Enable CORS so a designer hosted on a different origin can call the endpoint
Enable the AI-assisted Explore feature in the ActiveReportsJS Web Report Designer and point it at your endpoint
Run both projects together and generate a report layout from data using AI
Before diving into this tutorial, please ensure the following requirements are met:
.NET SDK: .NET 8.0 SDK or later.
Node.js: a current LTS version of Node.js (includes npm), used to install and serve the client-side designer.
Visual Studio (optional): Visual Studio 2022 or later with the ASP.NET and web development workload, if you prefer building the back end from the IDE rather than the dotnet CLI.
An AI provider account: depending on the provider you choose, one of the following:
An OpenAI API key.
An Azure OpenAI resource, with a deployment name, endpoint URL, and API key.
A Google AI Studio API key for Gemini.
A local Ollama installation with a model pulled (e.g. ollama pull llama3.2).
Basic Knowledge of C#, JavaScript, and Visual Studio: Familiarity with C# programming, plain JavaScript, and navigating Visual Studio is assumed. If you need a refresher, the Microsoft C# Guide and Visual Studio Documentation are excellent resources.
The two projects talk to each other over HTTP:
The Web Report Designer (served as static files, e.g. via http-server) runs in the browser at one origin, such as http://127.0.0.1:8080.
When a user invokes the Explore function for a dataset, the designer sends a POST request describing the dataset's fields to the back end's AI reporting endpoint, by default /api/reporting/ai.
The ASP.NET Core back end runs at a different origin, such as http://localhost:5100. Its AI reporting middleware receives the request, forwards a prompt built from the fields to the configured AI provider, and returns the generated report item definitions (table, tablix, or chart) as JSON.
The designer renders the returned report items directly onto the report layout.
Because the two projects run on different ports, the back end must have CORS enabled, or the browser will block the designer's requests.
Launch Visual Studio (this tutorial is based on Visual Studio 2022, but the steps are similar in other versions, and identical using dotnet new web from the command line).
Select the Create a new project option from the Visual Studio startup window.
In the list of project templates, find and select ASP.NET Core Empty. Click the Next button to continue.
In the Configure your new project dialog, provide a name for your project (for example ActiveReportsAIBackEnd), choose a suitable location, and click Next.
In the Additional Information dialog, select .NET 8.0 (or newer) as the target framework, and click Create.
If you prefer the CLI, the equivalent is:
dotnet new web -n ActiveReportsAIBackEndTwo packages are required:
MESCIUS.ActiveReports.AI.Web — the ASP.NET Core middleware that exposes the AI reporting endpoint.
One provider package, matching the AI service you want to use:
Provider | Package |
|---|---|
OpenAI |
|
Azure OpenAI |
|
Google Gemini |
|
Ollama (local) |
|
To install them:
Right-click on your project in the Solution Explorer and select Manage NuGet Packages.
Go to the Browse tab and search for MESCIUS.ActiveReports.AI.Web. Select it and click Install.
Repeat for the provider package that matches the AI service you intend to use.
Accept the license terms for the installed packages in the License Acceptance dialog.
Or, from the CLI (example using OpenAI):
dotnet add package MESCIUS.ActiveReports.AI.Web
dotnet add package MESCIUS.ActiveReports.Design.AI.OpenAI Open Program.cs and register the AI provider before builder.Build(). Pick the block below that matches the package you installed.
Option A — OpenAI
using GrapeCity.ActiveReports.Design.AI.OpenAI.Extensions;
builder.Services.AddOpenAI(config =>
{
config.ApiKey = "sk-..."; // your OpenAI API key
config.Model = "gpt-4o";
config.Timeout = 300 * 1000; // milliseconds
});Option B — Azure OpenAI
using GrapeCity.ActiveReports.Design.AI.AzureOpenAI.Extensions;
builder.Services.AddAzureOpenAI(config =>
{
config.Endpoint = "https://my-resource.openai.azure.com/";
config.DeploymentName = "my-gpt4o-deployment";
config.Model = "gpt-4o";
config.ApiKey = "...";
config.Timeout = 300 * 1000; // milliseconds
});Option C — Google Gemini
using GrapeCity.ActiveReports.Design.AI.Google.Extensions;
builder.Services.AddGemini(config =>
{
config.ApiKey = "AIza...";
config.Model = "gemini-2.0-flash";
config.Timeout = 300 * 1000; // milliseconds
});Option D — Ollama (local)
using GrapeCity.ActiveReports.Design.AI.Ollama.Extensions;
builder.Services.AddOllama(config =>
{
config.Endpoint = "http://localhost:11434";
config.Model = "llama3.2";
config.Timeout = 300 * 1000; // milliseconds
});Note:
Timeoutis optional on every provider and defaults to90000(90 seconds). AI-generated layouts can take a while for larger datasets, so the sample raises it to 5 minutes.
Security tip: don't hardcode API keys in
Program.csas shown above outside of a quick local test. Use user-secrets in development and environment variables or a secret manager (Azure Key Vault, etc.) in production, then read the value withbuilder.Configuration["OpenAI:ApiKey"].
Still in Program.cs, add the AI reporting middleware after builder.Build():
using GrapeCity.ActiveReports.AI.Web.Extensions;
app.UseAIReporting();By default, this mounts the endpoint at /api/reporting/ai. To use a different path, pass an options delegate:
app.UseAIReporting(options =>
{
options.ApiEndPoint = "/api/custom/ai";
});The endpoint only accepts POST requests with a type query parameter of table, tablix, or chart; any other method or type returns an error, so there's nothing else to configure to try it.
The Web Report Designer will be served from a different origin (a different port on localhost, or a different host entirely), so the browser will block its requests to the AI endpoint unless the back end explicitly allows them. Register a CORS policy before builder.Build(), and apply it before UseAIReporting():
const string CorsPolicyName = "AllowAnyOrigin";
builder.Services.AddCors(options =>
{
options.AddPolicy(CorsPolicyName, policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
app.UseCors(CorsPolicyName);
app.UseAIReporting();AllowAnyOrigin() is convenient for local development, but is too permissive for production. Once you know which host(s) will serve the designer, replace it with an explicit allow-list:
policy.WithOrigins("https://my-designer-host.example.com")
.AllowAnyMethod()
.AllowAnyHeader();Your complete Program.cs (OpenAI variant) should now look like this:
using GrapeCity.ActiveReports.AI.Web.Extensions;
using GrapeCity.ActiveReports.Design.AI.OpenAI.Extensions;
namespace ActiveReportsAIBackEnd
{
public class Program
{
private const string CorsPolicyName = "AllowAnyOrigin";
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenAI(config =>
{
config.ApiKey = "sk-...";
config.Timeout = 300 * 1000;
config.Model = "gpt-4o";
});
builder.Services.AddCors(options =>
{
options.AddPolicy(CorsPolicyName, policy =>
{
policy.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
});
});
var app = builder.Build();
app.UseCors(CorsPolicyName);
app.UseAIReporting();
app.Run();
}
}
}To build your project, go to the Build menu in Visual Studio and select Build Solution (or run dotnet build).
Start the application with Start Debugging/Start Without Debugging in Visual Studio, or dotnet run from the CLI.
Note the URL the project listens on (check Properties/launchSettings.json, or the console output) — for example http://localhost:5100. You'll need it to configure the client project next.
Create a new folder for the client project (for example arjs-test-app) and initialize it with npm init -y.
Install the ActiveReportsJS package and a simple static file server:
npm install @mescius/activereportsjs@latest
npm install http-server --saveAdd a start script to package.json so the folder can be served as static files:
{
"scripts": {
"start": "http-server"
},
"dependencies": {
"@mescius/activereportsjs": "^6.2.0-beta.7237",
"http-server": "^14.1.1"
}
}Create an index.des.html file with the following content:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>ARJS Report designer</title>
<link rel="stylesheet" type="text/css" href="node_modules/@mescius/activereportsjs/styles/ar-js-ui.css" />
<link rel="stylesheet" type="text/css" href="node_modules/@mescius/activereportsjs/styles/ar-js-designer.css" />
<script src="node_modules/@mescius/activereportsjs/dist/ar-js-core.js"></script>
<script src="node_modules/@mescius/activereportsjs/dist/ar-js-designer.js"></script>
<style>
#designer-host {
width: 100%;
height: 100vh;
}
</style>
</head>
<body>
<div id="designer-host"></div>
<script>
var designer = new MESCIUS.ActiveReportsJS.ReportDesigner.Designer("#designer-host", {
data: {
dataSets: {
visible: true,
canModify: true,
features: {
explore: {
enabled: true,
apiEndpoint: "http://localhost:5100/api/reporting/ai"
}
}
}
}
});
designer.setReport({ id: "Reports/Products.rdlx-json", displayName: "my report" });
</script>
</body>
</html>The relevant piece is the data.dataSets.features.explore block:
enabled turns the AI-assisted "Explore" action on for datasets in the Field List panel. It is false by default.
apiEndpoint is the absolute or relative URL of the AI reporting endpoint exposed by the back end. It defaults to /api/reporting/ai (useful when the designer is served by the same origin/app as the back end), but here it points across origins at http://localhost:5100/api/reporting/ai — the address printed when you ran the back end in Part 1.
Start the static file server:
npm starthttp-server prints the URL it's listening on (typically http://127.0.0.1:8080). Open http://127.0.0.1:8080/index.des.html in your browser.
The Web Report Designer should load with an empty (or the specified) report open.
With both projects running follow the guidelines from the Explore function documentation.
CORS error in the browser console (has been blocked by CORS policy): make sure the back end is running, AddCors/UseCors are configured as shown, and UseCors is called before UseAIReporting.
404 Not Found when calling the AI endpoint: double-check that apiEndpoint in index.des.html matches the port the back end is actually listening on, and the path matches ApiEndPoint in AIReportingOptions (default /api/reporting/ai).
401/403 or provider errors: verify the API key, deployment name (Azure OpenAI), or endpoint (Ollama) configured for your provider, and that the account/model has not hit a quota or rate limit.
Timeouts on larger datasets: increase config.Timeout (in milliseconds) for the provider you configured.