Ticket T473885
Visible to All Users

How to: Provide Credentials for the Dashboards Module when Using External Data Sources

created 8 years ago (modified 8 years ago)

I have a xaf application which is used to analyse large amounts of data over 500,000 records.  My client wants to use the new dashboard module to visualise the data. I have created a series of stored procedures on the server to reduce the query times, which works fine. The issue arises when we attempt to save the dashboard. After saving the dashboard an error is thrown see attached image.

a video of the error can be seen here: http://screencast-o-matic.com/watch/cbVq2tQHab

Steps to reproduce

  1. Create a new dashboard and select Database as the source type
  2. Specify Connection credentials
  3. Select Stored Procedure or use Query builder
  4. Design Dashboard
  5. Save Dashboard (at this point the connection string looks to be rewritten and throws the error)

Answers approved by DevExpress Support

created 8 years ago (modified 2 years ago)

Update:

Starting with v18.2 you are able to manage this behavior by using the SqlWizardSettings.DatabaseCredentialsSavingBehavior property as shown in the T742223: Dashboards - XAF doesn't allow storing credentials in Dashboard's XML content thread.

=====================================

Hello Patrick,

We've intentionally disabled saving credentials for external datasources inside dashboards because a control in the Web Dashboards module (ASPxDashboard) doesn't support it due to security reasons (they are processed on the client side).
You need to manually provide credentials for such datasources.

Scenario:
In this example, it is demonstrated how to provide credentials to the Shipping Countries dashboard in our XCRM demo.

Steps to implement
1. In the YourSolution.Module  project, add a helper class that provides credentials:

C#
using System.Data.SqlClient; using DevExpress.DataAccess.ConnectionParameters; using DevExpress.ExpressApp; ... public static class SqlDashboardHelper { public static void SetupSqlParameters(MsSqlConnectionParameters connectionParameters) { connectionParameters.ServerName = "server"; connectionParameters.DatabaseName = "database"; connectionParameters.AuthorizationType = MsSqlAuthorizationType.SqlServer; connectionParameters.UserName = "user"; connectionParameters.Password = "password"; } }

2. To provide credentials for the ASP.NET WebForms app, add the following controller to  the YourSolution.Module.Web\Controllers  folder:

