Tenant-aware applications
Refer to Tenant name for details about specifying the tenant for a Context object.
If Web Services for Microsoft Dynamics GP is running in a multitenant configuration, you should consider writing your applications that access the Dynamics GP service so that they are tenant-aware. A tenant-aware application will detect when the user has access to more than one tenant, and allow the user to select the tenant (Microsoft Dynamics GP installation) that they want to access. You use the TenantName property of the Context object for to specify the tenant to use for a web service call.
Default behavior
If you don't add tenant support to your application that accesses the Dynamics GP service, the application can still be used with a multitenant configuration. The Dynamics GP service has default behavior that will attempt to find the correct tenant to use.
The default behavior is used when you don't supply a value for the TenaneName property of the Context object. The Dynamics GP service will detect whether a multitenant environment is being used, and determine the number of tenants that the user running the web service application has access to. If the Dynamics GP service can determine that the user has access to only one tenant, that tenant will automatically be used for the web service calls. If the user doesn't have access to any tenants, or has access to two or more tenants, an exception is thrown to indicate that the Dynamics GP service could not determine the tenant to use.
Adding tenant support
To make your web service application tenant-aware, your application must do the following:
- When the application starts, it must detect that Web Services for Microsoft Dynamics GP is being used in a multitenant environment.
- If a multitenant environment is being used, the application must retrieve the list of tenants that the current user has access to.
- If the user has access to more than one tenant, the application should display a list of the available tenants and allow the user to select the tenant to use for that session of the application.
- Each call to the Dynamics GP service should use the selected tenant in the Context object that is passed with the method call.
The following illustration shows the tenant selector that is implemented in the Sales Document sample application. This modal window appears only when the user has access to more than one tenant, and must select which tenant to use.
Using code from the sample
The Sales Document sample application included with the Web Services for Microsoft Dynamics GP SDK contains an implementation of a tenant selector. You can look at the implementation to get ideas about how you could add multitenant support to your application. To use the tenant selector from the sample, use the following procedure.
Open the Sales Document sample application.
Open the folder that contains the files for the Sales Document sample. Be sure to select the version of the sample that corresponds to the endpoint type that you are using for your web service application.
Copy the tenant selector files into your project folder.
Copy the following files from the sample project to your project folder:
• TenantSelector.cs
• TenantSelector.Designer.cs
• TenatSelector.resx
Add the TenantSelector.cs file to your project.
In Visual Studio, choose to add an existing file to your project. Select the TenantSelector.cs file. It will appear in the Project Explorer.
Update the namespace for the TenantSelector.cs file.
In Visual Studio, choose to view the code for the TenantSelector.cs file. Change the namespace to match the namespace that you are using for your application.
Add the variable that will store the name of the tenant to use.
This is a string variable that must be accessible from any place in your code that you set values for the Context object. For the Sales Document sample, the variable is part of the main CustomerSalesForm.
public static string selectedTenant;
Add the helper method that will get the tenant status.
This is a private method that will query the Dynamics GP service to retrieve tenant information. If necessary, it will display the dialog box that contains the tenants that the user must choose from. This version of the helper application is written to access the legacy endpoint.
Legacy endpoint
// Find out if multiple tenants are available. If they are, allow the user // to select the tenant to use. private string getTenantConfiguration() { Tenant[] tenants; System.Collections.ArrayList tenantNames = new System.Collections.ArrayList(); TenantSelector ts; try { // Default assumption is that tenants are not being used string tenant = ""; // Create an instance of the service DynamicsGP wsDynamicsGP = new DynamicsGP(); // Be sure the default credentials are used wsDynamicsGP.UseDefaultCredentials = true; // Find out whether tenants are enabled if (wsDynamicsGP.MultitenantEnabled() == true) { // Tenants are enabled, so retrieve a list tenants = wsDynamicsGP.GetTenantList(false); // If there is more than one available tenant, then ask // the user to select one if (tenants.Length == 0) { MessageBox.Show("You do not have access to any Microsoft Dynamics GP installations. The application will close.", "Access Error", MessageBoxButtons.OK); Application.Exit(); } else if (tenants.Length == 1) { // The user has access to only one tenant, so use it tenant = tenants[0].Name; } else { // Display the list of tenants so the user can select one ts = new TenantSelector(); // Add tenant names to the list that will be displayed in // the Tenant Selector dialog foreach (Tenant t in tenants) { tenantNames.Add(t.Name); } ts.FillTenantList(tenantNames); // Show the Tenant Selector dialog ts.ShowDialog(); // Handle the response from the dialog if (ts.DialogResult == DialogResult.OK) { tenant = ts.GetTenantSelection; ts.Close(); } else { // The user clicked Cancel, so exit the application Application.Exit(); } } } return tenant; } catch (Exception err) { StringBuilder errorMessage = new StringBuilder("An error occurred attempting to retrive tenant information for the web services installation."); errorMessage.AppendLine(err.Message); MessageBox.Show(errorMessage.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return ""; } }
Add code to call the helper method.
Place this method call in a location where it will be run immediately when the application starts.
// Call the helper function to find out about the tenant configuration
selectedTenant = getTenantConfiguration();
Update the code that creates Context objects.
Find all of the places in your code that create Context objects. Update the code so that the TenantName property of the Context object is set to the value of the selectedTenant variable retrieved from the helper method.