Dashboards
Core loads JSON chart definitions through OData aggregation. The host supplies management, record pages, and drawers.
Registration
Register AddCoreDashboards() in the API host and AddCoreDashboardsBlazor() in the Blazor host.
Definition
Store parameters and charts in Dashboard.JsonDefinition.
The dashboard entity supplies its name, key, host entity, and List or Single type.
This example shows monthly sales with links to supporting invoices:
{
"parameters": [
{ "id": "twelveMonthsAgo", "name": "From date", "type": "Date", "default": null }
],
"charts": [{
"id": "monthlySales", "name": "Monthly sales", "type": "Bar",
"query": {
"entity": "SalesInvoice",
"filters": [
{ "path": "TransactionDate", "clrType": "Date", "operator": "onorafter", "parameterId": "twelveMonthsAgo" }
],
"dimensions": [{ "id": "month", "property": "TransactionDate", "bucket": "Month" }],
"measures": [{
"kind": "aggregate", "id": "sales", "label": "Sales", "property": "Total", "aggregate": "Sum",
"drillDown": { "mode": "Records", "columns": ["DocNumber", "TransactionDate", "Total"] }
}],
"sort": [{ "dimension": "month", "direction": "Ascending" }],
"top": 12
}
}]
}
Queries use readable, queryable model fields. Display columns can also use readable computed fields.
Aggregates support Count, Sum, Average, Minimum, and Maximum, with optional per-measure filters.
Calculations combine earlier measure IDs using Add, Subtract, Multiply, or SafeDivide.
IDs beginning with _ are hidden input measures.
Dates and context
Date buckets support Day, Week, Month, Quarter, and Year. Weeks start on Monday; DateTimeOffset grouping uses UTC.
For aging, set calculation: "AgingBucket" and anchorParameterId on the dimension.
Default buckets are Current, 1–30, 31–60, 61–90, and 90+ days; null dates show No due date.
Relative-date parameter IDs include today, thirtyDaysAgo, sixtyDaysAgo, ninetyDaysAgo, twelveMonthsAgo,
lastCompletedMonthStart, and currentMonthStart. Leave their default null.
Customize dates with DashboardOptions.StandardDates; IDashboardTimeZoneProvider defaults to UTC.
Same-entity charts inherit the host list's filters and search. Related-entity charts declare a to-one reference:
"context": { "hostEntity": "Customer", "referencePath": "SellToCustomer" }
Core applies that host scope through coreScope before aggregation.
Navigation
Set drillDown per measure in server JSON. Omit it for display-only values. Saves and copies preserve these settings.
Recordsopens source records with the chart and measure filters. Optionalcolumnsselects initial display fields.Entityopens the grouped entity using its actual key. Null groups have no link; duplicate names keep separate keys.
For a chart grouped by SellToCustomer.FullName:
"drillDown": { "mode": "Entity", "referencePath": "SellToCustomer" }
Omit referencePath to open the source entity itself.
Calculated record links declare their supporting aggregate measures:
{
"kind": "calculated", "id": "margin", "label": "Margin",
"calculation": "Subtract", "leftMeasureId": "sales", "rightMeasureId": "cost",
"drillDown": { "mode": "Records", "recordMeasureIds": ["sales", "cost"] }
}
Input filters combine with OR inside the chart scope. Percentage links usually select only the numerator's records.
Individual values open ungrouped records; measure legends keep chart grouping.
Aging legends include all customers in the bucket. Reference labels can open their entity.
Legacy Calculation destinations remain display-only; their chart calculations still work.
Host navigation
Supply one URL resolver for all charts:
<DashboardSidebar NavigationUrl="ResolveNavigation" />
ResolveNavigation(DashboardNavigationTarget target) returns an existing entity URL when EntityGuid is set.
Otherwise, return a record-list URL carrying Label, Filter, Search, CoreScope, GroupBy, Columns, and ScopeLabels.
Use QueryHelpers.AddQueryString to encode these values.
Return null when no route exists. DashboardPanel and DashboardPanelFrame accept the same resolver.
The host owns record pages, drawers, and full-page navigation. Set the ListView's Filter, FixedSearch,
CoreScope, and ScopeLabels from the target; include Guid in its graph for record links.
FixedSearch receives the target's Search. Scope labels appear as fixed filter chips.
Scope and access
Links retain resolved dates, filters, search, and related-entity scope through paging, grouping, counts, and totals. Additional list filters narrow this scope. Dashboards on scoped lists inherit it, including across further references. Details read current records. API permissions and tenant restrictions still apply; a URL grants no access.
Core batches chart queries. Default limits are 200 rows per chart, 1 MiB per definition, and 64 batch parts. Chart row limits do not limit supporting records.