Skip to main content
A newer version of this page is available. .

Provide Authentication to Access JSON Data

  • 8 minutes to read

This tutorial demonstrates how to bind a report to JSON data located at the endpoint that requests basic HTTP authentication.

Runtime Authentication

The JsonDataSource component has a JsonSource property that provides access to a UriJsonSource object. The JsonDataSource uses this object’s methods to retrieve JSON data from the specified URI. Implement the UriJsonSource class’ descendant that provides authentication parameters to get JSON data.

Add the Username and Password properties to your descendant:

using DevExpress.DataAccess.Json;
using System;
using System.ComponentModel;
using System.Net;
using System.Xml.Linq;
//...
    public class MyUriJsonSource : UriJsonSource {
//...
        public string Username { get; set; }

        [PasswordPropertyText(true)]
        public string Password { get; set; }
//...
    }

Override the UriJsonSource class’ methods as follows:

  • GetJsonString
    Use the specified username and password to access JSON data.

    using DevExpress.DataAccess.Json;
    using System;
    using System.ComponentModel;
    using System.Net;
    using System.Xml.Linq;
    //...
        public class MyUriJsonSource : UriJsonSource {
    //...
            public override string GetJsonString() {
                using(var client = new WebClient()) {
                    client.Credentials = new NetworkCredential(Username, Password);
                    // add a header to the request
                    // client.Headers.Add(Username, Password);
                    return client.DownloadString(Uri);
                }
            }
    //...
        }
    

    Tip

    The code snippet above demonstrates the basic HTTP authentication. You can implement token-based authentication instead.

  • SaveToXml and LoadFromXml
    Save/load the Username and Password property values to/from a report’s serialization to preview the report in the End-User Report Designer.

    using DevExpress.DataAccess.Json;
    using System;
    using System.ComponentModel;
    using System.Net;
    using System.Xml.Linq;
    //...
        public class MyUriJsonSource : UriJsonSource {
    //...
            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;
                }
            }
    //...
        }
    

    Tip

    In the code above, the SecretStorage class stores the Username and Password property values in a file. To store them in a database, cloud or another location, implement another storage.

  • Clone
    Include the Username and Password property values in the MyUriJsonSource object’s cloned copy. The End-User Report Designer uses this copy when you switch to Preview.

    using DevExpress.DataAccess.Json;
    using System;
    using System.ComponentModel;
    using System.Net;
    using System.Xml.Linq;
    //...
        public class MyUriJsonSource : UriJsonSource {
    //...
            protected override JsonSourceBase Clone() {
                var clone = new MyUriJsonSource() {
                    Uri = Uri,
                    RootElement = RootElement,
                    Username = Username,
                    Password = Password
                };
                return clone;
            }
    //...
        }
    

Implement a helper method that uses the passed URI, username, and password to create a JsonDataSource object.

using DevExpress.DataAccess.Json;
using DevExpress.DataAccess.UI.Native.Json;
using System;
using System.Windows.Forms;
using XtraReport_JsonDataSource_with_Authorization.ReportCustomization;
//...
    public static class JsonDataSourceAuthorization_Example {
        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;
        }
    }

You can now use this helper method to assign a JSON data source to a report.

private void RuntimeAuthenticationButton_Click(object sender, EventArgs e) {
    var report = new XtraReport1();
    report.DataSource = JsonDataSourceAuthorization_Example.CreateCustomJsonDataSource(
        @"http://northwind.servicestack.net/customers.json", "username1", "userPassword1");
    report.DataMember = "Customers";
    new DevExpress.XtraReports.UI.ReportDesignTool(report).ShowDesigner();
}

Add JSON Authentication to a Wizard Page

The Report Wizard and Data Source Wizard (VS, WinForms, WPF) contain the Specify JSON Data Location page. You can customize this page to allow users to specify the JSON data source’s authentication parameters.

Json-Design-Time-Authentication

