ActiveReports 17 .NET Edition
Developers / Create Applications / Blazor WebDesigner Application / Configure and Use Shared Data Sources
In This Topic
    Configure and Use Shared Data Sources
    In This Topic

    The shared data sources contain connection properties that allow binding multiple reports to the same data. The shared data sources can be created and edited only in Standalone Designer or VS integrated designer. In WebDesigner, however, you can only reference an existing data source.

    Following are the scenarios for using shared data sources in web designer:

    The shared data source solves this problem because the report definition contains only the reference to the data source definition, which is resolved on the server-side when a report is previewed.

    Note: Shared data sources are disabled by default.

    You must create a shared data source (.rdsx) in Standalone Designer or Visual Studio Integrated Designer. See Work with Local Shared Data Sources for more information.

    The steps to use shared data sources are elaborated below. You should first create a WebDesigner in Blazor application. See Blazor Server Application topic for more information.

    1. Open the WebDesigner application.
    2. Place the shared reference, a .rdsx file, in the ‘resources’ folder of the project.
    3. In the Index.razor where web designer is initialized, use Shared property as shown in the following code to enable shared data sources.
      Index.razor
      Copy Code
      @page "/"
      @inject IJSRuntime JSRuntime
      <PageTitle>Index</PageTitle>
      <link href="_content/GrapeCity.ActiveReports.Blazor.Viewer/jsViewer.min.css" rel="stylesheet" />
      <div id="designerContainer">
          <ReportDesigner @ref="_designer" PreviewSettings=@_preview DataSettings="@_data" />
      </div>
      @code {
          private ReportDesigner _designer;  
          private DataSettings _data;
          private PreviewSettings _preview;
          public Index()
          {
              _data = new DataSettings
                  {
                      DataSets = new DataSets { CanModify = true },
                      DataSources = new DataSources
                      {
                          CanModify = true,
                          Shared = new SharedDataSourceOptions()
                          {
                              Enabled = true
                          }
                      },
                  };
              _preview = new PreviewSettings
                  {
                      CanPreview = false
                  };
          }
      }
      

      Implement the ISharedDataSourceService

    4. Create 'Implementation' folder.

    5. To the 'Implementation' folder, add ‘SharedDataSourceService.cs’ class which will contain implementation for ISharedDataSourceService.

      SharedDataSourceService.cs
      Copy Code
      public class SharedDataSourceService : ISharedDataSourceService
      {
          private DirectoryInfo _resourcesRootDirectory =
              new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "resources"));
         
          public SharedDataSourceInfo[] GetSharedDataSourceList()
          {
              return _resourcesRootDirectory
                  .EnumerateFiles("*.rdsx")
                  .Select(x =>
                  {
                      var dataSource = GetDataSource(x.Name);
                      return new SharedDataSourceInfo()
                      {
                          Name = x.Name,
                          Type = dataSource.ConnectionProperties.DataProvider
                      };
                  }).ToArray();
          }
          public DataSource GetDataSource(string name)
          {
              return DataSourceTools.LoadSharedDataSource(Path.Combine(_resourcesRootDirectory.FullName, name));
          }
      }
      

      Implement the IResourcesService

    6. Add 'ResourceService.cs'  to the 'Implementation' folder to add implementation for IResourcesService.

      ResourceService.cs
      Copy Code
      public class ResourceService: IResourcesService
      {
          private readonly Dictionary<string, Report> _tempStorage = new Dictionary<string, Report>();
          private readonly Dictionary<string, SectionReport> _tempSectionStorage = new Dictionary<string, SectionReport>();
          private readonly ResourceLocator _resourceLocator;
         
          private DirectoryInfo _resourcesRootDirectory =
              new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "resources"+ Path.DirectorySeparatorChar));
         
          public ResourceService()
          {
              _resourceLocator = new DefaultResourceLocator(new Uri(_resourcesRootDirectory.FullName));
          }   
          public Report GetReport(string id)
          {
              if (_tempStorage.TryGetValue(id, out var tempReport))
              {
                  tempReport.Site = new ReportSite(_resourceLocator);
                  return tempReport;
              }
             
              var reportFullPath = Path.Combine(_resourcesRootDirectory.FullName, id);
              var reportXml = File.ReadAllBytes(reportFullPath);
              var report = ReportConverter.FromXML(reportXml);
              report.Site = new ReportSite(_resourceLocator);
                 
              return report;
          }
          public IReportInfo[] GetReportsList()
          {
              return _resourcesRootDirectory
                  .EnumerateFiles("*.rdlx")
                  .Select(x =>
                  {
                      var reportXml = File.ReadAllBytes(x.FullName);
                      var report = ReportConverter.FromXML(reportXml);
                      return new ReportInfo
                      {
                          Id = x.Name,
                          Name = x.Name,
                          Type = report.IsFixedPageReport ? "FPL" : "CPL"
                      };
                  }).Cast<IReportInfo>().ToArray();
          }
          public string SaveReport(string name, Report report, bool isTemporary = false)
          {
              if (isTemporary)
              {
                  var tempName = Guid.NewGuid() + ".rdlx";
                  _tempStorage.Add(tempName, report);
                  return tempName;
              }
             
              var reportFullPath = Path.Combine(_resourcesRootDirectory.FullName, name);
              report.Name = name;
              var reportXml = ReportConverter.ToXml(report);
              File.WriteAllBytes(reportFullPath, reportXml);
              return name;
          }
          public string UpdateReport(string id, Report report)
          {
              return SaveReport(id, report, false);
          }
          public void DeleteReport(string id)
          {
              if (_tempStorage.ContainsKey(id))
              {
                  _tempStorage.Remove(id);
                  return;
              }
             
              var reportFullPath = Path.Combine(_resourcesRootDirectory.FullName, id);
             
              if(File.Exists(reportFullPath))
                  File.Delete(reportFullPath);
          }
          public Uri GetBaseUri()
          {
              return _resourceLocator.BaseUri;
          }
          public Theme GetTheme(string id)
          {
              throw new NotImplementedException();
          }
          public IThemeInfo[] GetThemesList()
          {
              return Array.Empty<IThemeInfo>();
          }
          public byte[] GetImage(string id, out string mimeType)
          {
              throw new NotImplementedException();
          }
          public IImageInfo[] GetImagesList()
          {
              return Array.Empty<IImageInfo>();
          }
      }
      public class ReportInfo : IReportInfo
      {
          public string Id { get; set; }
          public string Name { get; set; }
          public string Type { get; set; }
      }
      class ReportSite : ISite
      {
          private readonly ResourceLocator _resourceLocator;
          public ReportSite(ResourceLocator resourceLocator) =>
              _resourceLocator = resourceLocator;
          public object GetService(Type serviceType) =>
              serviceType == typeof(ResourceLocator) ? _resourceLocator : null;
          public IComponent Component => null;
          public IContainer Container => null;
          public bool DesignMode => false;
          public string Name { get; set; }
      }
      

      Configure and register services

    7. Open Program.cs and update the file as shown below. The Startup.cs file does the following:

      1. configures the services and middleware used by the application
      2. registers the 'ISharedDataSourceService' and 'IResourcesService' as singleton services
      3. adds reporting and designer services
      4. sets the path to the GrapeCity.ActiveReports.config file where the SQLite provider is added
      5. configures the reporting and designer middleware
      6. serves static files
                       
        Program.cs
        Copy Code
        using BlazorDesignerServer.Implementation;
        using BlazorDesignerServer.Services;
        using GrapeCity.ActiveReports.Aspnetcore.Designer;
        using GrapeCity.ActiveReports.Aspnetcore.Viewer;
        using Microsoft.AspNetCore.SignalR;
        using System.Text;
        using GrapeCity.ActiveReports.Aspnetcore.Designer.Services;
        using IDataSetsService = BlazorDesignerServer.Services.IDataSetsService;
        var builder = WebApplication.CreateBuilder(args);
        var ResourcesRootDirectory =
            new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "resources"));
        var TemplatesRootDirectory =
            new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "templates"));
        var DataSetsRootDirectory =
            new DirectoryInfo(Path.Combine(Directory.GetCurrentDirectory(), "datasets"));
        Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
        // Add services to the container.
        builder.Services.AddReporting();
        builder.Services.AddDesigner();
        builder.Services.AddRazorPages().AddJsonOptions(options => options.JsonSerializerOptions.PropertyNamingPolicy = null);
        builder.Services.AddServerSideBlazor();
        builder.Services.Configure<HubOptions>(options =>
        {
            options.MaximumReceiveMessageSize = 524288000; //500MB
        });
        builder.Services.AddSingleton<IResourcesService, ResourceService>();
        builder.Services.AddSingleton<ISharedDataSourceService, SharedDataSourceService>();
        builder.Services.AddSingleton<ITemplatesService>(new FileSystemTemplates(TemplatesRootDirectory));
        builder.Services.AddSingleton<IDataSetsService>(new FileSystemDataSets(DataSetsRootDirectory));
        builder.Services.AddCors();
        var app = builder.Build();
        // Configure the HTTP request pipeline.
        if (!app.Environment.IsDevelopment())
        {
            app.UseExceptionHandler("/Error");
        }
        // For use as a server for BlazorWebAssembly
        app.UseCors(cors => cors.SetIsOriginAllowed(origin => new Uri(origin).Host == "localhost")
            .AllowAnyMethod()
            .AllowAnyHeader()
            .AllowCredentials()
            .WithExposedHeaders("Content-Disposition"));
        app.UseReporting(config =>
        {
            config.UseCustomStore(id =>
            {
                var resourcesService = app.Services.GetRequiredService<IResourcesService>();
                return resourcesService.GetReport(id);
            });
        });
        app.UseDesigner(config =>
            {
                var sharedDataSourceService = app.Services.GetRequiredService<ISharedDataSourceService>();
                var resourcesService = app.Services.GetRequiredService<IResourcesService>();
                config.UseCustomStore(resourcesService);
                config.UseSharedDataSources(sharedDataSourceService);
            });
        app.UseStaticFiles();
        app.UseRouting();
        app.MapControllers();
        app.MapBlazorHub();
        app.MapFallbackToPage("/_Host");
        app.Run();
        
    8. Run the application.
    9. Go to the Data tab to add the data source.

    10. In the Data Source Editor dialog, select ‘Shared Reference’ as Provider and then the ‘.rdsx’ file as Reference.Shared Reference configuration in Data Source Editor dialog