Acontplus.Reports 1.5.7

dotnet add package Acontplus.Reports --version 1.5.7
                    
NuGet\Install-Package Acontplus.Reports -Version 1.5.7
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Acontplus.Reports" Version="1.5.7" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Acontplus.Reports" Version="1.5.7" />
                    
Directory.Packages.props
<PackageReference Include="Acontplus.Reports" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Acontplus.Reports --version 1.5.7
                    
#r "nuget: Acontplus.Reports, 1.5.7"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Acontplus.Reports@1.5.7
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Acontplus.Reports&version=1.5.7
                    
Install as a Cake Addin
#tool nuget:?package=Acontplus.Reports&version=1.5.7
                    
Install as a Cake Tool

Acontplus.Reports

NuGet

.NET

License: MIT

A high-performance .NET library for RDLC report generation and direct printing with advanced features for enterprise applications. Optimized for high concurrency, large reports, thermal printers, and production workloads.

๐Ÿš€ Features

Core Capabilities

  • โœ… Async/Await Support - Fully asynchronous API for better scalability
  • โœ… RDLC Report Generation - Support for PDF, Excel, Word, HTML5, Image exports
  • โœ… Direct Printing - Print reports directly to thermal/receipt printers
  • โœ… High Concurrency - Built-in concurrency limiting and thread-safe operations
  • โœ… Memory Optimization - Stream pooling and efficient memory management for large reports
  • โœ… Smart Caching - Configurable report definition caching with TTL and size limits
  • โœ… Comprehensive Logging - Structured logging with performance metrics
  • โœ… Error Handling - Custom exceptions with detailed error context
  • โœ… Dependency Injection - Full DI support with extension methods
  • โœ… Timeout Protection - Configurable timeouts to prevent runaway report generation
  • โœ… Size Limits - Configurable maximum report sizes

Performance Optimizations

  • Report definition caching reduces file I/O
  • Concurrency limiting prevents resource exhaustion
  • Async operations improve scalability under load
  • Memory pooling reduces GC pressure
  • Cancellation token support for graceful shutdowns
  • Separate semaphore controls for report generation and printing

๐Ÿ“ฆ Installation

NuGet Package Manager

Install-Package Acontplus.Reports

.NET CLI

dotnet add package Acontplus.Reports

PackageReference

<ItemGroup>
  <PackageReference Include="Acontplus.Reports" Version="1.3.15" />
</ItemGroup>

๐ŸŽฏ Quick Start

1. Register Services

using Acontplus.Reports.Extensions;

// In Program.cs or Startup.cs
builder.Services.AddReportServices(builder.Configuration);

// Or with custom configuration
builder.Services.AddReportServices(options =>
{
    options.MainDirectory = "Reports";
    options.MaxConcurrentReports = 20;
    options.MaxConcurrentPrintJobs = 5;
    options.MaxReportSizeBytes = 50 * 1024 * 1024; // 50 MB
    options.ReportGenerationTimeoutSeconds = 180; // 3 minutes
    options.PrintJobTimeoutSeconds = 120; // 2 minutes
    options.EnableReportDefinitionCache = true;
    options.MaxCachedReportDefinitions = 100;
    options.CacheTtlMinutes = 60;
    options.EnableDetailedLogging = true;
});

2. Configure appsettings.json

{
  "Reports": {
    "MainDirectory": "Reports",
    "ExternalDirectory": "C:\\ExternalReports",
    "MaxReportSizeBytes": 104857600,
    "ReportGenerationTimeoutSeconds": 300,
    "PrintJobTimeoutSeconds": 180,
    "EnableReportDefinitionCache": true,
    "MaxCachedReportDefinitions": 100,
    "CacheTtlMinutes": 60,
    "EnableMemoryPooling": true,
    "MaxConcurrentReports": 10,
    "MaxConcurrentPrintJobs": 5,
    "EnableDetailedLogging": false
  }
}

3. Add Report Files

Ensure your RDLC files are included in your project:

<ItemGroup>
    <None Update="Reports\**\*.rdlc">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
    <None Update="Reports\Images\**">
        <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </None>
</ItemGroup>

๐Ÿ“– Comprehensive Usage Guide

Report Generation Service

The IRdlcReportService provides methods for generating reports in various formats.

Complete Example - Invoice Report
using Acontplus.Reports.Interfaces;
using Acontplus.Reports.DTOs;
using Acontplus.Reports.Exceptions;
using Microsoft.AspNetCore.Mvc;
using System.Data;