C#
using DevExpress.DashboardWeb; using DevExpress.ExpressApp; using DevExpress.ExpressApp.Dashboards.Web; using DevExpress.Persistent.Base; using DevExpress.DataAccess.ConnectionParameters; ... public class WebDashboardCustomizeController : ViewController<DetailView> { public WebDashboardCustomizeController() { TargetObjectType = typeof(IDashboardData); } protected override void OnActivated() { base.OnActivated(); WebDashboardViewerViewItem dashboardViewerViewItem = View.FindItem("DashboardViewer") as WebDashboardViewerViewItem; if(dashboardViewerViewItem != null) { dashboardViewerViewItem.ControlCreated += DashboardViewerViewItem_ControlCreated; } } private void DashboardViewerViewItem_ControlCreated(object sender, EventArgs e) { WebDashboardViewerViewItem dashboardViewerViewItem = sender as WebDashboardViewerViewItem; dashboardViewerViewItem.DashboardDesigner.ConfigureDataConnection += DashboardDesigner_ConfigureDataConnection; //You can prevent setting direct Database connections using the following commented code in versions prior to 16.2.6. In the next versions, use the DashboardsModule.HideDirectDataSourceConnections property. //dashboardViewerViewItem.DashboardDesigner.ClientSideEvents.BeforeRender = "function onBeforeRender(s, e) { s.dashboardDesigner.unregisterExtension('dxdde-data-source-wizard'); }"; } private void DashboardDesigner_ConfigureDataConnection(object sender, ConfigureDataConnectionWebEventArgs e) { if(e.ConnectionName == "YOUR_CONNECTION_NAME") { e.ConnectionParameters = new MsSqlConnectionParameters(); SqlDashboardHelper.SetupSqlParameters((MsSqlConnectionParameters)e.ConnectionParameters); } } protected override void OnDeactivated() { WebDashboardViewerViewItem dashboardViewerViewItem = View.FindItem("DashboardViewer") as WebDashboardViewerViewItem; if(dashboardViewerViewItem != null) { dashboardViewerViewItem.ControlCreated -= DashboardViewerViewItem_ControlCreated; } base.OnDeactivated(); } }

Optionally, you can also prevent setting direct Database connections in the ASP.NET application using the following code in InitializeComponent method in YourSolution.Web\WebApplication.cs file:

C#
dashboardsModule.HideDirectDataSourceConnections = true;

Or you can change the value of this property with our Application Designer.

Note: to allow users to select a Dashboard Data Source's connecting string, use the following solution: Web - The "A connection string provider is not configured" error occurs after using the "Create data source…" command.

3. To provide credentials for the WinForms app, add the following controller to theYourSolution.Module.Win\Controllers  folder:

C#
using DevExpress.DashboardCommon; using DevExpress.DataAccess.ConnectionParameters; using DevExpress.ExpressApp; using DevExpress.ExpressApp.Dashboards.Win; using DevExpress.Persistent.Base; ... public class WinDashboardCustomizeController : ViewController<DetailView> { WinShowDashboardDesignerController desingerController; WinDashboardViewerViewItem dashboardViewerViewItem; public WinDashboardCustomizeController() { TargetObjectType = typeof(IDashboardData); } protected override void OnActivated() { base.OnActivated(); dashboardViewerViewItem = View.FindItem("DashboardViewer") as WinDashboardViewerViewItem; if(dashboardViewerViewItem != null) { dashboardViewerViewItem.ControlCreated += DashboardViewerViewItem_ControlCreated; } desingerController = Frame.GetController<WinShowDashboardDesignerController>(); if(desingerController != null) { desingerController.DashboardDesignerManager.DashboardDesignerCreated += DashboardDesignerManager_DashboardDesignerCreated; } } protected override void OnDeactivated() { if(dashboardViewerViewItem != null) { dashboardViewerViewItem.ControlCreated -= DashboardViewerViewItem_ControlCreated; } if(desingerController != null) { desingerController.DashboardDesignerManager.DashboardDesignerCreated -= DashboardDesignerManager_DashboardDesignerCreated; } base.OnDeactivated(); } private void DashboardDesignerManager_DashboardDesignerCreated(object sender, DashboardDesignerShownEventArgs e) { e.DashboardDesigner.ConfigureDataConnection += DashboardDesigner_ConfigureDataConnection; } private void DashboardDesigner_ConfigureDataConnection(object sender, DashboardConfigureDataConnectionEventArgs e) { ConfigureDataConnection(e); } private void DashboardViewerViewItem_ControlCreated(object sender, EventArgs e) { WinDashboardViewerViewItem dashboardViewerViewItem = View.FindItem("DashboardViewer") as WinDashboardViewerViewItem; if(dashboardViewerViewItem != null) { dashboardViewerViewItem.Viewer.ConfigureDataConnection += Viewer_ConfigureDataConnection; } } private void Viewer_ConfigureDataConnection(object sender, DashboardConfigureDataConnectionEventArgs e) { ConfigureDataConnection(e); } private void ConfigureDataConnection(DashboardConfigureDataConnectionEventArgs e) { if(e.ConnectionName == "YOUR_CONNECTION_NAME") { e.ConnectionParameters = new MsSqlConnectionParameters(); SqlDashboardHelper.SetupSqlParameters((MsSqlConnectionParameters)e.ConnectionParameters); } } }

Also, if you don't plan to view these dashboards on the Web, you can enable saving credentials in a database in the following manner (you need to add this to YourSolution.Module.Win\Controllers  folder):

C#
using DevExpress.DashboardCommon; using DevExpress.ExpressApp; using DevExpress.ExpressApp.Dashboards.Win; using DevExpress.Persistent.Base; ... public class WinDashboardController : ViewController { WinShowDashboardDesignerController winShowDashboardDesignerController; protected override void OnActivated() { base.OnActivated(); winShowDashboardDesignerController = Frame.GetController<WinShowDashboardDesignerController>(); if (winShowDashboardDesignerController != null) { winShowDashboardDesignerController.DashboardDesignerManager = new CustomDashboardDesignerManager(Application); } } public WinDashboardController() { TargetObjectType = typeof(IDashboardData); } } public class CustomDashboardDesignerManager : DashboardDesignerManager { protected override void ProcessDashboardBeforeSaving(Dashboard dashboard) { } public CustomDashboardDesignerManager(XafApplication application) : base(application) { } }

UPDATE:
Starting with v17.1, we hide the following page in the Data Source Wizard (you can learn more about it in a breaking change).

If you want to show it, replace CustomDashboardDesignerManager in the code above with the following:

C#
public class CustomDashboardDesignerManager : DashboardDesignerManager { protected override void OnDesignerShown(DashboardDesigner dashboardDesigner) { dashboardDesigner.DataSourceWizard.SqlWizardSettings.DatabaseCredentialsSavingBehavior = DevExpress.DataAccess.Wizard.SensitiveInfoSavingBehavior.Prompt; base.OnDesignerShown(dashboardDesigner); } protected override void ProcessDashboardBeforeSaving(Dashboard dashboard) { } public CustomDashboardDesignerManager(XafApplication application) : base(application) { } }

This functionality is demonstrated in our XCRM demo and you can find the full source code of this solution in the  C:\Users\Public\Documents\DevExpress Demos <Version>\Components\eXpressApp Framework\XCRM\CS  folder.

Thanks,
Alexander.

    Show previous comments (18)
    DevExpress Support Team 7 years ago

      Hello,

      I've created a separate ticket on your behalf, because we need to better understand our requirements: T611057: Clarification regarding the example provided in the T473885 ticket).  I will reply in that ticket soon.

      GS GS
      Genesis Supsup 3 years ago

        How do I set this up in XAF Blazor?

        Georgiy G (DevExpress) 3 years ago

          Hello,

          To set this up in XAF Blazor applications, customize the Dashboard Configurator. During the dashboard configurator setup, supply your connection strings (for example, by setting a connection strings provider) and subscribe to the DashboardConfigurator.ConfigureDataConnection event. Use this event handler to customize connection parameters. The following example shows how to specify credentials for the "YOUR_CONNECTION_NAME" connection:

          1. Specify your connection strings in the DXApplication.Blazor.Server/appsettings.json file:

            JSON
            "ConnectionStrings": { "YOUR_CONNECTION_NAME": "Pooling=false;Data Source=(localdb)\\mssqllocaldb;Initial Catalog=DXApplication;" },
          2. Create a  DXApplication.Blazor.Server/Services/CustomDashboardConfigurator.cs file and define your custom dashboard configurator in it:

            C#
            using DevExpress.DashboardAspNetCore; using DevExpress.DataAccess.ConnectionParameters; using DevExpress.ExpressApp.Dashboards.Blazor.Services; using Microsoft.Extensions.Configuration; // ... public class CustomDashboardConfigurator : BlazorDashboardConfigurator {     private readonly IConfiguration configuration; public CustomDashboardConfigurator(IConfiguration configuration) { this.configuration = configuration; } public void Setup() { SetConnectionStringsProvider(new DashboardConnectionStringsProvider(configuration)); ConfigureDataConnection += CustomDashboardConfigurator_ConfigureDataConnection; } private void CustomDashboardConfigurator_ConfigureDataConnection(object sender, DevExpress.DashboardWeb.ConfigureDataConnectionWebEventArgs e) { if(e.ConnectionName == "YOUR_CONNECTION_NAME") { var connectionParameters = new MsSqlConnectionParameters(); SetupSqlParameters(connectionParameters); e.ConnectionParameters = connectionParameters; } } private void SetupSqlParameters(MsSqlConnectionParameters connectionParameters) { connectionParameters.ServerName = "server"; connectionParameters.DatabaseName = "database"; connectionParameters.AuthorizationType = MsSqlAuthorizationType.SqlServer; connectionParameters.UserName = "user"; connectionParameters.Password = "password"; } }
          3. Register your custom dashboard configurator to be used instead of the default BlazorDashboardConfigurator in DXApplication.Blazor.Server/Startup.cs:

            C#
            using DevExpress.ExpressApp.Dashboards.Blazor; using DevExpress.ExpressApp.Dashboards.Blazor.Services; using DevExpress.DashboardAspNetCore; // ... public class Startup { // ... public void ConfigureServices(IServiceCollection services) { // ... services.AddScoped<BlazorDashboardConfigurator, CustomDashboardConfigurator>(); services.AddXafDashboards((configurator, services) => { ((CustomDashboardConfigurator)configurator).Setup(); }); } // ... }

          Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

          Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.