0

My ASP.NET Core MVC project has several reports. To render the reports as PDF, I'm using AspNetCore.Reporting library.

This library works fine for a single report but due to some cache issues it throws an exception while generating another report. The solution I found on the internet was to run report generation as a new process but I don't know how to implement that.

I found the suggestion to use Tmds.ExecFunction to run report generation as a seperate process. But I dont know how to pass parameters to the function.

Here is my code:

  string ReportName = "invoiceDine";
            DataTable dt = new DataTable();
            dt = GetInvoiceItems(invoiceFromDb.Id);
            Dictionary<string, string> param = new Dictionary<string, string>();
            param.Add("bParam", $"{invoiceFromDb.Id}");
            param.Add("gParam", $"{salesOrderFromDb.Guests}");
            param.Add("tParam", $"{invoiceFromDb.Table.Table}");
            param.Add("dParam", $"{invoiceFromDb.Time}");
            param.Add("totalP", $"{invoiceFromDb.SubTotal}");
            param.Add("t1", $"{tax1}");
            param.Add("t2", $"{tax2}");
            param.Add("tA1", $"{tax1Amount}");
            param.Add("tA2", $"{tax2Amount}");
            param.Add("AT1", $"{totalAmountWithTax1}");
            param.Add("AT2", $"{totalAmountWithTax2}");
            param.Add("terminalParam", $"{terminalFromDb.Name}");
            param.Add("addressParam", $"{t.Address}");
            param.Add("serviceParam", "Service Charges of applicable on table of " + $"{personForServiceCharges}" + " & Above");
            var result = reportService.GenerateReport(ReportName, param, "dsInvoiceDine", dt);
            return File(result,"application/Pdf");


This is my version of the function:                                     
``` public byte[] GenerateReport(string ReportName, Dictionary<string,string> Parameters,string DataSetName,DataTable DataSource )
        {
            string guID = Guid.NewGuid().ToString().Replace("-", "");
            string fileDirPath = Assembly.GetExecutingAssembly().Location.Replace("POS_Website.dll", string.Empty);

            string ReportfullPath = Path.Join(fileDirPath, "\\Reports");
            string JsonfullPath = Path.Join(fileDirPath,"\\JsonFiles");

            string rdlcFilePath = string.Format("{0}\\{1}.rdlc", ReportfullPath, ReportName);
            string generatedFilePath = string.Format("{0}\\{1}.pdf", JsonfullPath, guID);
            string jsonDataFilePath = string.Format("{0}\\{1}.json", JsonfullPath, guID);
            File.WriteAllText(jsonDataFilePath, JsonConvert.SerializeObject(DataSource));

            FunctionExecutor.Run((string[] args) =>
            {
            // 0 : Data file path - jsonDataFilePath 
            // 1 : Filename - generatedFilePath 
            // 2 : RDLCPath - rdlcFilePath 
            ReportResult result;
           
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            Encoding.GetEncoding("windows-1252");
            LocalReport report = new LocalReport(args[2]);
            DataTable dt = JsonConvert.DeserializeObject<DataTable>(File.ReadAllText(args[0]));
            report.AddDataSource(args[3], dt);
            result = report.Execute(RenderType.Pdf, 1,Parameters);

                using (var fs = new FileStream(args[1], FileMode.Create, FileAccess.Write))
                {
                    fs.Write(result.MainStream);
                }
            }, new string[] {jsonDataFilePath, generatedFilePath, rdlcFilePath, DataSetName });

            var memory = new MemoryStream();
            using (var stream = new FileStream(Path.Combine("", generatedFilePath), FileMode.Open))
            {
                stream.CopyTo(memory);
            }

            File.Delete(generatedFilePath);
            File.Delete(jsonDataFilePath);
            memory.Position = 0;
            return memory.ToArray();
        }
                                                                        
But it throws exception "Field marshaling is not supported by ExecFunction" on line: 
 var result = reportService.GenerateReport(ReportName, param, "dsInvoiceDine", dt);
  • Here is a suggestion but how to pass parameters to the function [https://github.com/amh1979/AspNetCore.Reporting/issues/9#issuecomment-990626517] – Dawood Jamil Dec 10 '21 at 05:38
  • Which line is causing the error? Can you include all the code including the method calling this method? Also, put edits into the question. Comments mat be non-permanent. – mcalex Dec 10 '21 at 05:43
  • @mcalex Can you help me with how to move my report genration logic to console App and then run that console App from my Asp.Net core mvc app as new Process. – Dawood Jamil Dec 10 '21 at 05:55
  • I'm Stuck with the error for last two weeks. I shall be very thankful for any help. – Dawood Jamil Dec 10 '21 at 05:59
  • Are those template strings in your actual code? Stuff like: "YOUR DLL NAME", "YOUR RDLC NAME" and "YOUR SERVICE METHOD TO FETCH DATA" etc? – mcalex Dec 10 '21 at 06:12
  • Yes I have Updated my code.. It throws an exception "Field marshaling is not supported by ExecFunction". – Dawood Jamil Dec 10 '21 at 07:44
  • OK, have you had a look at [ReportViewerCore.NETCore](https://www.nuget.org/packages/ReportViewerCore.NETCore/). But this is a whole 'nother problem that requires a new/reworded question. – mcalex Dec 10 '21 at 18:58
  • ReportViewerCore.NetCore is supported by .Net Core 3.1, my project is in .Net 5 – Dawood Jamil Dec 11 '21 at 05:17
  • Are you sure? "This project is aimed at porting Microsoft Reporting Services (Report Viewer) to [.NET Core 3.1 **+**.](https://github.com/lkosson/reportviewercore/)" and [Added .NET 5 support](https://github.com/lkosson/reportviewercore/blob/master/CHANGELOG.md#1515), but your new question is probably going to get a better solution. – mcalex Dec 11 '21 at 07:31
  • I have tried it in .Net 5 it does not work. it has a dependency of .Net 3.1 core. – Dawood Jamil Dec 11 '21 at 14:24

1 Answers1

0

No Need to run report generation as a seperate process. Just Dont Pass extension as 1 in:

 var result = localReport.Execute(RenderType.Pdf, 1, param);

The Solution is:

  int ext = (int)(DateTime.Now.Ticks >> 10);
  var result = localReport.Execute(RenderType.Pdf, ext, param);