[ApiController]
[Route("api/[controller]")]
public class InvoiceController : ControllerBase
{
    private readonly IRdlcReportService _reportService;
    private readonly ILogger<InvoiceController> _logger;

    public InvoiceController(
        IRdlcReportService reportService,
        ILogger<InvoiceController> logger)
    {
        _reportService = reportService;
        _logger = logger;
    }

    [HttpGet("{invoiceId}")]
    public async Task<IActionResult> GetInvoice(
        int invoiceId,
        [FromQuery] string format = "PDF",
        CancellationToken cancellationToken = default)
    {
        try
        {
            // Step 1: Create Parameters DataSet
            var parameters = new DataSet();

            // Required: ReportProps table defines report location and format
            var reportPropsTable = new DataTable("ReportProps");
            reportPropsTable.Columns.Add("ReportPath", typeof(string));
            reportPropsTable.Columns.Add("ReportName", typeof(string));
            reportPropsTable.Columns.Add("ReportFormat", typeof(string));
            reportPropsTable.Rows.Add("InvoiceReport.rdlc", $"Invoice_{invoiceId}", format.ToUpper());
            parameters.Tables.Add(reportPropsTable);

            // Optional: ReportParams table for images, logos, and text parameters
            var reportParamsTable = new DataTable("ReportParams");
            reportParamsTable.Columns.Add("paramName", typeof(string));
            reportParamsTable.Columns.Add("paramValue", typeof(byte[]));
            reportParamsTable.Columns.Add("isPicture", typeof(bool));
            reportParamsTable.Columns.Add("isCompressed", typeof(bool));

            // Add text parameters
            reportParamsTable.Rows.Add(
                "CompanyName",
                System.Text.Encoding.UTF8.GetBytes("Acontplus Corporation"),
                false,
                false);

            reportParamsTable.Rows.Add(
                "InvoiceTitle",
                System.Text.Encoding.UTF8.GetBytes("COMMERCIAL INVOICE"),
                false,
                false);

            // Add logo/image parameter
            var logoBytes = await System.IO.File.ReadAllBytesAsync("wwwroot/images/logo.png");
            reportParamsTable.Rows.Add("CompanyLogo", logoBytes, true, false);

            parameters.Tables.Add(reportParamsTable);

            // Step 2: Create Data DataSet with your business data
            var data = new DataSet();

            // Invoice Header
            var headerTable = new DataTable("InvoiceHeader");
            headerTable.Columns.Add("InvoiceNumber", typeof(string));
            headerTable.Columns.Add("InvoiceDate", typeof(DateTime));
            headerTable.Columns.Add("CustomerName", typeof(string));
            headerTable.Columns.Add("CustomerAddress", typeof(string));
            headerTable.Columns.Add("Subtotal", typeof(decimal));
            headerTable.Columns.Add("Tax", typeof(decimal));
            headerTable.Columns.Add("Total", typeof(decimal));

            // Fetch from database (example)
            var invoice = await GetInvoiceFromDatabaseAsync(invoiceId);
            headerTable.Rows.Add(
                invoice.Number,
                invoice.Date,
                invoice.CustomerName,
                invoice.CustomerAddress,
                invoice.Subtotal,
                invoice.Tax,
                invoice.Total);
            data.Tables.Add(headerTable);

            // Invoice Items
            var itemsTable = new DataTable("InvoiceItems");
            itemsTable.Columns.Add("LineNumber", typeof(int));
            itemsTable.Columns.Add("ProductCode", typeof(string));
            itemsTable.Columns.Add("Description", typeof(string));
            itemsTable.Columns.Add("Quantity", typeof(decimal));
            itemsTable.Columns.Add("UnitPrice", typeof(decimal));
            itemsTable.Columns.Add("Amount", typeof(decimal));

            foreach (var item in invoice.Items)
            {
                itemsTable.Rows.Add(
                    item.LineNumber,
                    item.ProductCode,
                    item.Description,
                    item.Quantity,
                    item.UnitPrice,
                    item.Amount);
            }
            data.Tables.Add(itemsTable);

            // Step 3: Generate the report
            var report = await _reportService.GetReportAsync(
                parameters,
                data,
                externalDirectory: false,
                cancellationToken: cancellationToken);

            _logger.LogInformation(
                "Generated invoice {InvoiceId} in {Format} format, size: {Size} bytes",
                invoiceId, format, report.FileContents.Length);

            // Step 4: Return the file
            return File(
                report.FileContents,
                report.ContentType,
                report.FileDownloadName);
        }
        catch (ReportNotFoundException ex)
        {
            _logger.LogError(ex, "Report template not found for invoice {InvoiceId}", invoiceId);
            return NotFound($"Report template not found: {ex.Message}");
        }
        catch (ReportTimeoutException ex)
        {
            _logger.LogWarning(ex, "Report generation timed out for invoice {InvoiceId}", invoiceId);
            return StatusCode(504, "Report generation timed out");
        }
        catch (ReportSizeExceededException ex)
        {
            _logger.LogWarning(ex, "Report size exceeded limit for invoice {InvoiceId}", invoiceId);
            return StatusCode(413, $"Report too large: {ex.ReportSize} bytes (max: {ex.MaxSize})");
        }
        catch (ReportGenerationException ex)
        {
            _logger.LogError(ex, "Report generation failed for invoice {InvoiceId}", invoiceId);
            return StatusCode(500, $"Report generation failed: {ex.Message}");
        }
    }
}