The following steps describe how to add the Username and Password editors to the Specify JSON Data Location wizard page:

  1. Extend the IChooseJsonSourcePageView interface with the Username and Password properties.

    using DevExpress.DataAccess.Wizard.Views;
    //...
        public interface IMyChooseJsonSourcePageView : IChooseJsonSourcePageView {
            string Username { get; set; }
            string Password { get; set; }
        }
    
  2. Implement a custom Page View based on the ChooseJsonSourcePageView to add the Username and Password items to the page.

    public class MyChooseJsonSourcePageView : DevExpress.DataAccess.UI.Wizard.Views.ChooseJsonSourcePageView, IMyChooseJsonSourcePageView {
        //...
    }
    
  3. Implement a Page Presenter based on the ChooseJsonSourcePage<TModel> to define the page’s custom logic.
    In the Begin, Validate and Commit methods, create the MyUriJsonSource class’s instance and pass the page’s IMyChooseJsonSourcePageView.Username and IMyChooseJsonSourcePageView.Password property values as constructor parameters.

    public class MyChooseJsonSourcePage<TModel> : ChooseJsonSourcePage<TModel> where TModel : class, IJsonDataSourceModel {
        //...
        public override void Begin() {
            base.Begin();
            if(Model.JsonSource != null) {
                var myJsonSource = Model.JsonSource as MyUriJsonSource;
                if(myJsonSource != null && View is IMyChooseJsonSourcePageView) {
                    (View as IMyChooseJsonSourcePageView).Password = myJsonSource.Password;
                    (View as IMyChooseJsonSourcePageView).Username = myJsonSource.Username;
                }
            }
        }
        public override bool Validate(out string errorMessage) {
            //...
            JsonDataSource source = null;
            try {
                return AsyncHelper.DoWithWaitForm(token => {
                    source = new JsonDataSource {
                        JsonSource = new MyUriJsonSource() {
                            Uri = new Uri(View.Uri),
                            Username = (View as IMyChooseJsonSourcePageView)?.Username,
                            Password = (View as IMyChooseJsonSourcePageView)?.Password
                        }
                    };
                    token.ThrowIfCancellationRequested();
                    source.Fill();
                    Model.DataSchema = DevExpress.DataAccess.Native.Data.DataView.ConvertToDataView(source);
                    Model.JsonSchema = source.Schema;
                }, Context.WaitFormActivator, Context.CreateExceptionHandler(ExceptionHandlerKind.Loading));
            } catch(Exception e) {
                errorMessage = e.Message;
                return false;
            } finally {
                source?.Dispose();
            }
        }
        public override void Commit() {
            Model.JsonSource = new MyUriJsonSource() {
                Uri = new Uri(View.Uri),
                Username = (View as IMyChooseJsonSourcePageView)?.Username,
                Password = (View as IMyChooseJsonSourcePageView)?.Password
            };
            View.Changed -= ViewOnChanged;
        }
    }
    
  4. Implement the IWizardCustomizationService interface to register the custom Page View and Presenter.

    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;
            }
        } 
    

    In the code abode, the MyWizardCustomizationService class implements the IJsonEditorsCustomizationService interface to invoke the customized Specify JSON Data Location wizard page from the context menu.

    Json-Design-Time-Authentication

  5. Add MyWizardCustomizationService to the DesignMdiController‘s service collection.

    private void DesignTimeAuthenticationButton_Click(object sender, EventArgs e) {
        var reportDesignTool = new DevExpress.XtraReports.UI.ReportDesignTool(new DevExpress.XtraReports.UI.XtraReport());
        reportDesignTool.DesignForm.DesignMdiController.AddService(typeof(IWizardCustomizationService), new MyWizardCustomizationService());
        reportDesignTool.DesignForm.DesignMdiController.AddService(typeof(IJsonEditorsCustomizationService), new MyWizardCustomizationService());
        reportDesignTool.ShowDesigner();
    }    
    

Refer to the Wizard Customization Overview topic for more information on how to customize wizard pages.