api controller using AspNetCore.Reporting thows System.FormatException: 'The header contains invalid values at index 0

569 views Asked by At

This api controller is used to return a pdf stream to display in an html object tag

using AspNetCore.Reporting;
using Microsoft.AspNetCore.Mvc;

        [HttpGet, Route("ProcedureRangeForm")]
        public IActionResult ProcedureRangeForm(string procedureRangeId, byte procedureTypeId)
        {
            int extension = 1;
            var _reportPath = "";
            switch (procedureRangeId)
            {
                case "1":
                    _reportPath = @"Reports\ProcedureRangeForm1.rdlc";
                    break;
                case "2":
                    _reportPath = @"Reports\ProcedureRangeForm2.rdlc";
                    break;
                case "3":
                    _reportPath = @"Reports\ProcedureRangeForm3.rdlc";
                    break;
                default:
                    // code block
                    break;
            }
            //Employee employee = _context.Employees.FirstOrDefault(x => x.Id == "41")!;
            ProcedureType procedureType = _context.ProcedureTypes.FirstOrDefault(x => x.Id == procedureTypeId);
            //RelationDegree relationDegree = _context.RelationDegrees.FirstOrDefault(x => x.Id == 1)!;
            var reportParams1 = new Dictionary<string, string>();
            var reportParams2 = new Dictionary<string, string>();
            var reportParams3 = new Dictionary<string, string>();
            reportParams1.Add("UnitCode", "UnitCode");
            reportParams1.Add("ProcedureType", procedureType!.Name!);
            reportParams2.Add("ProcedureType", procedureType!.Name!);
            reportParams3.Add("ProcedureType", procedureType!.Name!);
            //reportParams1.Add("Attachments", "");

            LocalReport localReport = new LocalReport(_reportPath);
            FileContentResult fileContentResult;
            MemoryStream memory = new();
            try
            {
                ReportResult result = null!;
                switch (procedureRangeId)
                {
                    case "1":      
                        result = localReport.Execute(RenderType.Pdf, extension, parameters: reportParams1);
                        break;
                    case "2":
                        result = localReport.Execute(RenderType.Pdf, extension, parameters: reportParams2);
                        break;
                    case "3":
                        result = localReport.Execute(RenderType.Pdf, extension, parameters: reportParams3);
                        break;
                    default:
                        // code block
                        break;
                }
                byte[] file = result.MainStream;
                fileContentResult = new FileContentResult(file, "application/pdf");
            }
            catch (Exception e)
            {
                Console.WriteLine("{0} Exception caught.", e);
                return Content(HttpStatusCode.InternalServerError.ToString(), e.Message);
            }
            finally
            {
            }
            return fileContentResult;
        }

I want to call this api more than once with varient parameters. when i call once to display ProcedureRangeForm1.rdlc it run successfully , but when i call again to display ProcedureRangeForm2.rdlc throw this exception

System.FormatException: 'The header contains invalid values at index 0: 'An error occurred during local report processing.;The definition of the report 'Reports\ProcedureRangeForm1.rdl' is invalid. An unexpected error occurred in Report Processing. The process cannot access the file 'hdsktzjh.err' because it is being used by another process.''

1

There are 1 answers

0
amralsaidy On

After a lot of research, I found a solution to my question:

First, I used nuget package Tmds.ExecFunction by Execute a function in a separate process as in this link But I didn't get what I wanted

And then I replaced the library AspNetCore.Reporting by ReportViewerCore.NETCore as in this link the problem solved as this code

using Microsoft.Reporting.NETCore;

[Route("api/[controller]")]
[ApiController]
public class ProcedureRangeFormsController : ControllerBase
{

    private readonly HousingDbContext _context;
    public ProcedureRangeFormsController(HousingDbContext context)
    {
        _context = context;
    }
    // GET api/values
    [HttpGet, Route("ProcedureRangeForm/{procedureRangeId}/{procedureTypeId}")]
    public IActionResult ProcedureRangeForm(string procedureRangeId, string procedureTypeId)
    {
        var reportPath = "";
        switch (procedureRangeId)
        {
            case "1":
                reportPath = "TaxHousing.Reports.ProcedureRangeForm1.rdlc";
                break;
            case "2":
                reportPath = "TaxHousing.Reports.ProcedureRangeForm2.rdlc";
                break;
            case "3":
                reportPath = "TaxHousing.Reports.ProcedureRangeForm3.rdlc";
                break;
            default:
                // code block
                break;
        }

        using var rs = Assembly.GetExecutingAssembly().GetManifestResourceStream(reportPath);
        var localReport = new Microsoft.Reporting.NETCore.LocalReport();
        localReport.LoadReportDefinition(rs);
        var reportParams1 = new[] { 
            new ReportParameter("ProcedureType", "ProcedureType1"),
            new ReportParameter("UnitCode", "UnitCode1") 
        };
        var reportParams2 = new[] { 
            new ReportParameter("ProcedureType", "ProcedureType2")
        };
        var reportParams3 = new[] {
            new ReportParameter("ProcedureType", "ProcedureType3")
        };
        byte[] file = null;
        switch (procedureRangeId)
        {
            case "1":
                localReport.SetParameters(reportParams1);
                break;
            case "2":
                localReport.SetParameters(reportParams2);
                break;
            case "3":
                localReport.SetParameters(reportParams3);
                break;
            default:
                // code block
                break;
        }

        try
        {
            file = localReport.Render("PDF");
        }
        catch (Exception e)
        {
            Console.WriteLine("{0} Exception caught.", e);
            return Content(HttpStatusCode.InternalServerError.ToString(), e.Message);
        }

        return new FileContentResult(file, "application/pdf");
    }
}