docs/documentation/quartz-3.x/packages/dashboard.md
Quartz.Dashboard is a Blazor-based dashboard for Quartz.NET that runs inside your ASP.NET Core app and uses Quartz HTTP API endpoints.
::: warning Quartz Dashboard is currently a work in progress. The dashboard API surface may change between releases. Supported target frameworks are .NET 8 and newer. :::
::: tip Quartz 3.16 or later required. :::
Add package references:
Install-Package Quartz.Dashboard
Install-Package Quartz.HttpApi
Configure Quartz, enable HTTP API, and add the dashboard services.
services.AddQuartz(q =>
{
q.AddHttpApi(options =>
{
options.ApiPath = "/quartz-api";
});
});
services.AddQuartzDashboard();
services.AddQuartzHostedService(options => options.WaitForJobsToComplete = true);
Map endpoints:
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();
app.UseEndpoints(endpoints =>
{
endpoints.MapQuartzApi().RequireAuthorization();
endpoints.MapQuartzDashboard();
});
By default, dashboard UI is available at /quartz.
To populate execution history and make related views useful, enable Quartz history plugins in QuartzOptions:
services.Configure<QuartzOptions>(options =>
{
options["quartz.plugin.jobHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin, Quartz.Plugins";
options["quartz.plugin.triggerHistory.type"] = "Quartz.Plugin.History.LoggingTriggerHistoryPlugin, Quartz.Plugins";
});
Use an explicit policy for dashboard access, and secure API endpoints separately:
services.AddAuthorization(options =>
{
options.AddPolicy("QuartzDashboardOps", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireRole("Operations", "SchedulerAdmin");
});
});
services.AddQuartzDashboard(options =>
{
options.AuthorizationPolicy = "QuartzDashboardOps";
});
app.UseEndpoints(endpoints =>
{
endpoints.MapQuartzApi().RequireAuthorization("QuartzDashboardOps");
endpoints.MapQuartzDashboard();
});
If you need machine-to-machine access, use your API auth scheme (for example, an API key handler) and bind that to a policy used by MapQuartzApi().
For dashboard-only custom checks, prefer ASP.NET Core policy/handler-based authorization so the dashboard UI, hub, and API are enforced consistently.
ReadOnly = true) for observers, and a separate write-enabled dashboard for operators.If your host application already uses Blazor Server (i.e., it calls MapRazorComponents<App>().AddInteractiveServerRenderMode()), you must use the MapQuartzDashboard overload that accepts the existing RazorComponentsEndpointConventionBuilder. This avoids registering a second /_blazor SignalR endpoint, which would cause routing conflicts.
services.AddRazorComponents().AddInteractiveServerComponents();
services.AddQuartzDashboard();
app.UseRouting();
app.UseAntiforgery();
var blazor = app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.MapQuartzDashboard(blazor);
The dashboard pages, layout, CSS, and JavaScript interop are automatically registered into the host's Blazor setup via AddAdditionalAssemblies. No additional <link> or <script> tags are needed in your App.razor.
::: warning
Do not call the parameterless MapQuartzDashboard() alongside your own MapRazorComponents — this registers two /_blazor endpoints and causes the dashboard's interactive pages to fail.
:::
If your host project has no .razor files of its own (e.g., a pure API project hosting Quartz), and you are running on .NET 10 or later, you must add the following to your project file:
<PropertyGroup>
<RequiresAspNetWebAssets>true</RequiresAspNetWebAssets>
</PropertyGroup>
This property tells the .NET SDK to include the Blazor framework scripts (_framework/blazor.web.js, blazor.server.js) in the app's static web assets. Without it, requests to /_framework/blazor.web.js return HTTP 404 because in .NET 10+, these files are no longer embedded in the ASP.NET Core assemblies — they are served as static web assets instead.
On .NET 8 and .NET 9, the framework scripts are served via endpoint routing and no extra configuration is needed.