Skip to Content
Mobile

Afaria API 204 - Build Your Own Self Service Portal - User Self Service (Apply Policies/Lock/Unlock/Wipe/Delete)

Tags:

Introduction

This is the fourth in a series of documents on creating your own Enrollment Portal or End-User Self-Service portal. The focus of this document is applying policies, locking/unlocking devices, deleting devices and getting a list of running servers. It is meant as a continuation of our previous efforts in Afaria API 101, Afaria API 201, Afaria API 202 and Afaria API 203, and assumes completion of those sections. Best coding practices are not necessarily followed to allow for clarity in the instruction of use of the Afaria API.

Requirements & Assumptions

  • SAP Afaria 7.0 SP5
  • Microsoft Visual Studio (examples in Visual Studio 2013)
  • Afaria API service account user information
  • Experience programming with .NET based languages (examples in C#)
  • Previously reviewed prior documents in this series

Table of Contents

Sending a Notification

All of the changes made in steps in this section will occur in the AfariaHelper class. SendCommandNotificationV002 is used instead of SendCommandNotification because SendCommandNotification will not work with newer command notification types (and is primarily included for backwards compatibility), whereas SendCommandNotificationV002 will continue to work with newer notification types and future enhancements.

  1. Add a service reference to the Outbound service, as outlined in Afaria API 101, and name it AfariaOutbound.
  2. Add a property named svcOutbound for the AfariaOutbound.OutboundServiceClient.
  3. Add a public enum named DeviceActions, and expose the actions that you wish to expose on the portal. Set each enumeration value equal to the equivalent option of the Outbound service's RemoteCommand enum.

    public enum DeviceAction { ApplyPolicies = AfariaOutbound.RemoteCommand.ApplyPolicies

                              , Lock = AfariaOutbound.RemoteCommand.Lock

                              , Unlock = AfariaOutbound.RemoteCommand.Unlock

                              , RemoveControl = AfariaOutbound.RemoteCommand.RemoveControl

                              , WipeAll = AfariaOutbound.RemoteCommand.WipeAll

                              , WipeAllAndBlockExchangeActiveSync = AfariaOutbound.RemoteCommand.WipeAllAndBlockExchangeActiveSync

                              , UserLock = AfariaOutbound.RemoteCommand.UserLock};

  4. Add a method named initOutboundService which takes no parameters and returns void.
    1. Copy initDevicesService and make the necessary modifications so that initOutboundService will initiate the svcOutbound property from step 2.
  5. Add a methond named isOutboundServiceOperable which takes no parameters and returns bool.
    1. Copy isDevicesServiceOperable and make the necessary modifications so that isOutboundServiceOperable will assure that the Outbound service is available, will attempt to initialize svcOutbound if not, and return true/false based on the state of the svcOutbound.
  6. Add a method named notifyDevice that takes parameters of a string for the Device ID and a DeviceAction enum from step 3.
    1. Check if the deviceID appears to be a valid device GUID by calling Guid.TryParse and check if the Outbound service is available by calling isOutboundServiceOperable. Do nothing if either of these fail.
    2. Call setServerID (this method will be created in the following section and takes no parameters). Since the notifyDevice method will cause the sending of a notification, it is necessary to specify to the API which Afaria Server should send the notification (normally the Master server).
    3. Create a new AfariaOutbound.ClientSpecifier object.
    4. Set the ClientSpecifier.IdType to AfariaOutbound.IdType.ClientGuid.
    5. Set the ClientSpecifier.Value to the deviceID parameter.
    6. Create a new AfariaOutbound.RemoteCommandBase object named remoteCommand.
    7. Add a switch on the DeviceAction parameter.
      1. For each of the DeviceAction types in the enumeration, set the remoteCommand object to a new instance of the RemoteCommandXXXXXXXX type (eg, for DeviceAction.Lock, set remoteCommand to a new AfariaOutbound.RemotecommandLock.
    8. Call SendCommandNotificationV002 on the Outbound service, and pass parameters of the remoteCommand object, a AfariaOutbound.ClientSpecifier array containing only the client specifier created in step 3 above and a boolean. The boolean value represents whether the API should return a tracking value, which can later be passed to the Outbound service's GetSendStatus call in order to get the success/failure of the outbound notification(s) and the progress if multiple devices were specified in the API call.

      public void notifyDevice(string deviceID, DeviceAction command)

      {

        Guid temp;

        if (Guid.TryParse(deviceID, out temp) && isOutboundServiceOperable())

        {

          setServerID();

          AfariaOutbound.ClientSpecifier client = new AfariaOutbound.ClientSpecifier();

          client.IdType = AfariaOutbound.IdType.ClientGuid;

          client.Value = deviceID;

          AfariaOutbound.RemoteCommandBase remoteCommand;

          switch (command)

          {

            case DeviceAction.UserLock:

              remoteCommand = new AfariaOutbound.RemoteCommandUserLock();

              break;

            case DeviceAction.Lock:

              remoteCommand = new AfariaOutbound.RemoteCommandLock();

              break;

            case DeviceAction.Unlock:

              remoteCommand = new AfariaOutbound.RemoteCommandUnlock();

              break;

            case DeviceAction.RemoveControl:

              remoteCommand = new AfariaOutbound.RemoteCommandRemoveControl();

              break;

            case DeviceAction.WipeAll:

              remoteCommand = new AfariaOutbound.RemoteCommandWipeAll();

              break;

            case DeviceAction.WipeAllAndBlockExchangeActiveSync:

              remoteCommand = new AfariaOutbound.RemoteCommandWipeAllAndBlockExchangeActiveSync();

              break;

            default:

              remoteCommand = new AfariaOutbound.RemoteCommandApplyPolicies();

              break;

          }

          svcOutbound.SendCommandNotificationV002(remoteCommand

                            , new AfariaOutbound.ClientSpecifier[] {client}

                            , false);

        }

      }

Getting a List of Afaria Servers and Deleting a Device

All of the changes made in steps in this section will occur in the AfariaHelper class.

  1. Deleting a device requires specification of a server's transmitter ID. This can either be saved in the web.config file, or pulled from the API. For illustration purposes, The example will pull this value from the API on a per call basis, but for production environments, it is best to store this value in the web.config for quick reference, and catch for exceptions thrown, then correct the value by calling the API.
    1. Add a service reference to the Server service, as outlined in Afaria API 101, and name it AfariaServer.
    2. Add a property to AfariaHelper of type ServerServiceClient and name it svcServer.
    3. Add a method named initServerService which takes no parameters and returns void.
      1. Copy initDevicesService and make the ncessary modifications so that initServerService will initiate the svcServer property.
    4. Add a method named isServerServiceOperable which takes no parameters and returns bool.
      1. Copy isDevicesServiceOperable and make the necessary modifications so that isServerServiceOperable will assure that the Server service is available, will attempt to initialize svcServer if not, and return true/false based on the state of svcServer.
    5. Add a protected/private method called getServerIDs which takes no parameters and returns a string array. As a matter of preference,the Master server will be the 0th element in the array (if running), but this is not necessary, so steps 4, 5.3 and 6 can be skipped.
      1. Check if the Server service is available by calling isServerServiceOperable. Return an empty array if not.
      2. Call svcServer.GetServerList and save the results to an array of AfariaServer.ServiceDescription named servers.
      3. Create a new List<string> named serverList.
      4. Create a new string named serverMasterID and set to string.Empty.
      5. Loop through each ServerDescription in the servers array and:
        1. Check if the server is running by comparing the ServerDescription.State to AfariaServer.ServerState.Running. Do nothing if not running.
        2. Add the server to the serverList using the ServerDescription.ServerId.
        3. Check if the server is the master server by comparing the ServerDescription.Role to AfariaServerRole.Master. Do nothing if not the master, set serverMasterID to the ServerDescription.ServerId.
      6. If serverMasterID has been set, remove it from the list and insert it at position 0.
      7. Set the return array to the result of serverList.ToArray and return this value.

        protected string[] getServerIDs()

        {

          string[] ret = new string[0];

          if(isServerServiceOperable())

          {

            AfariaServer.ServerDescription[] servers = svcServer.GetServerList();

            if(servers != null)

            {

              ListserverList = new List();

              string serverMasterID = string.Empty;

              foreach(AfariaServer.ServerDescription server in servers)

              {

                if(server.State == AfariaServer.ServerState.Running)

                {

                  serverList.Add(server.ServerId);

                  if(server.Role == AfariaServer.ServerRole.Master)

                  {

                    serverMasterID = server.ServerId;

                  }

                }

              }

              if(serverMasterID != string.Empty)

              {

                serverList.Remove(serverMasterID);

                serverList.Insert(0, serverMasterID);

              }

              ret = serverList.ToArray();

            }

          }

          return ret;

        }

    6. Add a protected/private method called setServerID which takes no parameters and returns void. Since the ServerID context is shared amongst all services using the same context, it does not matter which service that SetServiceIdContext is called against, just that it is called for one of the services sharing the same context.
      1. Call getServerIDs and save the result to a string array.
      2. If the string array is non-empty and svcServer is not null (it should never be null because of the call to getServerIDs), call SetServerIdContext with the 0th element of the array returned by getServerIDs.

        protected void setServerID()

        {

          string[] servers = getServerIDs();

          if (servers.Length > 0 && svcServer != null)

          {

            svcServer.SetServerIdContext(servers[0]);

          }

        }

  2. Add a public method named deleteDevice which takes a string parameter for the device ID and returns void.
    1. Check if the deviceID appears to be a valid device GUID by calling Guid.TryParse and check if the Device service is available by calling isDeviceServiceOperable. Do nothing if either of these fail.
    2. Call setServerID.
    3. Call DeleteDevices on the Devices service, passing as parameters: a AfariaDevices.DeleteOptions mask and a string array which includes only the passed parameter.
      1. Since the DeleteOptions is a mask, it is possible to refine the data which is removed when calling DeleteDevice. A normal option would be to pass DeleteOptions.AllMask, which would remove all device related data, but for illustration purposes, the example will delete all data except for the existing TEM/Device Activity data, which may be desired in some environments. This is done by performing bitwise operations on the mask options. Using XOR may appear cleaner, but for readability, it is less clear about what is actually being deleted.

public void deleteDevice(string deviceID)

{

  Guid temp;

  if (Guid.TryParse(deviceID, out temp) && isDevicesServiceOperable())

  {

    setServerID();

    //delete but keep Device Activity (TEM) data

    svcDevices.DeleteDevice(AfariaDevices.DeleteOptions.Device

      | AfariaDevices.DeleteOptions.ActionLog

      | AfariaDevices.DeleteOptions.FromDeviceGroups

      | AfariaDevices.DeleteOptions.InventoryData

      | AfariaDevices.DeleteOptions.LogData

      | AfariaDevices.DeleteOptions.PackageTrackingData, new string[] { deviceID });

  }

}

Updating for SP5 compatibility

Inventory structure was updated for SP5 in order to be more consistent between device types. As such, the AfariaHelper class will need to be modified slightly. In most instances, it is not necessary to update service references when updating the Afaria server, but it is necessary to take advantage of new functionality via the API.

  1. Modify getDeviceProps to reflect the new structure. I will point out the specific changes necessary for updating the previous example in the following steps.
  2. For Android:
    1. Modify the Android case of the first switch in getDeviceProps. IMEI, Serial number, Phone number and Device Model are now a part of the General class instead of the Device and Phone classes.

      case AfariaDevices.ClientType.Android:

          request.RequestParameters[0].ClassPropertiesList = new AfariaDevices.DevicePropertiesRequestClassProperty[2];

          request.RequestParameters[0].ClassPropertiesList[0] = new AfariaDevices.DevicePropertiesRequestClassProperty();

          request.RequestParameters[0].ClassPropertiesList[0].ClassName = "General";

          request.RequestParameters[0].ClassPropertiesList[0].PropertyNames = new string[4];

          request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[0] = "IMEI";

          request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[1] = "Serial number";

          request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[2] = "Phone number";

          request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[3] = "Device Model";

          request.RequestParameters[0].ClassPropertiesList[1] = new AfariaDevices.DevicePropertiesRequestClassProperty();

          request.RequestParameters[0].ClassPropertiesList[1].ClassName = "Android";

          request.RequestParameters[0].ClassPropertiesList[1].PropertyNames = new string[1];

          request.RequestParameters[0].ClassPropertiesList[1].PropertyNames[0] = "Device Maker";

          break;

    2. Modify the Android case of the second switch in getDeviceProps to reflect the changes in the request above.

      case AfariaDevices.ClientType.Android:

          if ((dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName == "IMEI")

                && (dss._dataTableSurrogates[0]._dataColumnSurrogates[1]._columnName == "Serial number")

                && (dss._dataTableSurrogates[0]._dataColumnSurrogates[2]._columnName == "Phone number")

                && (dss._dataTableSurrogates[0]._dataColumnSurrogates[3]._columnName == "Device Model")

                && (dss._dataTableSurrogates[1]._dataColumnSurrogates[0]._columnName == "Device Maker")

                && dss._dataTableSurrogates[0]._records != null

                && dss._dataTableSurrogates[1]._records != null)

          {

                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName

                    , dss._dataTableSurrogates[0]._records[0][0].ToString()); //IMEI

                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[1]._columnName

                    , dss._dataTableSurrogates[0]._records[1][0].ToString()); //Serial number

                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[2]._columnName

                    , dss._dataTableSurrogates[0]._records[2][0].ToString()); //Phone number

                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[3]._columnName

                    , dss._dataTableSurrogates[0]._records[3][0].ToString()); //Device model

                deviceProps.Add(dss._dataTableSurrogates[1]._dataColumnSurrogates[0]._columnName

                    , dss._dataTableSurrogates[1]._records[0][0].ToString()); //Device maker

          }

          break;

  3. For iOS:
    1. Modify the iOS case of the first switch in getDeviceProps. Model is now a part of the General class and is called Device Model. Phone number is also now a part of the General class.

      case AfariaDevices.ClientType.Ios:

          request.RequestParameters[0].ClassPropertiesList = new AfariaDevices.DevicePropertiesRequestClassProperty[1];

          request.RequestParameters[0].ClassPropertiesList[0] = new AfariaDevices.DevicePropertiesRequestClassProperty();

          request.RequestParameters[0].ClassPropertiesList[0].ClassName = "General";

          request.RequestParameters[0].ClassPropertiesList[0].PropertyNames = new string[2];

          request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[0] = "Device Model";

          request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[1] = "Phone number";

          break;

    2. Modify the iOS case of the second switch in getDeviceProps to reflect the changes made in the request above.

      case AfariaDevices.ClientType.Ios:

          if ((dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName == "Device Model")

                && (dss._dataTableSurrogates[0]._dataColumnSurrogates[1]._columnName == "Phone number")

                && dss._dataTableSurrogates[0]._records != null)

          {

                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName

                    , dss._dataTableSurrogates[0]._records[0][0].ToString()); //Model

                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[1]._columnName

                    , dss._dataTableSurrogates[0]._records[1][0].ToString()); //Phone number

          }

          break;

  4. Since the names have changed in inventory, we must also update the getDeviceInfo method when pulling info from getDeviceProps.
    1. For iOS, Model is now "Device Model", "Phone number" remains the name.
    2. For Android, "Device maker" and "Device model" are now "Device Maker" and "Device Model".

