Reporting - JsonDataSource Updates

Reporting Team Blog
04 April 2019

As expressed in your feedback, token-based authentication functionality is crucial for JsonDataSource usage. This post describes how to implement this feature in v18.2 and then introduces our built-in implementation to be released with v19.1.

Implement Token-Based Authentication in v18.2

This section will cover two situations in which you might need this functionality:

  • You are a report developer and want to bind a report to JSON data at runtime.
  • You want to allow end-users to set up a connection using the Report Designer.

Bind to JSON Data at Runtime

First, create a UriJsonSource descendant and override the GetJsonString method, which downloads JSON data from the web service. Also, create two properties to store the user name and password:

 
public class MyUriJsonSource : UriJsonSource {
    public string Username { get; set; }
    [PasswordPropertyText(true)]
    public string Password { get; set; }
    public override string GetJsonString() {
        using(var client = new WebClient()) {
            client.Credentials = new NetworkCredential(Username, Password);
            return client.DownloadString(Uri);
        }
    }
…
}

Important note: The code snippet above implements basic HTTP authentication. You can modify it to enable token-based authentication. You can also rename or replace the properties that store login credentials:

public override string GetJsonString() {
       using(var client = new WebClient()) {
           client.Credentials = new NetworkCredential(Username, Password);
           // add header to request
           //client.Headers.Add(HeaderName, HeaderValue);
           return client.DownloadString(Uri);
       }
}

Define a static class that will create a JsonDataSource instance:

public static class MyJsonDataSourceHelper {
    public static JsonDataSource CreateCustomJsonDataSource(string uri, string username, string password) {
        var jsonDatasource = new JsonDataSource() {
            Name = "jsonDataSource",
            JsonSource = new MyUriJsonSource() {
                Uri = new Uri(uri),
                Username = username,
                Password = password
            }
        };
        return jsonDatasource;
    }
}

When designing a report, you can either use Embedded Fields (Mail Merge) or create report controls at runtime. Bind the report to data as shown below to see the result:

var report = CreateReport();
report.DataSource = MyJsonDataSourceHelper.CreateCustomJsonDataSource(
    @"http://northwind.servicestack.net/customers.json", "userName1", "userPassword1");
report.DataMember = "Customers";
new DevExpress.XtraReports.UI.ReportPrintTool(report).ShowPreview();

The complete implementation code is available on GitHub.

Modify End-User Report Designer

UI modification involves a few steps:

The following code showsa basic IWizardCustomizationService implementation. (The complete source code is available on GitHub.)

public class MyWizardCustomizationService : IWizardCustomizationService, 
    IJsonEditorsCustomizationService {
  public void CustomizeDataSourceWizard(IWizardCustomization<XtraReportModel> tool) 
  {  
    tool.RegisterPage<ChooseJsonSourcePage<XtraReportModel>, 
      MyChooseJsonSourcePage<XtraReportModel>>();
    tool.RegisterPageView<IChooseJsonSourcePageView, MyChooseJsonSourcePageView>();
  }

  public void CustomizeReportWizard(IWizardCustomization<XtraReportModel> tool) 
  {
    tool.RegisterPage<ChooseJsonSourcePage<XtraReportModel>, 
      MyChooseJsonSourcePage<XtraReportModel>>();
    tool.RegisterPageView<IChooseJsonSourcePageView, MyChooseJsonSourcePageView>();
  }

  public void CustomizeWizard(JsonEditorId editor, 
    IWizardCustomization<JsonDataSourceModel> tool) 
  {
    tool.RegisterPage<ChooseJsonSourcePage<JsonDataSourceModel>, 
      MyChooseJsonSourcePage<JsonDataSourceModel>>();
    tool.RegisterPageView<IChooseJsonSourcePageView, MyChooseJsonSourcePageView>();
  }

  public bool TryCreateDataSource(IDataSourceModel model, out object dataSource, 
    out string dataMember) 
  {
    dataSource = null;
    dataMember = model?.DataMember;
    return false;
  }

  public bool TryCreateReport(IDesignerHost designerHost, XtraReportModel model, 
    object dataSource, string dataMember) 
  {
    return false;
  }
}

As you might have noticed, the code above implements the IJsonEditorsCustomizationService interface. This is required if you want to enable custom wizard pages when end-users edit existing JsonDataSource objects:


Next, implement a UriJsonSource descendant as discussed in the previous section.

When end-users switch to the Preview tab, the DevExpress Reporting engine serializes the report layout. To add the new UserName and Password properties into serialized data, override the SaveToXml / LoadFromXml methods as shown in the following code:

protected override void SaveToXml(XElement connection) {
    base.SaveToXml(connection);
    MySecretStorage.SecretStorage.Instance.SaveCredentials(Uri.Authority, 
new Tuple<string, string>(Username, Password));
}
protected override void LoadFromXml(XElement connection) {
    base.LoadFromXml(connection);
    var cred = MySecretStorage.SecretStorage.Instance.GetCredentials(Uri.Authority);
    if(cred != null) {
        Username = cred.Item1;
        Password = cred.Item2;
    }
}

The sample above uses a separate file to store property values. You can customize this code to meet your requirements.

Once the wizard is complete, the created data source object is copied from the wizard to the internal report model. A similar operation is carried out when you switch to the Preview tab in the End-User Report Designer. The Clone method manages this behavior - which you can override as follows:

protected override JsonSourceBase Clone() {
    var clone = new MyUriJsonSource() {
        Uri = Uri,
        RootElement = RootElement,
        Username = Username,
        Password = Password
    };
    return clone;
}

Once all steps have been completed, the Report Designer will allow end-users to connect to the required data sources.

Json Data Source - Authentication Workaround

Authentication Enhancements in v19.1

The manual implementation described above will not be required once we ship v19.1 After you choose the Web Service Endpoint (URI) option in the wizard, you’ll see the following screen:

Json Data Source - New Authentication Options

We provide three authentication options: Basic HTTP Authentication, Header Parameters and Query Parameters. The last option allows you to specify custom query string values to be passed with a web service request.

Your Feedback Counts

Let us know whether your use cases for such data sources are fully supported by our v19.1 implementation. We received a request to embed a predefined header parameters set into this wizard screen. We are also considering the capability to map report parameters to JsonDataSource request parameters. We would love to learn more about your needs.

Please take a moment to cast your vote in the survey below.

Free DevExpress Products - Get Your Copy Today

The following free DevExpress product offers remain available. Should you have any questions about the free offers below, please submit a ticket via the DevExpress Support Center at your convenience. We'll be happy to follow-up.
No Comments

Please login or register to post comments.