Printer Service

The IRdlcPrinterService enables direct printing to thermal printers, receipt printers, or standard printers.

Complete Example - Receipt Printing
using Acontplus.Reports.Interfaces;
using Acontplus.Reports.DTOs;
using Acontplus.Reports.Exceptions;

public class PosService
{
    private readonly IRdlcPrinterService _printerService;
    private readonly ILogger<PosService> _logger;

    public PosService(IRdlcPrinterService printerService, ILogger<PosService> logger)
    {
        _printerService = printerService;
        _logger = logger;
    }

    public async Task<bool> PrintReceiptAsync(
        SaleTransaction sale,
        string printerName = "ThermalPrinter80mm",
        CancellationToken cancellationToken = default)
    {
        try
        {
            // Step 1: Configure printer settings
            var printerConfig = new RdlcPrinterDto
            {
                // Printer name from Windows printer settings
                PrinterName = printerName,

                // RDLC file name (in Reports directory)
                FileName = "Receipt.rdlc",

                // Format for printing (IMAGE for thermal printers)
                Format = "IMAGE",

                // Directory paths
                ReportsDirectory = Path.Combine(AppContext.BaseDirectory, "Reports"),
                LogoDirectory = Path.Combine(AppContext.BaseDirectory, "Reports", "Images"),

                // Logo file name (without extension)
                LogoName = "store_logo",

                // Device info for thermal printer (EMF format)
                DeviceInfo = "<DeviceInfo><OutputFormat>EMF</OutputFormat></DeviceInfo>",

                // Number of copies
                Copies = 1
            };

            // Step 2: Prepare data sources
            var dataSources = new Dictionary<string, List<Dictionary<string, string>>>
            {
                // Receipt header data
                ["ReceiptHeader"] = new()
                {
                    new()
                    {
                        ["ReceiptNumber"] = sale.ReceiptNumber,
                        ["TransactionDate"] = sale.Date.ToString("yyyy-MM-dd HH:mm:ss"),
                        ["CashierName"] = sale.CashierName,
                        ["StoreName"] = "Acontplus Store",
                        ["StoreAddress"] = "123 Main St, City, State",
                        ["StoreTaxId"] = "TAX-123456789"
                    }
                },

                // Receipt items
                ["ReceiptItems"] = sale.Items.Select((item, index) => new Dictionary<string, string>
                {
                    ["LineNumber"] = (index + 1).ToString(),
                    ["ProductName"] = item.ProductName,
                    ["Quantity"] = item.Quantity.ToString("F2"),
                    ["UnitPrice"] = item.UnitPrice.ToString("F2"),
                    ["Total"] = item.Total.ToString("F2")
                }).ToList(),

                // Receipt totals
                ["ReceiptTotals"] = new()
                {
                    new()
                    {
                        ["Subtotal"] = sale.Subtotal.ToString("F2"),
                        ["Tax"] = sale.Tax.ToString("F2"),
                        ["Discount"] = sale.Discount.ToString("F2"),
                        ["Total"] = sale.Total.ToString("F2"),
                        ["PaymentMethod"] = sale.PaymentMethod,
                        ["AmountPaid"] = sale.AmountPaid.ToString("F2"),
                        ["Change"] = sale.Change.ToString("F2")
                    }
                }
            };

            // Step 3: Add report parameters
            var reportParams = new Dictionary<string, string>
            {
                ["Barcode"] = sale.ReceiptNumber,
                ["FooterMessage"] = "Thank you for your purchase!",
                ["CustomerName"] = sale.CustomerName ?? "Guest"
            };

            // Step 4: Create print request
            var printRequest = new RdlcPrintRequestDto
            {
                DataSources = dataSources,
                ReportParams = reportParams
            };

            // Step 5: Execute print job
            var success = await _printerService.PrintAsync(
                printerConfig,
                printRequest,
                cancellationToken);

            if (success)
            {
                _logger.LogInformation(
                    "Receipt {ReceiptNumber} printed successfully to {PrinterName}",
                    sale.ReceiptNumber, printerName);
            }

            return success;
        }
        catch (ReportNotFoundException ex)
        {
            _logger.LogError(ex, "Receipt template not found");
            throw;
        }
        catch (ReportTimeoutException ex)
        {
            _logger.LogWarning(ex, "Print job timed out after {Timeout}s", ex.TimeoutSeconds);
            throw;
        }
        catch (ReportGenerationException ex)
        {
            _logger.LogError(ex, "Print job failed: {Message}", ex.Message);
            throw;
        }
    }
}

