Ticomix.TelerikReporting 2025.12.10.1

Ticomix.TelerikReporting

Purpose Statement

A .NET library that provides comprehensive Telerik Reporting integration for web applications, enabling report design, viewing, and management capabilities with support for both Angular and MVC frameworks. Built on Telerik Reporting 18.1.24.709 with enhanced features for enterprise reporting solutions.

Database Models Used

The package requires the following database models to be added to your application:

  • ReportFile: Stores report definition files and metadata
  • ReportFolder: Hierarchical organization of reports
  • ReportHeader: Main report metadata and configuration
  • ReportSubscriptionParameter: Parameter definitions for scheduled reports
  • ReportSubscriptionTelerik: Telerik-specific subscription settings
  • ReportSubscriptionRun: Execution history and status tracking
  • ReportVersion: Version control for report definitions
  • SysJobStatus: Background job status tracking
  • ErrorLog: Comprehensive error logging and monitoring

Additional context files required:

  • ApplicationDbContextErrorLog.cs
  • ApplicationDbContextTelerikReporting.cs

Classes and Functions

Core Controllers

  • TelerikReportDesignerController: Handles report designer web service requests
  • TelerikReportViewerController: Manages report viewer functionality
  • ReportDesignerController: Custom report designer operations
  • ReportViewerController: Custom report viewing operations

Helper Classes

  • ReportHelper: Utility functions for report operations and management

ViewModels

  • ReportHeaderViewModel: Data transfer object for report metadata

Installation Instructions

Prerequisites

Ensure your application has the following NuGet packages installed:

  • Ticomix.TelerikReporting
  • Ticomix.AspNetCore.Mvc.Knedo
  • Ticomix.AspNetCore.Web
  • Ticomix.Common
  • Ticomix.EFCore

Database Setup

  1. Add the required database models and migrations to your project
  2. Include the context files in your \Data folder
  3. Run database migrations to create the necessary tables

ASP.NET Core Configuration

Startup.cs / Program.cs Changes

  1. Configure Swagger (exclude Telerik controllers):
services.AddSwaggerGen(c =>
{
    c.DocInclusionPredicate((docName, apiDesc) =>
    {
        if (apiDesc.ActionDescriptor is ControllerActionDescriptor desc && 
            desc.ControllerTypeInfo.Assembly.FullName.StartsWith("Telerik"))
        {
            return false;
        }
        return apiDesc.GroupName == null || apiDesc.GroupName == docName;
    });
    c.SchemaFilter<NullableSchemaFilter>();
});
  1. Configure Globalization:
Globals.SupportedCultures = CultureInfo.GetCultures(CultureTypes.SpecificCultures);
Globals.DefaultCulture = new CultureInfo("en-US");
  1. Add User Roles:
UserRoleHelper.CreateUserRole("Telerik Report View", 
    Description: "Ability to view Telerik Reports");
UserRoleHelper.CreateUserRole("Telerik Report Edit", 
    Description: "Ability to create and edit Telerik Reports through the web report designer.");
  1. Configure Services:
// Distributed Cache
services.AddDistributedSqlServerCache(options =>
{
    options.ConnectionString = Configuration.GetConnectionString("DefaultConnection");
    options.SchemaName = "dbo";
    options.TableName = "DistributedCacheTable";
});

// Session Management
services.AddSession();

// Distributed Locking
services.AddSingleton<IDistributedLockProvider>((services) => 
    new SqlDistributedSynchronizationProvider(Configuration.GetConnectionString("DefaultConnection")));

// Logging
services.AddScoped<ILogger, Ticomix.Common.Helpers.Logger<int>>();
services.AddScoped<Microsoft.Extensions.Logging.ILogger>((sp) => sp.GetRequiredService<ILogger>());

// Cancellation Token
services.AddScoped(typeof(CancellationToken), serviceProvider =>
{
    IHttpContextAccessor httpContext = serviceProvider.GetRequiredService<IHttpContextAccessor>();
    return httpContext.HttpContext?.RequestAborted ?? CancellationToken.None;
});

// Telerik Reporting Configuration
services.Configure<Ticomix.TelerikReporting.TelerikReportingOptions>(options =>
{
    Configuration.Bind("TelerikReporting", options);
});
services.AddTelerikReporting<int>();
  1. Configure JSON Serialization:
