Developer Guide
Data Providers
Data providers connect ScreamCode.Reporting to your application data.
Interface
public interface IReportDataProvider
{
string EntityName { get; }
string DisplayName { get; }
IReadOnlyList<ReportColumnDefinition> AvailableColumns { get; }
IReadOnlyList<ReportFilterDefinition> AvailableFilters { get; }
Task<ReportTable> GetDataAsync(ReportBuilderRequest request, CancellationToken ct = default);
Task<int> GetCountAsync(ReportBuilderRequest request, CancellationToken ct = default);
}
Column types
| Type | Description |
|---|---|
string | Text |
int | Integer number |
decimal | Decimal number |
datetime | Date and time |
bool | True/False |
currency | Formatted currency |
Filter types
| Type | Description |
|---|---|
string | Text contains filter |
daterange | From/To date filter |
bool | True/False toggle |
select | Dropdown with predefined options |
Complete example
public class InvoicesDataProvider : IReportDataProvider
{
private readonly AppDbContext _db;
public InvoicesDataProvider(AppDbContext db) => _db = db;
public string EntityName => "invoices";
public string DisplayName => "Invoices";
public IReadOnlyList<ReportColumnDefinition> AvailableColumns =>
[
new() { Name = "InvoiceNumber", DisplayName = "Invoice #", Type = "string" },
new() { Name = "CustomerName", DisplayName = "Customer", Type = "string" },
new() { Name = "Amount", DisplayName = "Amount", Type = "currency" },
new() { Name = "Status", DisplayName = "Status", Type = "string" },
new() { Name = "IssuedAt", DisplayName = "Issued Date", Type = "datetime" },
new() { Name = "IsPaid", DisplayName = "Paid", Type = "bool" }
];
public IReadOnlyList<ReportFilterDefinition> AvailableFilters =>
[
new() { Name = "IssuedAt", DisplayName = "Issue Date", Type = "daterange" },
new() { Name = "CustomerName", DisplayName = "Customer", Type = "string" },
new() { Name = "Status", DisplayName = "Status", Type = "select",
Options = ["Draft", "Sent", "Paid", "Overdue"] },
new() { Name = "IsPaid", DisplayName = "Paid Only", Type = "bool" }
];
public async Task<ReportTable> GetDataAsync(ReportBuilderRequest request, CancellationToken ct = default)
{
var query = _db.Invoices.AsQueryable();
if (request.Filters?.TryGetValue("IssuedAt_from", out var from) == true
&& DateTime.TryParse(from, out var fromDate))
query = query.Where(i => i.IssuedAt >= fromDate);
if (request.Filters?.TryGetValue("CustomerName", out var customer) == true
&& !string.IsNullOrEmpty(customer))
query = query.Where(i => i.CustomerName.Contains(customer));
if (request.PageSize > 0)
query = query.Skip((request.Page - 1) * request.PageSize).Take(request.PageSize);
var data = await query.Select(i => new Dictionary<string, object?>
{
["InvoiceNumber"] = i.InvoiceNumber,
["CustomerName"] = i.CustomerName,
["Amount"] = i.Amount,
["Status"] = i.Status,
["IssuedAt"] = i.IssuedAt,
["IsPaid"] = i.IsPaid
}).ToListAsync(ct);
return new ReportTable { Columns = AvailableColumns.ToList(), Rows = data };
}
public async Task<int> GetCountAsync(ReportBuilderRequest request, CancellationToken ct = default)
=> await _db.Invoices.CountAsync(ct);
}
Registering providers
builder.Services
.AddScreamReporting(builder.Configuration)
.AddDataProvider<InvoicesDataProvider>()
.AddDataProvider<OrdersDataProvider>()
.AddDataProvider<CustomersDataProvider>();
Next: Modules