Multi-Format Report Generation

Generate the same report in different formats:

public async Task<Dictionary<string, byte[]>> GenerateMultiFormatReport(
    DataSet parameters,
    DataSet data,
    CancellationToken cancellationToken)
{
    var formats = new[] { "PDF", "EXCEL", "EXCELOPENXML", "WORDOPENXML", "HTML5" };
    var results = new Dictionary<string, byte[]>();

    foreach (var format in formats)
    {
        // Update format in parameters
        var reportPropsRow = parameters.Tables["ReportProps"]!.Rows[0];
        reportPropsRow["ReportFormat"] = format;

        var report = await _reportService.GetReportAsync(
            parameters,
            data,
            externalDirectory: false,
            cancellationToken);

        results[format] = report.FileContents;
    }

    return results;
}

๐Ÿ“š Advanced Configuration

Configuration Options Reference

Option Type Default Description
MainDirectory string "Reports" Main directory for RDLC files (relative to app base)
ExternalDirectory string? null External directory for offline reports (absolute path)
MaxReportSizeBytes long 104857600 (100MB) Maximum output size in bytes
ReportGenerationTimeoutSeconds int 300 (5min) Timeout for report generation
PrintJobTimeoutSeconds int 180 (3min) Timeout for print jobs
EnableReportDefinitionCache bool true Enable template caching
MaxCachedReportDefinitions int 100 Maximum cached templates
CacheTtlMinutes int 60 Cache expiration time
EnableMemoryPooling bool true Enable memory pooling
MaxConcurrentReports int 10 Max concurrent report generations
MaxConcurrentPrintJobs int 5 Max concurrent print jobs
EnableDetailedLogging bool false Detailed performance logging

DTOs Reference

ReportPropsDto

Defines report properties (required in parameters DataSet as "ReportProps" table):

public class ReportPropsDto
{
    public required string ReportPath { get; set; }      // e.g., "InvoiceReport.rdlc"
    public required string ReportName { get; set; }      // e.g., "Invoice_123"
    public required string ReportFormat { get; set; }    // "PDF", "EXCEL", "EXCELOPENXML", etc.
}
RdlcPrinterDto

Configures printer settings:

public class RdlcPrinterDto
{
    public required string PrinterName { get; set; }      // Windows printer name
    public required string FileName { get; set; }         // RDLC file name
    public required string Format { get; set; }           // "IMAGE" for thermal printers
    public required string ReportsDirectory { get; set; } // Path to Reports folder
    public required string LogoDirectory { get; set; }    // Path to Images folder
    public required string LogoName { get; set; }         // Logo file name (no extension)
    public required string DeviceInfo { get; set; }       // XML device configuration
    public short Copies { get; set; }                     // Number of copies
}
RdlcPrintRequestDto

Contains print data:

public class RdlcPrintRequestDto
{
    // Data sources: DataSet name -> List of rows (as dictionaries)
    public required Dictionary<string, List<Dictionary<string, string>>> DataSources { get; set; }

    // Report parameters: parameter name -> value
    public required Dictionary<string, string> ReportParams { get; set; }
}
ReportResponse

Report output (implements IDisposable):

public class ReportResponse : IDisposable
{
    public byte[] FileContents { get; set; }      // Report binary data
    public string ContentType { get; set; }       // MIME type
    public string FileDownloadName { get; set; }  // Suggested filename
}

Exception Handling

All exceptions inherit from ReportGenerationException:

// Base exception
catch (ReportGenerationException ex)
{
    _logger.LogError(ex, "Report error: {Message}", ex.Message);
    // Properties: ReportPath, ReportFormat
}