services.AddControllers(c =>
{
    c.Conventions.Add(new ApiExplorerGroupPerVersionConvention());
}).AddJsonOptions(options =>
{
    options.JsonSerializerOptions.PropertyNamingPolicy = null;
}).AddNewtonsoftJson(options =>
{
    options.SerializerSettings.ContractResolver = new DefaultContractResolver();
});
  1. Configure Middleware:
app.UseSession();

wwwroot Setup

  1. Create a wwwroot folder in your server project root
  2. Create a Reports subfolder
  3. Copy Blank Report.trdp into the Reports folder for new report creation

Controller Implementation Examples

Report Management Controller

Example implementation for managing report definitions and metadata:

[Route("api/[controller]/[action]")]
[ApiController]
[Authorize(Roles = "Telerik Report Edit")]
public class ReportDesignerController : ControllerBase
{
    private readonly ApplicationDbContext db;
    private readonly ReportHelper ReportHelper;
    private readonly UserRoleHelper userRoleHelper;

    public ReportDesignerController(IWebHostEnvironment environment, IHttpContextAccessor accessor, 
        ApplicationDbContext context, IOptionsSnapshot<AppConfiguration> appConfiguration)
    {
        db = context;
        db.SetUserName(accessor.HttpContext?.User?.Identity?.Name);
        ReportHelper = new ReportHelper(db, environment);
        userRoleHelper = new UserRoleHelper(db, appConfiguration.Value.SiteId);
    }

    [HttpPost]
    [ProducesResponseType(200, Type = typeof(IDataSourceResult<ReportHeaderViewModel>))]
    public async Task<ActionResult> List_KendoGrid([FromBody] WebApiDataSourceRequest<ReportHeaderViewModel> request, CancellationToken cancellationToken)
    {
        var data = (from rh in db.ReportHeader.AsNoTracking()
                    join rv in db.ReportVersion.AsNoTracking() on rh.IDReportHeader equals rv.ReportHeaderID
                    where rh.Deleted == false
                    select new ReportHeaderViewModel
                    {
                        IDReportHeader = rh.IDReportHeader,
                        FileName = rh.FileName,
                        Description = rh.Description,
                        LastEditedUser = rv.AddUser,
                        LastEditedDateTime = rv.AddDate,
                        IncludeInReportIndex = rh.IncludeInReportIndex,
                        Version = rv.Version
                    }).ToList();

        var result = await data.ToDataSourceResultAsync(request.ToDataSourceRequest(), cancellationToken);
        return Ok(result);
    }

    [HttpPost]
    [ProducesResponseType(StatusCodes.Status200OK, Type = typeof(ReportHeader))]
    public async Task<IActionResult> PostReportHeader([FromBody] ReportHeader viewmodel)
    {
        if (viewmodel.IDReportHeader == Guid.Empty)
        {
            // Create new report with role-based security
            string reportName = Path.GetFileNameWithoutExtension(viewmodel.FileName);
            userRoleHelper.CreateTelerikReportRole(reportName);
            
            string? adminId = userRoleHelper.GetGroupId("Administrator");
            if (adminId != null)
            {
                userRoleHelper.AssignAdministratorRoles(adminId);
            }
        }
        
        return Ok(viewmodel);
    }
}

Report Viewer Controller

Example implementation for viewing reports with role-based access:

[Route("api/[controller]/[action]")]
[ApiController]
[Authorize(Roles = "Telerik Report View")]
public class ReportViewerController : ControllerBase
{
    [HttpPost]
    [ProducesResponseType(200, Type = typeof(IDataSourceResult<ReportListItem>))]
    public async Task<ActionResult> List_KendoGrid([FromBody] WebApiDataSourceRequest<ReportListItem> request, CancellationToken cancellationToken)
    {
        // Get allowed reports based on user roles
        var allowedReports = User.Claims
            .Where(c => c.Type == ClaimTypes.Role && c.Value.StartsWith(TelerikReportLogic.RolePrefix))
            .Select(c => c.Value.Substring(TelerikReportLogic.RolePrefix.Length))
            .ToList();

        var data = await ReportHelper.GetReports(cancellationToken, allowedReports);
        var result = await data.ToDataSourceResultAsync(request.ToDataSourceRequest(), cancellationToken);

        return Ok(result);
    }
}

Telerik Report Designer Controller

Example implementation for Telerik's web report designer:

