Generating a report with .net core web api and displaying it to the user with Blazor webassembly

646 views Asked by At

I just started using Devexpress and I have a little problem.

I have two projects.

I have a .NetCore Web Api project. I have a Blazor webassembly client project. My codes in the .Net core Api project are as follows. Nuget: DevExpress.AspNetCore.Reporting

Program.cs

#region Devexpress Reporting
builder.Services.AddDevExpressControls();
builder.Services.AddScoped<ReportStorageWebExtension, ReportStorage>();
#endregion

ReportFactory.cs

    namespace InventoryManagement.API.Reports
    {
        public static class ReportFactory
        {
            public static Dictionary<string, Func<XtraReport>> Reports = new Dictionary<string, Func<XtraReport>>()
            {
                ["TestReport"] = () => new Report2()
            };
        }
    }

ReportProvider.cs

    namespace InventoryManagement.API.Reports
    {
        public class ReportProvider : IReportProvider
        {
            XtraReport IReportProvider.GetReport(string id, ReportProviderContext context)
            {
                if (ReportFactory.Reports.ContainsKey(id))
                {
                    return ReportFactory.Reports[id]();
                }
                else
                    throw new DevExpress.XtraReports.Web.ClientControls.FaultException
                        (string.Format("Could not find report '{0}'.", id));
            }
        }
    }

ReportStorage.cs

    namespace InventoryManagement.API.Reports
    {
        public class ReportStorage : DevExpress.XtraReports.Web.Extensions.ReportStorageWebExtension
        {
            readonly string ReportDirectory;
            const string FileExtension = ".repx";

            public ReportStorage(IWebHostEnvironment env)
            {
                ReportDirectory = Path.Combine(env.ContentRootPath, "Reports");
                if (!Directory.Exists(ReportDirectory))
                {
                    Directory.CreateDirectory(ReportDirectory);
                }
            }

            public override bool CanSetData(string url)
            {
                return true;
            }

            public override bool IsValidUrl(string url)
            {
                return Path.GetFileName(url) == url;
            }

            public override byte[] GetData(string url)
            {
                try
                {
                    if (Directory.EnumerateFiles(ReportDirectory).Select(Path.GetFileNameWithoutExtension).Contains(url))
                    {
                        return File.ReadAllBytes(Path.Combine(ReportDirectory, url + FileExtension));
                    }
                    if (ReportFactory.Reports.ContainsKey(url))
                    {
                        using (MemoryStream ms = new MemoryStream())
                        {
                            ReportFactory.Reports[url]().SaveLayoutToXml(ms);
                            return ms.ToArray();
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new DevExpress.XtraReports.Web.ClientControls.FaultException("Could not get report data.", ex);
                }
                throw new DevExpress.XtraReports.Web.ClientControls.FaultException(string.Format("Could not find report '{0}'.", url));
            }

            public override Dictionary<string, string> GetUrls()
            {
                return Directory.GetFiles(ReportDirectory, "*" + FileExtension)
                                        .Select(Path.GetFileNameWithoutExtension)
                                        .Union(ReportFactory.Reports.Select(x => x.Key))
                                        .ToDictionary<string, string>(x => x);
            }

            public override void SetData(XtraReport report, string url)
            {
                var resolvedUrl = Path.GetFullPath(Path.Combine(ReportDirectory, url + FileExtension));
                if (!resolvedUrl.StartsWith(ReportDirectory + Path.DirectorySeparatorChar))
                {
                    throw new DevExpress.XtraReports.Web.ClientControls.FaultException("Invalid report name.");
                }
                report.SaveLayoutToXml(resolvedUrl);
            }

            public override string SetNewData(XtraReport report, string defaultUrl)
            {
                // Stores the specified report using a new URL. 
                // The IsValidUrl and CanSetData methods are never called before this method. 
                // You can validate and correct the specified URL directly in the SetNewData method implementation 
                // and return the resulting URL used to save a report in your storage.
                SetData(report, defaultUrl);
                return defaultUrl;
            }
        }
    }

ReportsController.cs

    namespace InventoryManagement.API.Controllers
    {
        public class CustomWebDocumentViewerController : WebDocumentViewerController
        {
            public CustomWebDocumentViewerController(IWebDocumentViewerMvcControllerService controllerService) : base(controllerService)
            {
            }
        }

        public class CustomReportDesignerController : ReportDesignerController
        {
            public CustomReportDesignerController(IReportDesignerMvcControllerService controllerService) : base(controllerService)
            {
            }

            [HttpPost("[action]")]
            public object GetReportDesignerModel(
                [FromForm] string reportUrl,
                [FromForm] ReportDesignerSettingsBase options,
                [FromServices] IReportDesignerClientSideModelGenerator designerClientSideModelGenerator)
            {
                Dictionary<string, object> dataSources = new Dictionary<string, object>();
                SqlDataSource ds = new SqlDataSource("NWindConnectionString");
                dataSources.Add("sqlDataSource1", ds);
                ReportDesignerModel model;
                if (string.IsNullOrEmpty(reportUrl))
                    model = designerClientSideModelGenerator.GetModel(new XtraReport(), dataSources, "/DXXRD", "/DXXRDV", "/DXXQB");
                else
                    model = designerClientSideModelGenerator.GetModel(reportUrl, dataSources, "/DXXRD", "/DXXRDV", "/DXXQB");
                model.WizardSettings.EnableSqlDataSource = true;
                model.Assign(options);
                var modelJsonScript = designerClientSideModelGenerator.GetJsonModelScript(model);
                return Content(modelJsonScript, "application/json");
            }
        }
        public class CustomQueryBuilderController : QueryBuilderController
        {
            public CustomQueryBuilderController(IQueryBuilderMvcControllerService controllerService) : base(controllerService)
            {
            }
        }
    }

For Blazor webassembly, I just installed the package "DevExpress.Blazor.Reporting.JSBasedControls.WebAssembly" and created a page called Report.razor as below. But I have no idea how to connect frontend application to server for report. I can't get the report generated by the web api somehow.

Can you help me how can I get it and show it on user side(frontend)?

I just added the following codes to the Blazor webassembly frontend side.

_imports

 @using DevExpress.Blazor.Reporting
 @using DevExpress.Blazor


    @page "/viewer"

    <DxWasmDocumentViewer ReportName="TestReport" Height="700px" Width="100%">
        <DxDocumentViewerExportSettings UseSameTab=false>
        </DxDocumentViewerExportSettings>
        <DxWasmDocumentViewerRequestOptions InvokeAction="DXXRDV">
        </DxWasmDocumentViewerRequestOptions>
    </DxWasmDocumentViewer>
1

There are 1 answers

0
e1ecringe On

From the component markup you shared, it seems that you need to specify the DxWasmDocumentViewerRequestOptions.Host property value to make it work.