// Specific exceptions
catch (ReportNotFoundException ex)
{
    // Report template (.rdlc) file not found
    return NotFound($"Template not found: {ex.ReportPath}");
}

catch (ReportTimeoutException ex)
{
    // Generation or print exceeded timeout
    return StatusCode(504, $"Timeout after {ex.TimeoutSeconds}s");
}

catch (ReportSizeExceededException ex)
{
    // Output exceeded MaxReportSizeBytes
    return StatusCode(413, $"Size {ex.ReportSize} exceeds max {ex.MaxSize}");
}

Supported Export Formats

Format Enum Value Content Type Extension
PDF PDF application/pdf .pdf
Excel (Legacy) EXCEL application/vnd.ms-excel .xls
Excel (Modern) EXCELOPENXML application/vnd.openxmlformats-officedocument.spreadsheetml.sheet .xlsx
Word WORDOPENXML application/vnd.openxmlformats-officedocument.wordprocessingml.document .docx
HTML HTML5 text/html .html
Image IMAGE image/jpeg .jpg

Performance Tuning

High Concurrency Scenario
// E-commerce, multi-tenant, high traffic
options.MaxConcurrentReports = 50;
options.MaxConcurrentPrintJobs = 20;
options.EnableReportDefinitionCache = true;
options.MaxCachedReportDefinitions = 200;
options.ReportGenerationTimeoutSeconds = 120;
options.EnableMemoryPooling = true;
Large Reports Scenario
// Financial statements, data warehouses, complex reports
options.MaxReportSizeBytes = 500 * 1024 * 1024; // 500 MB
options.ReportGenerationTimeoutSeconds = 600; // 10 minutes
options.MaxConcurrentReports = 5; // Limit concurrent large reports
options.EnableMemoryPooling = true;
Memory-Constrained Scenario
// Cloud containers, shared hosting, limited resources
options.MaxConcurrentReports = 3;
options.MaxConcurrentPrintJobs = 2;
options.MaxCachedReportDefinitions = 20;
options.CacheTtlMinutes = 15;
options.MaxReportSizeBytes = 10 * 1024 * 1024; // 10 MB
POS/Retail Scenario
// Point of sale, thermal printers, receipts
options.MaxConcurrentPrintJobs = 10; // Multiple registers
options.PrintJobTimeoutSeconds = 60; // Fast printing
options.EnableReportDefinitionCache = true;
options.MaxCachedReportDefinitions = 50; // Receipt templates
options.EnableDetailedLogging = true; // Track print failures

๐Ÿ” Best Practices

1. Use Async Methods

// โœ… Good - Async
var report = await _reportService.GetReportAsync(params, data, false, ct);

// โŒ Avoid - Synchronous (deprecated)
var report = _reportService.GetReport(params, data, false);

2. Implement Proper Cancellation

[HttpGet("report")]
public async Task<IActionResult> GetReport(CancellationToken cancellationToken)
{
    // Cancellation token is automatically passed from HTTP request
    var report = await _reportService.GetReportAsync(
        params, data, false, cancellationToken);

    return File(report.FileContents, report.ContentType, report.FileDownloadName);
}

3. Dispose Report Responses

// โœ… Using statement ensures disposal
using var report = await _reportService.GetReportAsync(params, data);
ProcessReport(report);

// Or explicitly
var report = await _reportService.GetReportAsync(params, data);
try
{
    ProcessReport(report);
}
finally
{
    report.Dispose();
}

4. Structure Your DataSets Correctly

// Parameters DataSet structure:
// - ReportProps table (required): ReportPath, ReportName, ReportFormat
// - ReportParams table (optional): paramName, paramValue, isPicture, isCompressed

// Data DataSet structure:
// - One or more tables matching your RDLC DataSet names
// - Column names must match RDLC field names exactly

5. Handle Exceptions Gracefully

try
{
    var report = await _reportService.GetReportAsync(params, data, false, ct);
    return File(report.FileContents, report.ContentType, report.FileDownloadName);
}
catch (ReportNotFoundException ex)
{
    return NotFound(new { error = "Template not found", details = ex.Message });
}
catch (ReportTimeoutException ex)
{
    return StatusCode(504, new { error = "Timeout", seconds = ex.TimeoutSeconds });
}
catch (ReportSizeExceededException ex)
{
    return StatusCode(413, new { error = "Too large", size = ex.ReportSize });
}
catch (ReportGenerationException ex)
{
    _logger.LogError(ex, "Report failed");
    return StatusCode(500, new { error = "Generation failed" });
}