[Authorize(Roles = "Telerik Report Edit")]
[Route("api/reportdesigner")]
[ApiExplorerSettings(IgnoreApi = true)]
public class TelerikReportDesignerController : ReportDesignerControllerBase
{
    public TelerikReportDesignerController(ReportServiceConfiguration reportServiceConfiguration, 
        ApplicationDbContext context, ICustomResolver resolver, 
        IReportDesignerServiceConfiguration reportDesignerServiceConfiguration, 
        IHttpContextAccessor accessor, IOptionsSnapshot<TelerikReportingOptions> options, 
        CancellationToken cancellationToken)
        : base(reportDesignerServiceConfiguration, reportServiceConfiguration)
    {
        // Custom initialization logic
    }

    public override async Task<IActionResult> GetReportAsync([FromQuery] string uri)
    {
        try
        {
            InstanceReportSource report = (InstanceReportSource)(await resolver.ResolveReport2(uri, null));
            
            string data;
            using (StringWriter stringWriter = new StringWriter())
            {
                new ReportJsonSerializer().Serialize(stringWriter, report.ReportDocument);
                data = stringWriter.ToString();
            }

            return Content(data, "application/json");
        }
        catch
        {
            return CreateJsonResponse(HttpStatusCode.NotFound, "Report with id '" + uri + "' not found.");
        }
    }
}

Telerik Report Viewer Controller

Example implementation for Telerik's report viewer with role-based access:

[Route("api/reports")]
[ApiController]
[Authorize(Roles = "Telerik Report View,Telerik Report Edit")]
[ApiExplorerSettings(IgnoreApi = true)]
public class TelerikReportController : ReportsControllerBase
{
    public override IActionResult CreateInstance(string clientID, [FromBody] ClientReportSource reportSource)
    {
        // Extract report name from report source
        string? reportName = null;
        if (reportSource?.Report != null)
        {
            reportName = Path.GetFileNameWithoutExtension(reportSource.Report);
        }

        if (!string.IsNullOrEmpty(reportName))
        {
            // Check if user has specific role for this report
            string requiredRole = TelerikReportLogic.RolePrefix + reportName;
            if (!User.IsInRole(requiredRole))
            {
                return Unauthorized($"You do not have permission to view this report. Required role: {requiredRole}");
            }
        }

        string tempInstanceID = Guid.NewGuid().ToString();
        return ReportControllerCommon.CreateInstance<int>(tempInstanceID, clientID, reportSource, resolver.controller, base.CreateInstance);
    }
}

File Upload and Download Examples

[DisableRequestSizeLimit]
[HttpPost("{id}")]
public async Task<ActionResult> Upload([FromRoute] string id, IFormFile file)
{
    if (file == null || file.Length == 0)
    {
        return StatusCode(500);
    }

    try
    {
        // Read the file data
        byte[] fileData;
        using (var memoryStream = new MemoryStream())
        {
            await file.CopyToAsync(memoryStream);
            fileData = memoryStream.ToArray();
        }

        // Find the latest version and create a new version
        int latestVersion = await db.ReportVersion
            .Where(rv => rv.ReportHeaderID == Guid.Parse(id))
            .OrderByDescending(rv => rv.Version)
            .Select(rv => rv.Version)
            .FirstOrDefaultAsync();

        var reportVersion = new ReportVersion
        {
            ReportHeaderID = Guid.Parse(id),
            Version = latestVersion + 1,
            BinaryData = fileData
        };

        db.ReportVersion.Add(reportVersion);
        await db.SaveChangesAsync();

        return Ok(new { Message = "File uploaded successfully", Version = reportVersion.Version });
    }
    catch (Exception ex)
    {
        return StatusCode(500, $"Internal server error: {ex.Message}");
    }
}

[HttpGet("{id}")]
public async Task<ActionResult> Download([FromRoute] string id, CancellationToken cancellationToken)
{
    Guid guid = Guid.Parse(id);
    ReportHeader reportHeader = await db.ReportHeader.FindAsync(guid);
    if (reportHeader == null)
    {
        return StatusCode(404);
    }

    byte[] reportData = (from rv in db.ReportVersion
                         where rv.ReportHeaderID == reportHeader.IDReportHeader
                         orderby rv.Version descending
                         select rv.BinaryData).FirstOrDefault();

    FileContentResult result = new FileContentResult(reportData, "application/octet-stream");
    Response.Headers["Content-Disposition"] = $"filename=\"{reportHeader.FileName}\"";

    return result;
}

Angular Integration

For Angular applications, you'll need the companion NPM package:

