Angular.Web.Viewer.Net.Core.CustomInstanceResolver

2 posts, 0 answers
  1. Mark
    Mark avatar
    2 posts
    Member since:
    Jan 2020

    Posted 14 Feb Link to this post

    We decided to purchase telerik reporting based on the superior angular web viewer, report designer, and exporting features we found. I had some pretty solid requirements that i had to follow. One of which was using our own custom filtering controls, look, and fill. 

    I also wanted to use the instanceReportSource methodology and filter my data and attach to the datasource on the report based on each reload of the web viewer.

    We used the report designer inside of visual studio to do all of our design work. 

     

    So with that said i had to do a couple of things, to get our custom filtering to work through angular web viewer.

    1. On report source "report" parameter i had to JSON.stringify a model that contained any filter changes and the name of the report.

      getReportSource() {
            this.filter.Report = 'Company.Product.Domain.FinishedGoodsTransactionHistory.Reports.TransactionHistory';
            return JSON.stringify(this.filter);
        }

    2. I then needed to build a custom resolver, part of implementing the IReportResolver telerik interface is the "resolve(string report) method", this method is called 

  2. Mark
    Mark avatar
    2 posts
    Member since:
    Jan 2020

    Posted 14 Feb in reply to Mark Link to this post

    3 times.  code for custom report resolver i used.

     public class CompanyCustomReportResolver : IReportResolver
        {
            private static List<CompanyReportDefinitionBase> _reportList = new List<CompanyReportDefinitionBase>();

            private string _currentFilter = string.Empty;

            private string _currentUser = string.Empty;

            private ReportSource _currentReportSource;

            public CompanyCustomReportResolver(Action<List<CompanyCustomReportDefinitionBase>> reports)
            {
                reports(_reportList);
            }
            
            public ReportSource Resolve(string payload)
            {
               
                if ( DoesPayloadDoNotMatchCurrentPayload(payload,_currentFilter)  )
                {
                    var report = GetReportFromPayloadJsonString(payload);
                    var reportDefinition = _reportList.Single(x => x.CanProcess(report));
                    _currentReportSource = reportDefinition.BuildReport(payload);
                    _currentFilter = payload;
                    _currentUser = user;
                }

                return _currentReportSource;
            }


            private static bool DoesPayloadDoNotMatchCurrentPayload(string payload, string currentPayload)
            {
                return payload != currentPayload;
            }
          

            private static string GetReportFromPayloadJsonString(string payload)
            {
                try
                {
                    var payloadObj = JsonConvert.DeserializeObject<ReportModelBase>(payload);
                    return payloadObj.Report;
                }
                catch (Exception ex)
                {
                    throw new CustomException("Exception getting report name from report json");
                }
            }
        }

    ... i would implement each of my reports based on the abstract base class like so..

     public class FinishedGoodsTransactionHistoryReport : CompanyReportDefinitionBase
        {
            public override bool CanProcess(string report)
            {
               return report == "Company.Product.Domain.FinishedGoodsTransactionHistory.Reports.TransactionHistory";
            }

            public override ReportSource BuildReport(string filter)
            {
                var filterObj = JsonConvert.DeserializeObject<FinishedGoodTransactionHistoryFilter>(filter);
                var service = Ioc.Resolve<IFinishedGoodTransactionHistoryService>();
                var instanceReportSource = new InstanceReportSource();
                var reportInstance = new TransactionHistoryReport();
                AppendLogoToReport(reportInstance.logo);
                reportInstance.DataSource = service.GetReport(filterObj);
                instanceReportSource.ReportDocument = reportInstance;
                return instanceReportSource;
            }
        }

    then using the dependency injection that was in the aspnetcore examples from the telerik site, with the exception of using Ninject i hooked it up in startup.cs. like so...

     

      private static void RegisterTelerikReportServiceConfiguration(IKernel kernel)
            {
                kernel.Bind<IReportServiceConfiguration>().ToMethod(x => new ReportServiceConfiguration
                {
                    ReportResolver = new CompanyCustomReportResolver(config =>
                    {
                        config.Add(new FinishedGoodsTransactionHistoryReport());
                        config.Add(new FinishedGoodsInventoryTransactionUpdateReport());
                        config.Add(new FinishedGoodsTransactionHistorySummaryReport());
                    }), 
                    
                    HostAppId = $"ProductName{Guid.NewGuid()}",
                    Storage = new FileStorage()
                }).InSingletonScope();
            }

    long story short, this got me where i needed to go and the support team was great at helping me get to this solution. 

     

Back to Top