6. Enable Logging for Troubleshooting

// Development
options.EnableDetailedLogging = true;

// Production (only enable when needed)
options.EnableDetailedLogging = false;

๐Ÿงช Testing

Unit Test Example

public class ReportServiceTests
{
    private readonly Mock<ILogger<RdlcReportService>> _loggerMock;
    private readonly Mock<IOptions<ReportOptions>> _optionsMock;
    private readonly RdlcReportService _service;

    public ReportServiceTests()
    {
        _loggerMock = new Mock<ILogger<RdlcReportService>>();
        _optionsMock = new Mock<IOptions<ReportOptions>>();
        _optionsMock.Setup(x => x.Value).Returns(new ReportOptions());
        _service = new RdlcReportService(_loggerMock.Object, _optionsMock.Object);
    }

    [Fact]
    public async Task GenerateReport_ValidData_ReturnsReport()
    {
        // Arrange
        var parameters = CreateTestParameters("TestReport.rdlc", "Test", "PDF");
        var data = CreateTestData();

        // Act
        var result = await _service.GetReportAsync(parameters, data);

        // Assert
        Assert.NotNull(result);
        Assert.NotNull(result.FileContents);
        Assert.True(result.FileContents.Length > 0);
        Assert.Equal("application/pdf", result.ContentType);
    }
}

๐Ÿค Contributing

We welcome contributions! Please see our Contributing Guidelines for details.

Development Setup

git clone https://github.com/acontplus/acontplus-dotnet-libs.git
cd acontplus-dotnet-libs
dotnet restore
dotnet build
dotnet test

๐Ÿ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

๐Ÿ†˜ Support

  • ๐Ÿ“ง Email: proyectos@acontplus.com
  • ๐Ÿ› Issues: GitHub Issues
  • ๐Ÿ“– Documentation: Wiki

๐Ÿ‘จโ€๐Ÿ’ป Author

Ivan Paz - @iferpaz7

๐Ÿข Company

Acontplus - Software solutions


Built with โค๏ธ for the .NET community

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.5.7 118 12/25/2025
1.5.6 150 12/23/2025
1.5.5 124 12/11/2025
1.5.4 156 12/5/2025
1.5.3 184 12/4/2025
1.5.1 174 11/27/2025
1.5.0 180 11/23/2025
1.4.9 393 11/17/2025
1.4.8 381 11/17/2025
1.4.7 388 11/17/2025
1.4.6 276 11/11/2025
1.4.5 277 11/11/2025
1.4.4 194 11/6/2025
1.4.3 186 11/5/2025
1.4.2 189 11/5/2025
1.4.1 187 11/5/2025
1.4.0 197 11/5/2025
1.3.16 187 11/5/2025
1.3.15 192 11/2/2025
1.3.14 185 10/23/2025
1.3.13 166 9/26/2025
1.3.12 183 9/25/2025
1.3.11 183 9/25/2025
1.3.10 180 9/25/2025
1.3.9 192 9/24/2025
1.3.8 229 9/14/2025
1.3.7 230 9/14/2025
1.3.6 238 9/14/2025
1.3.5 179 9/10/2025
1.3.4 179 9/9/2025
1.3.3 191 8/21/2025
1.3.2 184 8/19/2025
1.3.1 172 8/8/2025
1.3.0 254 8/7/2025
1.2.5 258 8/5/2025
1.2.4 556 7/23/2025
1.2.3 130 7/18/2025
1.2.2 176 7/15/2025
1.2.1 179 7/15/2025
1.2.0 178 7/14/2025
1.1.0 181 7/14/2025
1.0.20 125 7/11/2025
1.0.19 128 7/11/2025
1.0.18 122 7/11/2025
1.0.17 183 7/10/2025
1.0.16 178 7/10/2025
1.0.15 168 7/10/2025
1.0.14 185 7/9/2025
1.0.13 186 7/9/2025
1.0.12 184 7/9/2025
1.0.11 181 7/7/2025
1.0.10 179 7/6/2025
1.0.9 185 7/6/2025
1.0.8 126 7/4/2025
1.0.7 186 7/3/2025
1.0.6 191 7/2/2025
1.0.5 178 7/2/2025
1.0.4 196 7/1/2025

Enhanced with contemporary report generation patterns, RDLC processing, PDF/Excel export capabilities, ReportViewer integration, template support, and enterprise-ready reporting solutions for business intelligence applications.