NPM Package: @ticomix/telerik-reporting

Angular Files Required

  • src/typings.d.ts
  • src/app/telerik-reporting/ folder with components
  • src/app/standalone.service.ts
  • src/app/standalone-routes.ts
  • Update app.component.html for standalone page logic

Additional Dependencies

  • Copy kendo.all.min.js to public/js folder

URL Rewriting (web.config)

For proper routing when designer/viewer opens in new tabs:

<system.webServer>
    <rewrite>
        <rules>
            <rule name="Angular Routes" stopProcessing="true">
                <match url="^(designer|viewer)(/.*)?$" />
                <conditions logicalGrouping="MatchAll">
                    <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                    <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                </conditions>
                <action type="Rewrite" url="/" />
            </rule>
        </rules>
    </rewrite>
</system.webServer>

MVC Integration

For MVC applications, the same server-side configuration applies. Additional MVC-specific views and controllers can be copied from Demo as needed.

Dependencies

Core Dependencies

  • Telerik.Reporting (18.1.24.709)
  • Telerik.Reporting.Services.AspNetCore (18.1.24.709)
  • Telerik.WebReportDesigner.Services (18.1.24.709)
  • Telerik.Reporting.OpenXmlRendering (18.1.24.709)
  • Telerik.Reporting.WebServiceDataSource (18.1.24.709)

Utility Dependencies

  • CsvHelper (33.0.1)
  • Reinforced.Typings (1.6.3.21)
  • DistributedLock.SqlServer (1.0.5)

Ticomix Dependencies

  • Ticomix.EFCore (via project reference)

Support and Documentation

For Angular UI components and additional documentation, visit:

Version Compatibility

  • .NET 6.0+
  • .NET 8.0+
  • Entity Framework Core 6.0+
  • SQL Server 2016+
  • Angular 12+

Showing the top 20 packages that depend on Ticomix.TelerikReporting.

Packages Downloads
Ticomix.Accounting
Package Description
163
Ticomix.Accounting
Package Description
99
Ticomix.Printing.Server
Package Description
98
Ticomix.Accounting
Package Description
87
Ticomix.Printing.Server
Package Description
81
Ticomix.Accounting
Package Description
76
Ticomix.Printing.Server
Package Description
75
Ticomix.Accounting
Package Description
74
Ticomix.Accounting
Package Description
72
Ticomix.Printing.Server
Package Description
70
Ticomix.Accounting
Package Description
69
Ticomix.Accounting
Package Description
59
Ticomix.Printing.Server
Package Description
59
Ticomix.Accounting
Package Description
55
Ticomix.Accounting
Package Description
47
Ticomix.Printing.Server
Package Description
45
Ticomix.Accounting
Package Description
44

