I have a .NET Core Web API that generates reports using Telerik Reporting. The report generation works perfectly in my local development environment, but when deployed to an Azure VM with IIS, it fails immediately with OperationCanceledException. The operation doesn't even wait for the configured 5-minute timeout.
The issue is intermittent. It works sometimes but suddenly stops working without any code changes.
Error Stack Trace
The operation was canceled. at System.Threading.CancellationToken.ThrowOperationCanceledException()
at System.Threading.ManualResetEventSlim.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.SpinThenBlockingWait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.InternalWaitCore(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, CancellationToken cancellationToken)
at System.Threading.Tasks.Task.Wait(CancellationToken cancellationToken)
at Telerik.Reporting.Paging.PageCompositionBase.SeparateThreadOutputBehavior.Finish()
at Telerik.Reporting.Paging.PageCompositionBase.CreatePages()
at Telerik.Reporting.Paging.PagerBase.Telerik.Reporting.Paging.IPager.CreatePages(IPageHandler handler, LayoutElement root)
at Telerik.Reporting.BaseRendering.RenderingExtensionBase.Render(LayoutElement root, Hashtable renderingContext, Hashtable deviceInfo, CreateStream createStreamCallback, EvaluateHeaderFooterExpressions evalHeaderFooterCallback, PageSettings pageSettings)
at Telerik.Reporting.BaseRendering.RenderingExtensionBase.Render(Report report, Hashtable renderingContext, Hashtable deviceInfo, CreateStream createStreamCallback, EvaluateHeaderFooterExpressions evalHeaderFooterCallback)
at Telerik.Reporting.Processing.ReportProcessor.RenderCore(ExtensionInfo extensionInfo, IList`1 processingReports, Hashtable deviceInfo, IRenderingContext renderingContext, CreateStream createStreamCallback)
at Telerik.Reporting.Processing.ReportProcessor.ProcessAndRender(String format, ReportSource reportSource, Hashtable deviceInfo, IRenderingContext renderingContext, CreateStream createStreamCallback)
at Telerik.Reporting.Processing.ReportProcessor.ProcessAndRenderStateless(String format, ReportSource reportSource, Hashtable deviceInfo, IRenderingContext renderingContext, CreateStream createStreamCallback)
at Telerik.Reporting.Processing.ReportProcessor.RenderReport(String format, ReportSource reportSource, Hashtable deviceInfo, CreateStream createStreamCallback, CancellationToken cancellationToken, String& documentName)
here is the code for report generation
public SalesSummaryDataOutput SalesSummaryReport(SalesReportSummaryRequest requestReport)
{
string reportPath = "\\Reports\\" + ReportTypes.SalesSummary.ToString() + ".trdx";
var reportProcessor = new ReportProcessor();
var deviceInfo = new Hashtable();
var reportSource = new UriReportSource();
reportSource.Uri = _hostEnvironment.ContentRootPath + reportPath;
reportSource.Parameters.Add("FromDate", requestReport.FromDate);
reportSource.Parameters.Add("ToDate", requestReport.ToDate);
reportSource.Parameters.Add("CompanyId", requestReport.CompanyId);
reportSource.Parameters.Add("LocationId", requestReport.LocationId);
reportSource.Parameters.Add("UserId", requestReport.UserId);
reportSource.Parameters.Add("ExecuteReport", true);
deviceInfo["OutputFormat"] = "PNG";
deviceInfo["DpiX"] = 192;
deviceInfo["DpiY"] = 192;
deviceInfo["Timeout"] = 300000;
deviceInfo["ThreadCulture"] = CultureInfo.CurrentCulture.Name;
try
{
CloseStreams();
string documentName = "ReportDocument";
var cts = new CancellationTokenSource(TimeSpan.FromMinutes(5));
bool result = reportProcessor.RenderReport("IMAGE", reportSource, deviceInfo, CreateStream, cts.Token, out documentName);
if (result)
{
var salesSummaryReport = new SalesSummaryDataOutput();
foreach (var stream in _streams)
{
byte[] imageData = ReadToEnd(stream);
string base64String = Convert.ToBase64String(imageData, 0, imageData.Length);
salesSummaryReport.ReportImages.Add(base64String);
}
CloseStreams();
return salesSummaryReport;
}
}
catch (Exception ex)
{
var salesSummaryReport = new SalesSummaryDataOutput();
salesSummaryReport.ReportImages.Add($"Error: {ex.Message}");
CloseStreams();
return salesSummaryReport;
}
return new SalesSummaryDataOutput();
}
Why does the cancellation happen immediately in IIS but not locally?
What could cause this intermittent behavior?
Are there specific IIS or Telerik configurations I'm missing?