Wrapping it up

  1. In Index.aspx, in Design, Add buttons below the GridView, but in the ViewDevices view for each of the commands you will utilize. Name them appropriately, e.g. ButtonApply, ButtonLock, ButtonUnlock, ButtonRemoveControl, ButtonWipe and ButtonDelete.
  2. Respectively, change the text on each button added in step 1 to an appropriate prompt e.g. "Apply Policies", "Lock", "Unlock", "Remove Control", "Wipe Device", "Delete".
  3. Set the Enabled property of each button added in step 1 to false.
  4. Double-click on each button added in step 1 to add the Click event function.
  5. Add a function to Index.aspx.cs, Index class named getSelectedDeviceID which takes no parameters and returns a string.
    1. Get the cell data from the selected row by accessing GridViewDeviceSelector.SelectedRow.Cells[##].Text, where ## is the column number for ClientGuid. In the example, column 2 contains the Device's GUID.

      protected string getSelectedDeviceID()

      {

        string ret = string.Empty;

        try

        {

          ret = GridViewDeviceSelector.SelectedRow.Cells[2].Text;

        }

        catch (NullReferenceException)

        {

        }

        return ret;

      }

  6. Add a function to Index.aspx.cs, Index class named getSelctedDeviceType which takes no parameter and returns a string.
    1. Get the cell data from the selected row by accessing GridViewDeviceSelector.SelectedRow.Cells[##].Text, where ## is the column number for DeviceType. In the example, column 4 contains the Device's OS type.

      protected string getSelectedDeviceType()

      {

        string ret = string.Empty;

        try

        {

          ret = GridViewDeviceSelector.SelectedRow.Cells[4].Text;

        }

        catch(NullReferenceException)

        {

        }

        return ret;

      }

  7. Add a function to Index.aspx.cs, Index class named sendNotification, which takes a parameter of the DeviceAction type created in the AfariaHelper.
    1. Using an instance of the AfariaHelper, call its notifyDevice method, passing it the result of getSelectedDeviceID and the action parameter passed in.

      protected void sendNotification(AfariaHelper.DeviceAction action)

      {

        using (AfariaHelper apiHelper = new AfariaHelper(getConfigSetting("AfariaAPIServiceAccountDomain")

                    , getConfigSetting("AfariaAPIServiceAccountUsername")

                    , getConfigSetting("AfariaAPIServiceAccountPassword")

                    , getConfigSetting("AfariaAPIServiceAddress")))

        {

          apiHelper.notifyDevice(getSelectedDeviceID(), action);

        }

      }

  8. In the event function for the Delete button click event (ButtonDelete_Click):
    1. Using the AfariaHelper, call deleteDevice, passing the result of getSelectedDeviceID.
    2. Call getDeviceList, so that the GridViewDeviceSelector will reflect that the device has/has not been deleted.
    3. In a production environment, if the device is an iOS device, it is advisable to call sendNotification with the RemoveControl command prior to deleting the device.
    4. protected void ButtonDelete_Click(object sender, EventArgs e)

      {

        using (AfariaHelper apiHelper = new AfariaHelper(getConfigSetting("AfariaAPIServiceAccountDomain")

              , getConfigSetting("AfariaAPIServiceAccountUsername")

              , getConfigSetting("AfariaAPIServiceAccountPassword")

              , getConfigSetting("AfariaAPIServiceAddress")))

        {

          apiHelper.deleteDevice(getSelectedDeviceID());

        }

        getDeviceList();

      }

  9. Add an event function for the GridViewDeviceSelector's SelectedIndexChanged event (GridViewDeviceSelector_SelectedIndexChanged). In this function, enable/disable buttons based on the availability of the command for the device type selected (returned from getSelectedDeviceType).
  10. In the event function for the Lock button click event (ButtonLock_Click):
    1. If the device type returned by getSelectedDeviceType is equal to "Ios", call sendNotification with DeviceAction.Lock.
    2. Otherwise, call sendNotification with DeviceAction.UserLock.
  11. For the remaining event functions for the buttons added in step 1, call sendNotification with the appropriate DeviceAction type.

Full Example Program

  • Index.aspx.cs

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Web;

    using System.Web.UI;

    using System.Web.UI.WebControls;

    using AfariaAPI201.AfariaPolicy;

    using AfariaAPI201;

    namespace AfariaAPI201

    {

        public partial class index : System.Web.UI.Page

        {

            Dictionary<string, string> m_codeDict;

            protected void Page_Load(object sender, EventArgs e)

            {

                m_codeDict = (Dictionary<string,string>)ViewState["codeDict"];

                if(m_codeDict == null)//first page load

                {

                    MultiViewMain.ActiveViewIndex = 0;

                    ButtonTabEnroll.Enabled = false;

                    getPortalSetup();

                }

            }

            protected void ButtonGetCode_Click(object sender, EventArgs e)

            {

                resetUI();

                try

                {

                    using (AfariaHelper apiHelper = new AfariaHelper(getConfigSetting("AfariaAPIServiceAccountDomain")

                                                                    , getConfigSetting("AfariaAPIServiceAccountUsername")

                                                                    , getConfigSetting("AfariaAPIServiceAccountPassword")

                                                                    , getConfigSetting("AfariaAPIServiceAddress")))

                    {

                        switch(DropDownListClientType.SelectedValue)

                        {

                            case "Ios":

                                setHyperlinkEnrollmentLink(apiHelper.getEnrollmentUrl(TextBoxUserName.Text,

                                    m_codeDict["Ios"],

                                    TextBoxEmailAddress.Text));

                                LabelUserInstructions.Text = "Click on the below URL and follow the prompts to enroll.";

                                break;

                            case "Android":

                                setHyperlinkEnrollmentLink(apiHelper.getEnrollmentUrl(TextBoxUserName.Text,

                                    m_codeDict["Android"],

                                    TextBoxEmailAddress.Text,

                                    ClientType.Android));

                                LabelUserInstructions.Text = "Download the Afaria client from the Google Play store, and return to this page and click on the below link.";

                                break;

                            case "WinPhone":

                                setHyperlinkEnrollmentLink(apiHelper.getEnrollmentUrl(TextBoxUserName.Text,

                                    m_codeDict["WinPhone"],

                                    TextBoxEmailAddress.Text,

                                    ClientType.WinPhone));

                                LabelUserInstructions.Text = "Copy the Enrollment Code URL below to enter it into the Server address field on Company Apps of your device.";

                                LabelUserInstructions.Enabled = true;

                                break;

                            case "WinMobileProfessional":

                                LabelUserInstructions.Text = "Copy the Enrollment Code following to enter it into the client on your device for enrollment:";

                                LabelUserInstructions.Text += "\r\n\r\n" + m_codeDict["WinMobileProfessional"];

                                LabelUserInstructions.Enabled = true;

                                break;

                            case "WinMobileStandard":

                                LabelUserInstructions.Text = "Copy the Enrollment Code following to enter it into the client on your device for enrollment:";

                                LabelUserInstructions.Text += "\r\n\r\n" + m_codeDict["WinMobileStandard"];

                                LabelUserInstructions.Enabled = true;

                                break;

                            case "Win32":

                            case "BlackBerry":

                            default:

                                LabelUserWarning.Text += "\r\nUnsupported Client Type.";

                                break;

                        }

                    }

                }

                catch (Exception ex)

                {

                    System.Diagnostics.Trace.WriteLine(ex.Message);

                    System.Diagnostics.Trace.WriteLine(ex.StackTrace);

                    LabelUserWarning.Text += "\r\nAn error occurred while processing, please try again and notify Support if this message persists.";

                }

            }

            private void setHyperlinkEnrollmentLink(string url)

            {

                HyperLinkEnrollmentLink.NavigateUrl = url;

                HyperLinkEnrollmentLink.Text = url;

                HyperLinkEnrollmentLink.Enabled = true;

                HyperLinkEnrollmentLink.Visible = true;

            }

            private string getConfigSetting(string setting)

            {

                string value = string.Empty;

                if (System.Configuration.ConfigurationManager.AppSettings.Count > 0)

                {

                    value = System.Configuration.ConfigurationManager.AppSettings[setting];

                }

                return value;

            }

            private void getPortalSetup()

            {

                using (AfariaHelper apiHelper = new AfariaHelper(getConfigSetting("AfariaAPIServiceAccountDomain")

                                        , getConfigSetting("AfariaAPIServiceAccountUsername")

                                        , getConfigSetting("AfariaAPIServiceAccountPassword")

                                        , getConfigSetting("AfariaAPIServiceAddress")))

                {

                    string sspGUID = getConfigSetting("AfariaSSPGUID");

                    if (string.IsNullOrWhiteSpace(sspGUID))

                    {

                        string sspName = getConfigSetting("AfariaSSPName");

                        if (string.IsNullOrWhiteSpace(sspName))

                        {

                            sspName = "NewCustomPortal";

                            setConfigSetting("AfariaSSPName", sspName);

                        }

                        sspGUID = apiHelper.getNewPortalGUID(sspName);

                        setConfigSetting("AfariaSSPGUID", sspGUID);

                        resetUI();

                        ButtonGetCode.Enabled = false;

                        LabelUserWarning.Text = "Portal not configured. Please contact support. REF:SSP=[" + sspName + "]";

                    }

                    else

                    {

                        m_codeDict = apiHelper.getPortalCodes(sspGUID);

                        ViewState["codeDict"] = m_codeDict;

                    }

                }

            }

            private void getDeviceList()

            {

                if (!string.IsNullOrWhiteSpace(TextBoxUserName.Text))

                {

                    System.Data.DataTable dt;

                    using (AfariaHelper apiHelper = new AfariaHelper(getConfigSetting("AfariaAPIServiceAccountDomain")

                                , getConfigSetting("AfariaAPIServiceAccountUsername")

                                , getConfigSetting("AfariaAPIServiceAccountPassword")

                                , getConfigSetting("AfariaAPIServiceAddress")))

                    {

                        dt = apiHelper.getDeviceInfo(TextBoxUserName.Text);

                    }

                    GridViewDeviceSelector.DataSource = dt;

                    GridViewDeviceSelector.DataBind();

                }

                else

                {

                    LabelUserWarning.Text = "A username must be specified to retrieve info.";

                }

            }

            private void setConfigSetting(string key, string value)

            {

                System.Configuration.Configuration config = null;

                try

                {

                    config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~");

                    config.AppSettings.Settings[key].Value = value;

                    config.Save();

                }

                catch (NullReferenceException)

                {

                    //add key, it doesn't exist

                    if(config != null)

                    {

                        config.AppSettings.Settings.Add(key, value);

                        config.Save();

                    }

                }

                catch(Exception ex)

                {

                    System.Diagnostics.Debug.WriteLine("Exception Message: " + ex.Message + "\r\nException Stack: " + ex.StackTrace);

                    throw ex;

                }

            }

            private void resetUI()

            {

                LabelUserWarning.Text = string.Empty;

                HyperLinkEnrollmentLink.Text = string.Empty;

                HyperLinkEnrollmentLink.NavigateUrl = string.Empty;

                HyperLinkEnrollmentLink.Enabled = false;

                HyperLinkEnrollmentLink.Visible = false;

                LabelUserInstructions.Text = string.Empty;

                LabelUserInstructions.Enabled = false;

            }

            protected void ButtonTabEnroll_Click(object sender, EventArgs e)

            {

                setTabViewState((Button)sender);

            }

            protected void ButtonTabDevices_Click(object sender, EventArgs e)

            {

                setTabViewState((Button)sender);

                getDeviceList();

            }

            private void setTabViewState(Button sender)

            {

                int selectedTabIndex = 0;

                int.TryParse(sender.CommandArgument, out selectedTabIndex);

                ButtonTabEnroll.Enabled = true;

                ButtonTabDevices.Enabled = true;

                sender.Enabled = false;

                MultiViewMain.ActiveViewIndex = selectedTabIndex;

            }

            protected void ButtonGetDevices_Click(object sender, EventArgs e)

            {

                getDeviceList();

            }

            protected void GridViewDeviceSelector_SelectedIndexChanged(object sender, EventArgs e)

            {

                System.Diagnostics.Debug.WriteLine("Selected Device Row: " + ((GridView)sender).SelectedIndex.ToString());

                switch(getSelectedDeviceType())

                {

                    case "Ios":

                        ButtonApply.Enabled = true;

                        ButtonDelete.Enabled = true;

                        ButtonLock.Enabled = true;

                        ButtonRemoveControl.Enabled = true;

                        ButtonUnlock.Enabled = true;

                        ButtonWipe.Enabled = true;

                        break;

                    case "Android":

                        ButtonApply.Enabled = true;

                        ButtonDelete.Enabled = true;

                        ButtonLock.Enabled = true;

                        ButtonRemoveControl.Enabled = false;

                        ButtonUnlock.Enabled = false;

                        ButtonWipe.Enabled = true;

                        break;

                    default:

                        ButtonApply.Enabled = false;

                        ButtonDelete.Enabled = true;

                        ButtonLock.Enabled = false;

                        ButtonRemoveControl.Enabled = false;

                        ButtonUnlock.Enabled = false;

                        ButtonWipe.Enabled = false;

                        break;

                }

            }

            protected void ButtonApply_Click(object sender, EventArgs e)

            {

                sendNotification(AfariaHelper.DeviceAction.ApplyPolicies);

            }

            protected void ButtonLock_Click(object sender, EventArgs e)

            {

                if (getSelectedDeviceType() == "Ios")

                {

                    sendNotification(AfariaHelper.DeviceAction.Lock);

                }

                else

                {

                    sendNotification(AfariaHelper.DeviceAction.UserLock);

                }

            }

            protected void ButtonUnlock_Click(object sender, EventArgs e)

            {

                sendNotification(AfariaHelper.DeviceAction.Unlock);

            }

            protected void ButtonRemoveControl_Click(object sender, EventArgs e)

            {

                sendNotification(AfariaHelper.DeviceAction.RemoveControl);

            }

            protected void ButtonWipe_Click(object sender, EventArgs e)

            {

                sendNotification(AfariaHelper.DeviceAction.WipeAll);

            }

            protected void ButtonDelete_Click(object sender, EventArgs e)

            {

                using (AfariaHelper apiHelper = new AfariaHelper(getConfigSetting("AfariaAPIServiceAccountDomain")

                            , getConfigSetting("AfariaAPIServiceAccountUsername")

                            , getConfigSetting("AfariaAPIServiceAccountPassword")

                            , getConfigSetting("AfariaAPIServiceAddress")))

                {

                    apiHelper.deleteDevice(getSelectedDeviceID());

                }

                getDeviceList();

            }

            protected void sendNotification(AfariaHelper.DeviceAction action)

            {

                using (AfariaHelper apiHelper = new AfariaHelper(getConfigSetting("AfariaAPIServiceAccountDomain")

                                        , getConfigSetting("AfariaAPIServiceAccountUsername")

                                        , getConfigSetting("AfariaAPIServiceAccountPassword")

                                        , getConfigSetting("AfariaAPIServiceAddress")))

                {

                    apiHelper.notifyDevice(getSelectedDeviceID(), action);

                }

            }

            protected string getSelectedDeviceID()

            {

                string ret = string.Empty;

                try

                {

                    ret = GridViewDeviceSelector.SelectedRow.Cells[2].Text;

                }

                catch (NullReferenceException)

                {

                }

                return ret;

            }

            protected string getSelectedDeviceType()

            {

                string ret = string.Empty;

                try

                {

                    ret = GridViewDeviceSelector.SelectedRow.Cells[4].Text;

                }

                catch(NullReferenceException)

                {

                }

                return ret;

            }

        }

        public class AfariaHelper : IDisposable

        {

            public string contextID { get; private set; }

            int contextCount;

            string APIdomain, APIaccount, APIpassword, APIaddress;

            PolicyServiceClient svcPolicy;

            AfariaServerProperties.ServerPropertiesServiceClient svcServerProperties;

            AfariaDevices.DevicesServiceClient svcDevices;

            AfariaOutbound.OutboundServiceClient svcOutbound;

            AfariaServer.ServerServiceClient svcServer;

            bool disposed = false;

            int tenantID;

    #region Static Methods

            public static List<string> getClientTypes()

            {

                List<string> types = new List<string>();

                foreach (string type in Enum.GetNames(typeof(ClientType)))

                {

                    if (type != "All" && type != "Undefined")

                    {

                        types.Add(type);

                    }

                }

                return types;

            }

    #endregion Statics

    #region Public Instance Methods & Constructor/Destructor

            public AfariaHelper(string APIdomain, string APIaccount, string APIpassword, string APIaddress = "127.0.0.1", int TenantID = 0)

            {

                this.APIdomain = APIdomain;

                this.APIaccount = APIaccount;

                this.APIpassword = APIpassword;

                this.APIaddress = APIaddress;

                this.tenantID = TenantID;

                contextID = Guid.NewGuid().ToString();

                contextCount = 0;

            }

            public enum DeviceAction { ApplyPolicies = AfariaOutbound.RemoteCommand.ApplyPolicies

                                    , Lock = AfariaOutbound.RemoteCommand.Lock

                                    , Unlock = AfariaOutbound.RemoteCommand.Unlock

                                    , RemoveControl = AfariaOutbound.RemoteCommand.RemoveControl

                                    , WipeAll = AfariaOutbound.RemoteCommand.WipeAll

                                    , WipeAllAndBlockExchangeActiveSync = AfariaOutbound.RemoteCommand.WipeAllAndBlockExchangeActiveSync

                                    , UserLock = AfariaOutbound.RemoteCommand.UserLock};

            public void Dispose()

            {

                Dispose(true);

            }

            protected void Dispose(bool disposing)

            {

                if (disposed)

                {

                    return;

                }

                if (disposing)

                {

                    contextCleanup();

                    if (svcPolicy != null)

                    {

                        svcPolicy.Close();

                        svcPolicy = null;

                    }

                }

                disposed = true;

            }

            public string getEnrollmentUrl(string userAccount, string enrollCode, string userEmail, ClientType deviceType = ClientType.Ios)

            {

                string url = string.Empty;

                string activationID = string.Empty;

                activationID = getActivationID(userAccount, enrollCode, userEmail, deviceType);

                if (!(string.IsNullOrEmpty(activationID)) && (isPolicyServiceOperable()))

                {

                    activationID = activationID.Replace(" ", string.Empty); //remove spaces from returned activation ID

                    AfariaPolicy.DataState ds = svcPolicy.OpenPolicy(enrollCode);

                    if (deviceType == ClientType.Android)

                    {

                        setServerID();

                    }

                    EnrollmentPolicySettings plcySettings = svcPolicy.EnrollmentGetPolicySettings(ds);

                    svcPolicy.Release(ds);

                    if (plcySettings != null)

                    {

                        switch (deviceType)

                        {

                            case ClientType.Ios:

                                url = ((EnrollmentPolicySettingsIos)plcySettings).MdmEnrollmentUrl;

                                url = url.Replace(enrollCode, activationID);

                                break;

                            case ClientType.Android:

                                url = "afaria://e=" + activationID;

                                break;

                            case ClientType.WinPhone:

                                url = ((EnrollmentPolicySettingsWinPhone)plcySettings).MdmEnrollmentUrl;

                                url = url.Replace(enrollCode, activationID);

                                break;

                            default:

                                return string.Empty; //not supported at this time

                        }

                    }

                    else

                    {

                        throw new Exception("Specified enrollment code is invalid.");

                    }

                    return url;

                }

                else

                {

                    throw new Exception("Policy Service is not operable");

                }

            }

            public string getActivationID(string userAccount, string enrollCode, string userEmail, ClientType deviceClientType)

            {

                string output = string.Empty;

                if (isPolicyServiceOperable())

                {

                    EnrollmentCodeActivationIdInfo activationID = svcPolicy.EnrollmentCodeGenerateActivationIdWithAddress(userAccount, enrollCode, userEmail, deviceClientType);

                    output = activationID.CompleteActivationId;

                }

                else

                {

                    throw new Exception("Policy Service is not operable");

                }

                return output;

            }

            public string getNewPortalGUID(string portalName)

            {

                string outString = string.Empty;

                if (!string.IsNullOrWhiteSpace(portalName))

                {

                    if (isServerPropertiesServiceOperable())

                    {

                        Guid portalGUID = svcServerProperties.AddSelfServicePortal(portalName);

                        outString = portalGUID.ToString();

                    }

                    else

                    {

                        throw new Exception("ServerProperties Service is not operable.");

                    }

                }

                return outString;

            }

            public Dictionary<string, string> getPortalCodes(string portalGUID)

            {

                Dictionary<string, string> outDict = new Dictionary<string, string>();

                if (!string.IsNullOrWhiteSpace(portalGUID))

                {

                    Guid guid = new Guid();

                    try

                    {

                        guid = new Guid(portalGUID);

                    }

                    catch (FormatException)

                    {

                        throw new Exception("Portal GUID is invalid.");

                    }

                    catch (OverflowException)

                    {

                        throw new Exception("Portal GUID is invalid.");

                    }

                    if(isServerPropertiesServiceOperable())

                    {

                        AfariaServerProperties.SelfServicePortalConfiguration[] sspConfigs;

                        sspConfigs = svcServerProperties.GetSelfServicePortalConfigurations(new Guid[] { guid });

                        if (sspConfigs.Length == 1)

                        {

                            foreach (AfariaServerProperties.SelfServicePortalEnrollmentCodeInfo code in sspConfigs[0].EnrollmentCodes)

                            {

                                outDict.Add(code.ClientType.ToString(), code.EnrollmentCode);

                            }

                        }

                        else

                        {

                            throw new Exception("Portal does not exist for this GUID.");

                        }

                    }

                }

                return outDict;

            }

            public System.Data.DataTable getDeviceInfo(string id)

            {

                System.Data.DataTable dt = null;

                if (!string.IsNullOrWhiteSpace(id))

                {

                    if (isDevicesServiceOperable())

                    {

                        AfariaDevices.DataState ds;

                        string[] deviceIDs = svcDevices.GetFirstIds(0, 20

                                    , AfariaDevices.SupportedClients.Android

                                        & AfariaDevices.SupportedClients.Ios

                                        & AfariaDevices.SupportedClients.WinPhone

                                    , AfariaDevices.SearchFields.SelfServiceUserName

                                    , id, out ds);

                        if(deviceIDs.Length > 0)

                        {

                            dt = new System.Data.DataTable("DeviceInfo");

                            dt.Columns.Add("UID");

                            dt.Columns.Add("ClientGUID");

                            dt.Columns.Add("DisplayName");

                            dt.Columns.Add("DeviceType");

                            dt.Columns.Add("OSversion");

                            dt.Columns.Add("Corporate");

                            dt.Columns.Add("Compliant");

                            dt.Columns.Add("IMEI");

                            dt.Columns.Add("SerialNo");

                            dt.Columns.Add("PhoneNo");

                            dt.Columns.Add("Model");

                            dt.Columns.Add("OSID");

                            dt.Columns.Add("LastConnection");

                            AfariaDevices.DeviceInfo[] devInfos;

                            devInfos = svcDevices.GetDeviceInfo(AfariaDevices.DeviceInfoDataRetrievalTypes.All, deviceIDs);

                            foreach(AfariaDevices.DeviceInfo info in devInfos)

                            {

                                object[] tmp = new object[] { info.ClientUid //0-identifier

                                                            , info.ClientGuid //1-identifier

                                                            , info.DeviceIdInfo.Value != null ? info.DeviceIdInfo.Value.Trim() : string.Empty //2-display name

                                                            , info.ClientType.ToString() //3-device type

                                                            , info.PlatformVersion //4-os version

                                                            , info.CorporateOwned //5-corporate

                                                            , info.DeviceComplianceStatus //6-compliant

                                                            , string.Empty //7-imei

                                                            , string.Empty //8-serial #

                                                            , string.Empty //9-phone number

                                                            , string.Empty //10-Manufacturer Model

                                                            , string.Empty //11-OS ID (UDID/AndroidID/MobileID)

                                                            , info.ConnectionInfo.LastConnection //12-last connection

                                                            };

                                Dictionary<string, string> additionalProps;

                                switch(info.ClientType)

                                {

                                    case AfariaDevices.ClientType.Ios:

                                        tmp[7] = info.IosDeviceInfo.Imei;

                                        tmp[8] = info.IosDeviceInfo.SerialNumber;

                                        tmp[11] = info.IosDeviceInfo.Udid;

                                        additionalProps = getDeviceProps(info.ClientType, info.ClientUid);

                                        if (additionalProps != null)

                                        {

                                            if (additionalProps.ContainsKey("Device Model"))

                                            {

                                                tmp[10] = additionalProps["Device Model"];//Model

                                            }

                                            if (additionalProps.ContainsKey("Phone number"))

                                            {

                                                tmp[9] = additionalProps["Phone number"];//PhoneNo

                                            }

                                        }

                                        break;

                                    case AfariaDevices.ClientType.WinPhone:

                                        tmp[7] = info.WinPhoneDeviceInfo.Imei;

                                        tmp[10] = info.WinPhoneDeviceInfo.Manufacturer

                                                    + " " + info.WinPhoneDeviceInfo.Model;

                                        additionalProps = getDeviceProps(info.ClientType, info.ClientUid);

                                        if(additionalProps != null)

                                        {

                                            if (additionalProps.ContainsKey("Mobile ID"))

                                            {

                                                tmp[11] = additionalProps["Mobile ID"];//OS ID

                                            }

                                        }

                                        break;

                                    case AfariaDevices.ClientType.Android:

                                        additionalProps = getDeviceProps(info.ClientType, info.ClientUid);

                                        if(additionalProps != null)

                                        {

                                

                                            if (additionalProps.ContainsKey("IMEI"))

                                            {

                                                tmp[7] = additionalProps["IMEI"];//IMEI

                                            }

                                            if (additionalProps.ContainsKey("Serial number"))

                                            {

                                                tmp[8] = additionalProps["Serial number"];//SerialNo

                                            }

                                            if (additionalProps.ContainsKey("Phone number"))

                                            {

                                                tmp[9] = additionalProps["Phone number"];//PhoneNo

                                            }

                                            if (additionalProps.ContainsKey("Device Maker") &&

                                                additionalProps.ContainsKey("Device Model"))

                                            {

                                                tmp[10] = additionalProps["Device Maker"].ToUpper()

                                                    + " " + additionalProps["Device Model"].ToUpper();// Maker + Model

                                            }

                                        }

                                        break;

                                    default:

                                        //nothing to see here, moving along

                                        break;

                                }

                                System.Data.DataRow dr = dt.Rows.Add(tmp);

                            }

                        }

                    }

                }

                return dt;

            }

            public void notifyDevice(string deviceID, DeviceAction command)

            {

                Guid temp;

                if (Guid.TryParse(deviceID, out temp) && isOutboundServiceOperable())

                {

                    setServerID();

                    AfariaOutbound.ClientSpecifier client = new AfariaOutbound.ClientSpecifier();

                    client.IdType = AfariaOutbound.IdType.ClientGuid;

                    client.Value = deviceID;

                    AfariaOutbound.RemoteCommandBase remoteCommand;

                    switch (command)

                    {

                        case DeviceAction.UserLock:

                            remoteCommand = new AfariaOutbound.RemoteCommandUserLock();

                            break;

                        case DeviceAction.Lock:

                            remoteCommand = new AfariaOutbound.RemoteCommandLock();

                            break;

                        case DeviceAction.Unlock:

                            remoteCommand = new AfariaOutbound.RemoteCommandUnlock();

                            break;

                        case DeviceAction.RemoveControl:

                            remoteCommand = new AfariaOutbound.RemoteCommandRemoveControl();

                            break;

                        case DeviceAction.WipeAll:

                            remoteCommand = new AfariaOutbound.RemoteCommandWipeAll();

                            break;

                        case DeviceAction.WipeAllAndBlockExchangeActiveSync:

                            remoteCommand = new AfariaOutbound.RemoteCommandWipeAllAndBlockExchangeActiveSync();

                            break;

                        default:

                            remoteCommand = new AfariaOutbound.RemoteCommandApplyPolicies();

                            break;

                    }

                    svcOutbound.SendCommandNotificationV002(remoteCommand

                                                        , new AfariaOutbound.ClientSpecifier[] {client}

                                                        , false);

                }

            }

            public void deleteDevice(string deviceID)

            {

                Guid temp;

                if (Guid.TryParse(deviceID, out temp) && isDevicesServiceOperable())

                {

                    setServerID();

                    //delete but keep Device Activity (TEM) data

                    svcDevices.DeleteDevice(AfariaDevices.DeleteOptions.Device

                        | AfariaDevices.DeleteOptions.ActionLog

                        | AfariaDevices.DeleteOptions.FromDeviceGroups

                        | AfariaDevices.DeleteOptions.InventoryData

                        | AfariaDevices.DeleteOptions.LogData

                        | AfariaDevices.DeleteOptions.PackageTrackingData, new string[] { deviceID });

                }

            }

    #endregion Public Instance Methods & Constructor/Destructor

    #region Protected/Private Instance Methods

            protected void initPolicyService()

            {

                svcPolicy = new PolicyServiceClient("NetTcpBinding_IPolicyService", "net.tcp://" + APIaddress + ":7982/AfariaService/Policy");

                svcPolicy.ClientCredentials.Windows.ClientCredential.Domain = APIdomain;

                svcPolicy.ClientCredentials.Windows.ClientCredential.UserName = APIaccount;

                svcPolicy.ClientCredentials.Windows.ClientCredential.Password = APIpassword;

                ContextInfo ci = svcPolicy.InitContext(contextID);

                if (ci.TenantId == -1)//TenantId not set

                {

                    svcPolicy.SetTenantIdContext(tenantID);

                }

                contextCount++;

            }

            protected void initServerPropertiesService()

            {

                svcServerProperties = new AfariaServerProperties.ServerPropertiesServiceClient("NetTcpBinding_IServerPropertiesService"

                                                        , "net.tcp://" + APIaddress + ":7982/AfariaService/ServerProperties");

                svcServerProperties.ClientCredentials.Windows.ClientCredential.Domain = APIdomain;

                svcServerProperties.ClientCredentials.Windows.ClientCredential.UserName = APIaccount;

                svcServerProperties.ClientCredentials.Windows.ClientCredential.Password = APIpassword;

                AfariaServerProperties.ContextInfo ci = svcServerProperties.InitContext(contextID);

                if (ci.TenantId == -1) //TenantId not set

                {

                    svcServerProperties.SetTenantIdContext(tenantID);

                }

                contextCount++;

            }

            protected void initDevicesService()

            {

                svcDevices = new AfariaDevices.DevicesServiceClient("NetTcpBinding_IDevicesService"

                                            , "net.tcp://" + APIaddress + ":7982/AfariaService/Devices");

                svcDevices.ClientCredentials.Windows.ClientCredential.Domain = APIdomain;

                svcDevices.ClientCredentials.Windows.ClientCredential.UserName = APIaccount;

                svcDevices.ClientCredentials.Windows.ClientCredential.Password = APIpassword;

                AfariaDevices.ContextInfo ci = svcDevices.InitContext(contextID);

                if(ci.TenantId == -1)

                {

                    svcDevices.SetTenantIdContext(tenantID);

                }

                contextCount++;

            }

            protected void initOutboundService()

            {

                svcOutbound = new AfariaOutbound.OutboundServiceClient("NetTcpBinding_IOutboundService"

                                                                , "net.tcp://" + APIaddress + ":7982/AfariaService/Outbound");

                svcOutbound.ClientCredentials.Windows.ClientCredential.Domain = APIdomain;

                svcOutbound.ClientCredentials.Windows.ClientCredential.UserName = APIaccount;

                svcOutbound.ClientCredentials.Windows.ClientCredential.Password = APIpassword;

                AfariaOutbound.ContextInfo ci = svcOutbound.InitContext(contextID);

                if(ci.TenantId == -1)

                {

                    svcOutbound.SetTenantIdContext(tenantID);

                }

                contextCount++;

            }

            protected void initServerService()

            {

                svcServer = new AfariaServer.ServerServiceClient("NetTcpBinding_IServerService"

                                                                , "net.tcp://" + APIaddress + ":7982/AfariaService/Server");

                svcServer.ClientCredentials.Windows.ClientCredential.Domain = APIdomain;

                svcServer.ClientCredentials.Windows.ClientCredential.UserName = APIaccount;

                svcServer.ClientCredentials.Windows.ClientCredential.Password = APIpassword;

                AfariaServer.ContextInfo ci = svcServer.InitContext(contextID);

                if (ci.TenantId == -1)

                {

                    svcServer.SetTenantIdContext(tenantID);

                }

                contextCount++;

            }

            protected bool isPolicyServiceOperable()

            {

                bool ret = false;

                if (svcPolicy != null)

                {

                    if (svcPolicy.State == System.ServiceModel.CommunicationState.Faulted)

                    {

                        svcPolicy.Abort();

                        contextCleanup();

                        svcPolicy = null;

                        try

                        {

                            initPolicyService();

                            ret = true;

                        }

                        catch (Exception ex)

                        {

                            throw new Exception("Error initializing service in isPolicyServiceOperable.", ex);

                        }

                    }

                    else if (svcPolicy.State == System.ServiceModel.CommunicationState.Opened)

                    {

                        ret = true;

                    }

                }

                else

                {

                    try

                    {

                        initPolicyService();

                        ret = true;

                    }

                    catch (Exception ex)

                    {

                        throw new Exception("Error initializing service in isPolicyServiceOperable.", ex);

                    }

                }

                return ret;

            }

            protected bool isServerPropertiesServiceOperable()

            {

                bool ret = false;

                if (svcServerProperties != null)

                {

                    if (svcServerProperties.State == System.ServiceModel.CommunicationState.Faulted)

                    {

                        svcServerProperties.Abort();

                        contextCleanup();

                        svcServerProperties = null;

                        try

                        {

                            initServerPropertiesService();

                            ret = true;

                        }

                        catch (Exception ex)

                        {

                            throw new Exception("Error initializing service in isServerPropertiesServiceOperable.", ex);

                        }

                    }

                    else if (svcServerProperties.State == System.ServiceModel.CommunicationState.Opened)

                    {

                        ret = true;

                    }

                }

                else

                {

                    try

                    {

                        initServerPropertiesService();

                        ret = true;

                    }

                    catch (Exception ex)

                    {

                        throw new Exception("Error initializing service in isServerPropertiesServiceOperable.", ex);

                    }

                }

                return ret;

            }

            protected bool isDevicesServiceOperable()

            {

                bool ret = false;

                if(svcDevices != null)

                {

                    if(svcDevices.State == System.ServiceModel.CommunicationState.Faulted)

                    {

                        svcDevices.Abort();

                        contextCleanup();

                        svcDevices = null;

                        try

                        {

                            initDevicesService();

                            ret = true;

                        }

                        catch(Exception ex)

                        {

                            throw new Exception("Error initializing service in isDevicesServiceOperable.", ex);

                        }

                    }

                    else if(svcDevices.State == System.ServiceModel.CommunicationState.Opened)

                    {

                        ret = true;

                    }

                }

                else

                {

                    try

                    {

                        initDevicesService();

                        ret = true;

                    }

                    catch(Exception ex)

                    {

                        throw new Exception("Error initializing service in isDevicesServiceOperable.", ex);

                    }

                }

                return ret;

            }

            protected bool isOutboundServiceOperable()

            {

                bool ret = false;

                if(svcOutbound != null)

                {

                    if(svcOutbound.State == System.ServiceModel.CommunicationState.Faulted)

                    {

                        svcOutbound.Abort();

                        contextCleanup();

                        svcOutbound = null;

                        try

                        {

                            initOutboundService();

                            ret = true;

                        }

                        catch(Exception ex)

                        {

                            throw new Exception("Error intiializing service in isOutboundServiceOperable", ex);

                        }

                    }

                    else if(svcDevices.State == System.ServiceModel.CommunicationState.Opened)

                    {

                        ret = true;

                    }

                }

                else

                {

                    try

                    {

                        initOutboundService();

                        ret = true;

                    }

                    catch(Exception ex)

                    {

                        throw new Exception("Error initializing service in isOutboundServiceOperable", ex);

                    }

                }

                return ret;

            }

            protected bool isServerServiceOperable()

            {

                bool ret = false;

                if (svcServer != null)

                {

                    if (svcServer.State == System.ServiceModel.CommunicationState.Faulted)

                    {

                        svcServer.Abort();

                        contextCleanup();

                        svcServer = null;

                        try

                        {

                            initServerService();

                            ret = true;

                        }

                        catch (Exception ex)

                        {

                            throw new Exception("Error intiializing service in isServerServiceOperable", ex);

                        }

                    }

                    else if (svcServer.State == System.ServiceModel.CommunicationState.Opened)

                    {

                        ret = true;

                    }

                }

                else

                {

                    try

                    {

                        initServerService();

                        ret = true;

                    }

                    catch (Exception ex)

                    {

                        throw new Exception("Error initializing service in isServerServiceOperable", ex);

                    }

                }

                return ret;

            }

            protected bool contextCleanup()

            {

                if (contextCount > 1)

                {

                    contextCount--;

                }

                else if (contextCount == 1 || contextCount == 0)

                {

                    PolicyServiceClient svcTemp = new PolicyServiceClient("NetTcpBinding_IPolicyService", "net.tcp://" + APIaddress + ":7982/AfariaService/Policy");

                    svcTemp.ClientCredentials.Windows.ClientCredential.Domain = APIdomain;

                    svcTemp.ClientCredentials.Windows.ClientCredential.UserName = APIaccount;

                    svcTemp.ClientCredentials.Windows.ClientCredential.Password = APIpassword;

                    svcTemp.InitContext(contextID);

                    svcTemp.CloseContext();

                    contextCount = 0;

                    return true;

                }

                else

                {

                    throw new Exception("We've lost track of our contexts!");

                }

                return false;

            }

            protected Dictionary<string,string> getDeviceProps(AfariaDevices.ClientType deviceType, string deviceID)

            {

                Dictionary<string, string> deviceProps = new Dictionary<string, string>();

                int deviceDBId = -1;

                if (!int.TryParse(deviceID, out deviceDBId))

                {

                    int.TryParse(deviceID.Substring(3), out deviceDBId);

                }

                if (isDevicesServiceOperable() && deviceDBId != -1)

                {

                    AfariaDevices.DevicePropertiesRequest request = new AfariaDevices.DevicePropertiesRequest();

                    request.DBIds = new AfariaDevices.DevicePropertiesId[1];

                    request.DBIds[0] = new AfariaDevices.DevicePropertiesId();

                    request.DBIds[0].ClientType = deviceType;

                    request.DBIds[0].DBId = deviceDBId;

                    request.RequestParameters = new AfariaDevices.DevicePropertiesRequestParameter[1];

                    request.RequestParameters[0] = new AfariaDevices.DevicePropertiesRequestParameter();

                    request.RequestParameters[0].ClientType = deviceType;

                    request.ReturnSchemaClassPropertyDefinitions = false;

                    switch (deviceType)

                    {

                        case AfariaDevices.ClientType.Android:

                            request.RequestParameters[0].ClassPropertiesList = new AfariaDevices.DevicePropertiesRequestClassProperty[2];

                            request.RequestParameters[0].ClassPropertiesList[0] = new AfariaDevices.DevicePropertiesRequestClassProperty();

                            request.RequestParameters[0].ClassPropertiesList[0].ClassName = "General";

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames = new string[4];

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[0] = "IMEI";

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[1] = "Serial number";

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[2] = "Phone number";

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[3] = "Device Model";

                            request.RequestParameters[0].ClassPropertiesList[1] = new AfariaDevices.DevicePropertiesRequestClassProperty();

                            request.RequestParameters[0].ClassPropertiesList[1].ClassName = "Android";

                            request.RequestParameters[0].ClassPropertiesList[1].PropertyNames = new string[1];

                            request.RequestParameters[0].ClassPropertiesList[1].PropertyNames[0] = "Device Maker";

                            break;

                        case AfariaDevices.ClientType.Ios:

                            request.RequestParameters[0].ClassPropertiesList = new AfariaDevices.DevicePropertiesRequestClassProperty[1];

                            request.RequestParameters[0].ClassPropertiesList[0] = new AfariaDevices.DevicePropertiesRequestClassProperty();

                            request.RequestParameters[0].ClassPropertiesList[0].ClassName = "General";

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames = new string[2];

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[0] = "Device Model";

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[1] = "Phone number";

                            break;

                        case AfariaDevices.ClientType.WinPhone:

                            request.RequestParameters[0].ClassPropertiesList = new AfariaDevices.DevicePropertiesRequestClassProperty[1];

                            request.RequestParameters[0].ClassPropertiesList[0] = new AfariaDevices.DevicePropertiesRequestClassProperty();

                            request.RequestParameters[0].ClassPropertiesList[0].ClassName = "Device";

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames = new string[1];

                            request.RequestParameters[0].ClassPropertiesList[0].PropertyNames[0] = "Mobile ID";

                            break;

                        default:

                            throw new Exception("getDeviceProps: Unexpected device type!");

                    }

                    AfariaDevices.DataSetSurrogate dss = svcDevices.GetDeviceProperties(request);

                    switch (deviceType)

                    {

                        case AfariaDevices.ClientType.Android:

                            if ((dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName == "IMEI")

                                && (dss._dataTableSurrogates[0]._dataColumnSurrogates[1]._columnName == "Serial number")

                                && (dss._dataTableSurrogates[0]._dataColumnSurrogates[2]._columnName == "Phone number")

                                && (dss._dataTableSurrogates[0]._dataColumnSurrogates[3]._columnName == "Device Model")

                                && (dss._dataTableSurrogates[1]._dataColumnSurrogates[0]._columnName == "Device Maker")

                                && dss._dataTableSurrogates[0]._records != null

                                && dss._dataTableSurrogates[1]._records != null)

                            {

                                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName

                                    , dss._dataTableSurrogates[0]._records[0][0] != null ?

                                        dss._dataTableSurrogates[0]._records[0][0].ToString()

                                        : string.Empty); //IMEI

                                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[1]._columnName

                                    , dss._dataTableSurrogates[0]._records[1][0].ToString()); //Serial number

                                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[2]._columnName

                                    , dss._dataTableSurrogates[0]._records[2][0].ToString()); //Phone number

                                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[3]._columnName

                                    , dss._dataTableSurrogates[0]._records[3][0].ToString()); //Device model

                                deviceProps.Add(dss._dataTableSurrogates[1]._dataColumnSurrogates[0]._columnName

                                    , dss._dataTableSurrogates[1]._records[0][0].ToString()); //Device maker

                            }

                            break;

                        case AfariaDevices.ClientType.Ios:

                            if ((dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName == "Device Model")

                                && (dss._dataTableSurrogates[0]._dataColumnSurrogates[1]._columnName == "Phone number")

                                && dss._dataTableSurrogates[0]._records != null)

                            {

                                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName

                                    , dss._dataTableSurrogates[0]._records[0][0].ToString()); //Model

                                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[1]._columnName

                                    , dss._dataTableSurrogates[0]._records[1][0].ToString()); //Phone number

                            }

                            break;

                        case AfariaDevices.ClientType.WinPhone:

                            if (dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName == "Mobile ID"

                                && dss._dataTableSurrogates[0]._records != null)

                            {

                                deviceProps.Add(dss._dataTableSurrogates[0]._dataColumnSurrogates[0]._columnName

                                    , dss._dataTableSurrogates[0]._records[0][0] != null ?

                                    dss._dataTableSurrogates[0]._records[0][0].ToString()

                                    : string.Empty); //Mobile ID

                            }

                            break;

                        default:

                            throw new Exception("getDeviceProps: Unexpected returned device type!");

                    }

                }

                return deviceProps;

            }

            protected string[] getServerIDs()

            {

                string[] ret = new string[0];

                if(isServerServiceOperable())

                {

                    AfariaServer.ServerDescription[] servers = svcServer.GetServerList();

                    if(servers != null)

                    {

                        List<string> serverList = new List<string>();

                        string serverMasterID = string.Empty;

                        foreach(AfariaServer.ServerDescription server in servers)

                        {

                            if(server.State == AfariaServer.ServerState.Running)

                            {

                                serverList.Add(server.ServerId);

                                if(server.Role == AfariaServer.ServerRole.Master)

                                {

                                    serverMasterID = server.ServerId;

                                }

                            }

                        }

                        if(serverMasterID != string.Empty)

                        {

                            serverList.Remove(serverMasterID);

                            serverList.Insert(0, serverMasterID);            

                        }

                        ret = serverList.ToArray();

                    }

                }

                return ret;

            }

            protected void setServerID()

            {

                string[] servers = getServerIDs();

                if (servers.Length > 0 && svcServer != null)

                {

                    svcServer.SetServerIdContext(servers[0]);

                }

            }

    #endregion Protected/Private Instance Methods

        }

    }

  • Index.aspx

    Please ignore the <span> tags.

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="index.aspx.cs" Inherits="AfariaAPI201.index" %>

    <!DOCTYPE html>

    <html xmlns="http://www.w3.org/1999/xhtml">

    <head runat="server">

        <title>AfariaAPI-SSP</title>

    </head>

        <body>

            <form id="form1" runat="server">

                <div>

                    <p>

                        <asp:Button ID="ButtonTabEnroll" runat="server" Text="New Device" CommandArgument="0" OnClick="ButtonTabEnroll_Click" />

                        <asp:Button ID="ButtonTabDevices" runat="server" Text="My Devices" CommandArgument="1" OnClick="ButtonTabDevices_Click" />

                    </p>

                </div>

                <div>

                    <asp:Label ID="LabelUserName" runat="server" Text="UserName:"></asp:Label>

                    <asp:TextBox ID="TextBoxUserName" runat="server"></asp:TextBox>

                </div>

                <div>

                    <asp:MultiView ID="MultiViewMain" runat="server">

                        <asp:View ID="ViewEnroll" runat="server">

                            <div>

                                <div>

                                    <asp:Label ID="LabelEmailAddress" runat="server" Text="Email Address:"></asp:Label>

                                    <asp:TextBox ID="TextBoxEmailAddress" runat="server"></asp:TextBox>

                                </div>

                                <div>

                                    <asp:Label ID="LabelClientType" runat="server" Text="Device Type:"></asp:Label>

                                    <asp:DropDownList ID="DropDownListClientType" runat="server" DataSourceID="ObjectDataSourceClientType"></asp:DropDownList>

                                    <asp:ObjectDataSource ID="ObjectDataSourceClientType" runat="server" SelectMethod="getClientTypes" TypeName="AfariaAPI201.AfariaHelper"></asp:ObjectDataSource>

                                </div>

                            </div>

                            <div><asp:Button ID="ButtonGetCode" runat="server" Text="Get Code" OnClick="ButtonGetCode_Click" /></div>

                            <div>

                                <asp:Label ID="LabelUserInstructions" runat="server" Text="" Enabled="False"></asp:Label><br />

                                <asp:HyperLink ID="HyperLinkEnrollmentLink" runat="server" Enabled="False" Visible="False">HyperLink</asp:HyperLink>

                            </div>

                        </asp:View>

                        <asp:View ID="ViewDevices" runat="server">

                            <asp:Button ID="ButtonGetDevices" runat="server" Text="Refresh My Devices List" OnClick="ButtonGetDevices_Click" />

                            <asp:GridView ID="GridViewDeviceSelector" runat="server" CellPadding="4" ForeColor="#333333" GridLines="None" OnSelectedIndexChanged="GridViewDeviceSelector_SelectedIndexChanged">

                            <AlternatingRowStyle BackColor="White" ForeColor="#284775" />

                            <Columns>

                                <asp:CommandField ButtonType="Button" ShowSelectButton="True" />

                            </Columns>

                            <EditRowStyle BackColor="#999999" />

                            <FooterStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />

                            <HeaderStyle BackColor="#5D7B9D" Font-Bold="True" ForeColor="White" />

                            <PagerStyle BackColor="#284775" ForeColor="White" HorizontalAlign="Center" />

                            <RowStyle BackColor="#F7F6F3" ForeColor="#333333" />

                            <SelectedRowStyle BackColor="#E2DED6" Font-Bold="True" ForeColor="#333333" />

                            <SortedAscendingCellStyle BackColor="#E9E7E2" />

                            <SortedAscendingHeaderStyle BackColor="#506C8C" />

                            <SortedDescendingCellStyle BackColor="#FFFDF8" />

                            <SortedDescendingHeaderStyle BackColor="#6F8DAE" />

                        </asp:GridView>

                            <asp:Button ID="ButtonApply" runat="server" OnClick="ButtonApply_Click" Text="Apply Policies" Enabled="False" />

                            <asp:Button ID="ButtonLock" runat="server" OnClick="ButtonLock_Click" Text="Lock" Enabled="False" />

                            <asp:Button ID="ButtonUnlock" runat="server" OnClick="ButtonUnlock_Click" Text="Unlock" Enabled="False" />

                            <asp:Button ID="ButtonRemoveControl" runat="server" OnClick="ButtonRemoveControl_Click" Text="Remove Control" Enabled="False" />

                            <asp:Button ID="ButtonWipe" runat="server" OnClick="ButtonWipe_Click" Text="Wipe Device" Enabled="False" />

                            <asp:Button ID="ButtonDelete" runat="server" OnClick="ButtonDelete_Click" Text="Delete" Enabled="False" />

                            <br />

                        </asp:View>

                    </asp:MultiView>

                </div>

                <div>

                    <br /><br />

                    <asp:Label ID="LabelUserWarning" runat="server" Text="" Font-Bold="True" ForeColor="Red" Enabled="False"></asp:Label>

                </div>

            </form>

        </body>

    </html>