Version Downloads Last updated
2025.12.10.1 0 12/10/2025
2025.12.9.3 0 12/9/2025
2025.12.9.2 1 12/9/2025
2025.12.9.1 0 12/9/2025
2025.12.8.2 1 12/8/2025
2025.12.7.1 1 12/7/2025
2025.12.5.2 1 12/5/2025
2025.12.5.1 1 12/5/2025
2025.12.3.2 1 12/3/2025
2025.12.3.1 1 12/3/2025
2025.11.25.1 1 11/25/2025
2025.11.24.1 12 11/24/2025
2025.11.22.1 8 11/22/2025
2025.11.21.2 2 11/22/2025
2025.11.21.1 2 11/21/2025
2025.11.20.4 3 11/20/2025
2025.11.20.3 2 11/20/2025
2025.11.20.2 2 11/20/2025
2025.11.20.1 2 11/20/2025
2025.11.18.2 1 11/18/2025
2025.11.18.1 4 11/18/2025
2025.11.4.1 3 11/4/2025
2025.10.31.1 14 10/31/2025
2025.10.29.1 25 10/29/2025
2025.10.22.1 21 10/22/2025
2025.10.15.1 72 10/15/2025
2025.10.9.1 14 10/10/2025
2025.10.3.2 20 10/3/2025
2025.10.3.1 3 10/3/2025
2025.10.1.4 24 10/1/2025
2025.10.1.3 3 10/1/2025
2025.10.1.2 3 10/1/2025
2025.9.24.1 33 9/24/2025
2025.9.2.3 75 9/2/2025
2025.8.19.3 41 8/19/2025
2025.8.19.2 5 8/19/2025
2025.7.25.1 161 7/25/2025
2025.7.21.3 29 7/21/2025
2025.7.19.2 8 7/19/2025
2025.7.16.1 42 7/16/2025
2025.7.15.1 20 7/15/2025
2025.7.11.2 25 7/11/2025
2025.6.20.2 95 6/20/2025
2025.6.16.5 8 6/16/2025
2025.6.11.2 48 6/11/2025
2025.6.10.2 11 6/10/2025
2025.6.9.2 7 6/9/2025
2025.6.4.1 82 6/4/2025
2025.6.2.1 25 6/2/2025
2025.5.22.1 42 5/22/2025
2025.5.2.1 27 5/2/2025
2025.5.1.1 75 5/1/2025
2025.4.18.12 38 4/18/2025
2025.4.15.1 75 4/15/2025
2025.4.10.1 35 4/10/2025
2025.4.8.4 13 4/8/2025
2025.4.4.10 9 4/4/2025
2025.3.28.1 33 3/28/2025
2025.3.25.2 24 3/25/2025
2025.3.20.1 28 3/20/2025
2025.3.19.5 19 3/19/2025
2025.3.19.3 13 3/19/2025
2025.3.18.5 18 3/18/2025
2025.3.18.4 8 3/18/2025
2025.3.18.3 9 3/18/2025
2025.3.18.2 9 3/18/2025
2025.3.12.1 18 3/12/2025
2025.3.7.1 24 3/7/2025
2025.2.17.2 8 2/17/2025
2025.2.14.2 64 2/14/2025
2025.1.30.1 13 1/30/2025
2025.1.29.2 11 1/29/2025
2025.1.29.1 17 1/29/2025
2025.1.28.1 51 1/28/2025
2025.1.27.4 16 1/27/2025
2025.1.27.3 22 1/27/2025
2025.1.27.2 16 1/27/2025
2025.1.27.1 12 1/27/2025
2025.1.6.1 20 1/6/2025
2024.12.31.2 52 12/31/2024
2024.12.31.1 18 12/31/2024
2024.12.30.1 21 12/30/2024
2024.12.20.2 25 12/20/2024
2024.12.17.18 26 12/17/2024
2024.12.17.2 23 12/17/2024
2024.12.11.3 32 12/11/2024
2024.12.10.1 18 12/10/2024
2024.12.5.3 17 12/5/2024
2024.12.5.2 14 12/5/2024
2024.12.4.10 12 12/4/2024
2024.12.4.9 18 12/4/2024
2024.11.15.4 48 11/16/2024
2024.11.15.1 12 11/15/2024
2024.11.6.3 34 11/6/2024
2024.11.6.1 14 11/6/2024
2024.11.5.6 18 11/5/2024
2024.11.5.4 13 11/5/2024
2024.10.28.3 29 10/28/2024
2024.10.28.2 15 10/28/2024
2024.10.28.1 15 10/28/2024
2024.10.24.1 16 10/24/2024
2024.10.23.1 16 10/23/2024
2024.10.17.2 22 10/17/2024
2024.10.8.1 23 10/8/2024
2024.8.20.1 72 8/20/2024
2024.8.6.1 40 8/6/2024
2024.7.17.1 59 7/17/2024
2024.7.15.1 20 7/15/2024
2024.7.9.4 23 7/9/2024
2024.7.9.3 15 7/9/2024
2024.7.9.2 16 7/9/2024
2024.7.2.1 30 7/2/2024
2024.7.1.4 26 7/1/2024
2024.6.14.1 24 6/14/2024
2024.6.12.2 39 6/12/2024
2024.6.11.1 19 6/11/2024
2024.6.10.1 18 6/10/2024
2024.5.31.2 28 5/31/2024
2024.5.22.2 41 5/22/2024
2024.4.25.1 41 4/25/2024
2024.4.19.3 244 4/19/2024
2024.4.17.1 23 4/17/2024
2024.4.12.3 18 4/12/2024
2024.4.9.1 30 4/9/2024
2024.4.5.3 22 4/5/2024
2024.4.4.2 26 4/4/2024
2024.4.2.1 19 4/2/2024
2024.3.27.2 21 3/27/2024
2024.3.19.4 27 3/19/2024
2024.3.13.5 26 3/13/2024
2024.3.13.2 17 3/13/2024
2024.3.8.2 28 3/8/2024
2024.3.6.1 32 3/6/2024
2024.2.27.1 37 2/27/2024
2024.2.19.1 28 2/19/2024