Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / productivity / SAP

Integrating SAP Web Services into Microsoft .NET Environments

0.00/5 (No votes)
24 Mar 2011CPOL8 min read 72.4K  
An implementation which enables the end user to choose a Services Registry backend at runtime

Preface

Recently, I started a project on the integration of SAP Web Services in Microsoft's .NET environment. The goal of this project was to write a test program where a user could call SAP Web Services dynamically and to provide the architecture to consume Web Services in environments like Microsoft Office. I documented my experiences in a series of three blogs in the SAP Developer Network. Still, I want to summarize my experiences once more in a more coherent way and want to make the information available not only in the SAP developer community (which is mostly ABAP oriented I assume) but also in the .NET/C# community.

Introduction

The invention of the Service Oriented Architecture (SOA) offers the user the possibility to call Web Services and integrate these into new applications. SAP Developer Network offers a special section for SOA, which can be accessed here.

When I started a prototype project of integrating Web Services into a .NET environment, one of the main challenges was to determine the WSDL and endpoint information of a given Web Service and to make the Web Service independent of the actual backend system - in other words, how to determine the WSDL dynamically at runtime.

Searching for information material for my prototype, I came across numerous articles telling how to determine the WSDL manually if you know a Services Registry system. Examples:

However, all of these examples rely on the knowledge of a well defined backend at design time. My goal was to find an implementation which enables the end user to choose a Services Registry backend at runtime.

For everything that I write below, I assume that a running Services Registry is available. I will not elaborate how to install and set-up a Services Registry. My blog is based on the publicly available Services Registry: http://sr.esworkplace.sap.com.

Services Registry

What is the Services Registry?

The Services Registry is a central server instance in a SOA landscape. In the case of an SAP setup, this will most likely be as well a physical server. In my words, the Services Registry is a kind of a "telephone book" where on the one hand service providers can publish information on a Web Service like:

  • Name of the service
  • Endpoint addresses
  • System information
  • etc.

On the other hand, service consumers can search in the Services Registry for the required information to be able to use the service. Thirdly, the Services Registry provides an API (ServicesRegistrySiPort) which can be used by developers to connect to the Services Registry and to exchange data between their application and the SR.

One more official definition provided by SAP looks like this: "SAP Services Registry (SR) is a part of SAP NetWeaver Composition Environment 7.1 (CE), a UDDI-compliant registry of service definitions available in the repository. It provides API for search and discovery of services, as well as for publishing custom services in the registry, and supports the Web Service Definition Language (WSDL) standard." (see: Anne Tarnoruder: "Introducing SAP Enterprise Services Explorer for Microsoft .NET").

Standard Services Registry in the ES Workplace

As mentioned in the introduction, SAP provides a publicly available Services Registry at the URL http://sr.esworkplace.sap.com. This SR is part of the "ES Workplace" (link: http://esworkplace.sap.com) and gives access to officially published SAP Web Services so a developer can test his/her program with these. To be able to use the services in the ES Workplace SR, you have to have a registered user in the ES Workplace. This user can be requested via an online form. Only after having registered, will you be able to use services from SAP backends with the following SAP functionality (status of March 2011):

  • SAP ERP 6.0 (Ehp4)
  • SAP CRM 7.0
  • SAP SRM 7.0
  • SAP PI 7.1
  • SAP SCM

For more details on the Services Registry in the ES Workplace, please see the SDN article "Services Registry for ESWorkplace" by Harish Mehta, Joerg Dehmel, and Nikolay Kanchev. The Services Registry of ES Workplace and the Services Registry API can be used with a generic test user:

username: sruser
password: eswork123

General Architecture

In principle, it is enough to determine Web Service properties (Web Service URLs) via the SR and to use these endpoints for your service references directly in your program. As I want to go a more dynamic approach, the general architecture is based on determining all Web Service information via the Services Registry. As you can see in the graphic below, all information on the Web Services are retrieved from the Services Registry.

The consuming end-user application was built using the Model-View-Controller pattern, which I based on my blog "Model View Control (MVC) Pattern using C# - A real life example". As I was dealing with a demo application, I did not implement any logic for the actual backend service call. Still, I hope that the information herein is instructive and shows the principles of using the Services Registry API.

For reuse purposes, I decided to encapsulate the Services Registry API logic in a DLL, which abstracts the direct calls to a level, which is convenient for a developer.

Encapsulating the Services Registry API in DLL

Referencing the Services Registry API

To create a DLL, you have to create a new Application Library project in Visual Studio - I assume that you are familiar with this. To incorporate the Services Registry API, create a new Service Reference in your project (click on menu item "Project" -> "Add Service Reference") and a popup will open where you enter the service details:

The Services Registry API has the following connection details:

After clicking "Go", Visual Studio will generate code so the service can be used in your program. Of special interest are the entries in the application configuration file app.config which typically look like this:

It will be our goal to get rid of these entries so we can define the links to the Services Registry at runtime.

app.config Stripping

The most simple way to call the services defined in app.config is by introducing statements like:

C#
ServicesRegistryAPI.ServicesRegistrySiClient theApiClient = 
   new ServicesRegistryAPI.ServicesRegistrySiClient(<app.config-endpointconfigname>);

But then, the URL to the Services Registry API would be hard coded via app.config. Thus, we need to define the binding information programmatically by using statements like:

C#
BasicHttpBinding servicesRegistryBinding = 
  new BasicHttpBinding("ServicesRegistrySiBinding");
//Binding settings
servicesRegistryBinding.Security.Mode = BasicHttpSecurityMode.TransportCredentialOnly;
servicesRegistryBinding.Security.Transport.ClientCredentialType = 
  HttpClientCredentialType.Basic;
//Endpoint address definition
EndpointAddress servicesRegistryEndpointAddress = 
  new EndpointAddress(<servRegEndpointAddress>);

ServicesRegistryAPI.ServicesRegistrySiClient theApiClient = 
  new ServicesRegistryAPI.ServicesRegistrySiClient(servicesRegistryBinding, 
  servicesRegistryEndpointAddress);

Please note that the security settings depend on the configuration of the binding which depends on the actual settings on the server side. The code above works for my demo project but please consider that it is mostly intended for instruction purposes. If the binding of the Services Registry is coded like in my example, we can get rid of the app.config file completely.

DLL Coding

I implemented the main class of the DLL as a singleton following the article "Implementing the Singleton Pattern in C#". The singleton implementation was mostly chosen because I wanted to get/set the attribute _serivceToTest independent of an instance.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;

namespace SoaConnect
{
    public sealed class CSoaConnector : ISoaConnector
    {
        private static CSoaConnector _theSoaConnectorInstance = null;
        static readonly object padlock = new object();

        private ServicesRegistryAPI.ServicesRegistrySiClient 
                theServicesRegistrySiClient;

        private string _serviceToTest;
        public string serviceToTest
        {
            get { return _serviceToTest; }
            set { _serviceToTest = value; }
        }

        public static CSoaConnector Instance
        {
            get
            {
                lock (padlock)
                {
                    if (_theSoaConnectorInstance == null)
                    {
                        _theSoaConnectorInstance = new CSoaConnector();
                    }
                    return _theSoaConnectorInstance;
                }
            }
        }

        /// <summary>
        /// Constructor
        /// </summary>
        public CSoaConnector() { }

        public ServicesRegistryAPI.ServicesRegistrySiClient 
               getServicesRegistryClient(string servRegEndpointAddress, 
               string userName, string password)
        {
            BasicHttpBinding servicesRegistryBinding = 
              new BasicHttpBinding("ServicesRegistrySiBinding");

            //security settings
            servicesRegistryBinding.Security.Mode = 
              BasicHttpSecurityMode.TransportCredentialOnly;
            servicesRegistryBinding.Security.Transport.ClientCredentialType = 
              HttpClientCredentialType.Basic;

            //Endpoint address definition
            EndpointAddress servicesRegistryEndpointAddress = 
              new EndpointAddress(servRegEndpointAddress);

            ///Initialize Service Registry Client
            theServicesRegistrySiClient = new 
              ServicesRegistryAPI.ServicesRegistrySiClient(
              servicesRegistryBinding, servicesRegistryEndpointAddress);
            ///Login settings
            theServicesRegistrySiClient.ClientCredentials.
              HttpDigest.AllowedImpersonationLevel = 
              System.Security.Principal.TokenImpersonationLevel.Impersonation;
            theServicesRegistrySiClient.ClientCredentials.
              HttpDigest.ClientCredential.UserName = userName;
            theServicesRegistrySiClient.ClientCredentials.
              HttpDigest.ClientCredential.Password = password;
            theServicesRegistrySiClient.ClientCredentials.UserName.UserName = userName;
            theServicesRegistrySiClient.ClientCredentials.UserName.Password = password;

            return theServicesRegistrySiClient;
        }

        public ServicesRegistryAPI.findServiceDefinitionsResponse 
               getFindServiceDefinition(string serviceName, string remoteSystemID)
        {
            // Prepare search attributes to retrieve information
            // on local settings of Web Services
            ServicesRegistryAPI.serviceDefinitionSearchAttributes 
              theSearchAttributes = 
              new ServicesRegistryAPI.serviceDefinitionSearchAttributes();

            //Add Service Name to search
            theSearchAttributes.name = serviceName;

            //Add System ID to Search
            if (remoteSystemID != "")
            {
                string[] systemIDs = new string[1];
                systemIDs[0] = remoteSystemID;
                theSearchAttributes.physicalSystemSldIDs = systemIDs;
            }

            ServicesRegistryAPI.findServiceDefinitions findServiceDefinitions = 
              new ServicesRegistryAPI.findServiceDefinitions();
            findServiceDefinitions.serviceDefinitionSearchAttributes = theSearchAttributes;

            ServicesRegistryAPI.findServiceDefinitionsResponse 
              theServiceDefinitionResponse = 
              theServicesRegistrySiClient.findServiceDefinitions(findServiceDefinitions);

            return theServiceDefinitionResponse;
        }

        public ServicesRegistryAPI.findServiceDefinitionsResponse 
               getServiceDefinitions(string searchParameter)
        {
            ServicesRegistryAPI.findServiceDefinitions theFindServiceDefinition = 
              new ServicesRegistryAPI.findServiceDefinitions();
            theFindServiceDefinition.serviceDefinitionSearchAttributes = 
              new ServicesRegistryAPI.serviceDefinitionSearchAttributes();
            theFindServiceDefinition.serviceDefinitionSearchAttributes.name = searchParameter;
            ServicesRegistryAPI.findServiceDefinitionsResponse 
              theServiceDefinitionResponse = 
              new ServicesRegistryAPI.findServiceDefinitionsResponse();
            theServiceDefinitionResponse = 
              theServicesRegistrySiClient.findServiceDefinitions(theFindServiceDefinition);
            theFindServiceDefinition.serviceDefinitionSearchAttributes.maxRows = 
              theServiceDefinitionResponse.@return.listDescription.actualCount;
            theServiceDefinitionResponse = 
              theServicesRegistrySiClient.findServiceDefinitions(theFindServiceDefinition);
            return theServiceDefinitionResponse;
        }
    }
}

error CS0030: Cannot convert type

When making the call to determine the Web Service configuration, the code consists of just one line:

C#
//Call Services Registry and get local Info to a service
ServicesRegistryAPI.findServiceDefinitionsResponse theServiceDefinitionResponse = 
   theServicesRegistrySiClient.findServiceDefinitions(findServiceDefinitions);

This line causes a system error "CS0030: Cannot convert type for ...classificationPair[] ...classificationPair". The solution to this error is documented in David Klein's Blog, which recommends to replace the entries like "classificationPair[][]" with "classificationPair[]" in the file references.cs in the .NET software project.

Services Registry API Added Statically

Please note the variables starting with the namespace "ServicesRegistryAPI". These references belong to a static services reference to the Services Registry API which has to be added to your project at design time.

ISoaConnector - Interface to CSoaConnector

The interface to CSoaConnector is quite narrow:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SoaConnect
{
    public interface ISoaConnector
    {
        string serviceToTest { get; set; }
        ServicesRegistryAPI.ServicesRegistrySiClient getServicesRegistryClient(
           string servRegEndpointAddress, string userName, string password);
        ServicesRegistryAPI.findServiceDefinitionsResponse 
           getFindServiceDefinition(string serviceName, string remoteSystemID);
        ServicesRegistryAPI.findServiceDefinitionsResponse 
           getServiceDefinitions(string searchParameter);
    }
}

DLL Consumer - The Demo Application

The demo program enables a user to enter the URL to a Services Registry API, user name, and password settings. By clicking on "Connect", the program connects to the Services Registry - here is where you need the singleton... After having connected to the SR, the user can enter a string as a search criterion ("Service Name to Search For") and by hitting "Search for Services", the system returns the services matching the search criteria. These services are listed in the dropdown box "Services Available in Services Registry", where the user can choose one. Below, the program displays some basic information on the service chosen by the user. The UI is fairly simple:

MVC - View

I based my Model View Controller on another article of mine in c-sharpcorner.com, which is an addendum to Matthew Cochran's blog: "Introduction to Model View Control (MVC) Pattern using C". The view behind the scenes is straightforward:

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;

namespace SOA_Test
{
    public partial class FormMainWindow : Form, IMainWindow_View
    {
        private CSettingsFile theSettingsFileHandler;
        public FormMainWindow()
        {
            theSettingsFileHandler = new CSettingsFile();
            this.initialize(theMainWindowController, theMainWindowModel);
            InitializeComponent();
            string[] systemURLs = theSettingsFileHandler.getSystemURLs();
            this.comboBox_SystemUrl.DataSource = systemURLs;
        }

        #region MVC related stuff
        private IMainWindow_Controller theMainWindowController = 
                            new CMainWindow_Controller();
        private IMainWindow_Model theMainWindowModel = new CMainWindow_Model();

        public void initialize(IMainWindow_Controller inMainWindowController, 
                               IMainWindow_Model inMainWindowModel)
        {

            if (theMainWindowModel != null) {}

            theMainWindowModel = inMainWindowModel;
            theMainWindowController = inMainWindowController;
            theMainWindowController.setModel(theMainWindowModel);
            theMainWindowController.setView(this);
            theMainWindowModel.addObserverView(this);

        }

        public void addObserver(IMainWindow_Controller inMainWindowController)
        {

            this.theMainWindowController = inMainWindowController;

        }

        public void updateUserInterface(IMainWindow_Model 
                    inMainWindowModel, object sender)
        {
        }

        #endregion

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            ComponentResourceManager theResourceManager = 
              new ComponentResourceManager(typeof(FormMainWindow));
            //this.toolStripSplitButton_MainWindow.Image = 
            //   (Bitmap)theResourceManager.GetObject(
            //    "Sphere_SAP_Warning_Red_Opaque.png");
            CConstants.userSettings theUserSettings;
            theUserSettings.systemURL = this.comboBox_SystemUrl.Text;
            theUserSettings.userName = this.textBoxUserName.Text;
            theUserSettings.password = this.textBoxPassword.Text;
            theMainWindowController.buttonConnect_Click(theUserSettings);
            this.label_Status.Text = "Connected";
            this.pictureBox_Status.Image = 
              (Bitmap)theResourceManager.GetObject("Sphere_SAP_Warm_Green_Opaque.png");
            this.button_SearchForService.Enabled = true;
        }

        private void FormMainWindow_Load(object sender, EventArgs e)
        {
        }

        private void comboBox_SystemUrl_TextChanged(object sender, EventArgs e)
        {
            CConstants.userSettings theUserSettings = 
              theMainWindowController.comboBox_SystemUrl_TextChanged(
              this.comboBox_SystemUrl.Text);
            this.textBoxUserName.Text = theUserSettings.userName;
            this.textBoxPassword.Text = theUserSettings.password;
        }

        private void button_TestService_Click(object sender, EventArgs e)
        {
            while ( this.comboBox_UddiKeys.Items.Count != 0)
            {
                this.comboBox_UddiKeys.Items.RemoveAt(0);
            }
            SoaConnect.ServicesRegistryAPI.serviceDefinitionInfo[] 
            serviceDefinitionInfos = theMainWindowController.testService(
                                     this.comboBox_ServiceNames.Text);
            this.textBox_NumberOfHits.Text = serviceDefinitionInfos.Count().ToString();

            string[] uddiKeyList = new string[0];
            int arrayCounter = uddiKeyList.Count();

            foreach (SoaConnect.ServicesRegistryAPI.serviceDefinitionInfo 
                     serviceDefinitionInfo in serviceDefinitionInfos)
            {
                arrayCounter++;
                Array.Resize(ref uddiKeyList, arrayCounter);
                uddiKeyList[arrayCounter - 1] = serviceDefinitionInfo.key;
            }
            this.comboBox_UddiKeys.Items.AddRange(uddiKeyList);
            this.comboBox_UddiKeys.SelectedIndex = 0;
            
            if (serviceDefinitionInfos[0].configState != null)
            {
                this.textBox_ConfigState.Text = serviceDefinitionInfos[0].configState;
            }
            else { this.textBox_ConfigState.Text = "Not Defined"; }

            this.textBox_ServiceDesc.Text = serviceDefinitionInfos[0].description[0].text;
        }

        private void button_SearchForService_Click(object sender, EventArgs e)
        {
            string searchParameter;
            if (this.textBox_SearchString.Text != "")
            {
                searchParameter = this.textBox_SearchString.Text;
            }
            else { searchParameter = "*"; }
            while (this.comboBox_ServiceNames.Items.Count != 0)
            {
                this.comboBox_ServiceNames.Items.RemoveAt(0);
            }
            this.comboBox_ServiceNames.Items.AddRange(
              theMainWindowController.getServiceDefinitions(searchParameter));
            this.comboBox_ServiceNames.SelectedIndex = 0;
            this.comboBox_ServiceNames.Enabled = true;
            this.comboBox_UddiKeys.Enabled = true;
        }

        private void comboBox_ServiceNames_SelectedValueChanged(object sender, EventArgs e)
        {
            while ( this.comboBox_UddiKeys.Items.Count != 0)
            {
                this.comboBox_UddiKeys.Items.RemoveAt(0);
            }
            SoaConnect.ServicesRegistryAPI.serviceDefinitionInfo[] serviceDefinitionInfos = 
              theMainWindowController.testService(this.comboBox_ServiceNames.Text);
            this.textBox_NumberOfHits.Text = serviceDefinitionInfos.Count().ToString();

            string[] uddiKeyList = new string[0];
            int arrayCounter = uddiKeyList.Count();

            foreach (SoaConnect.ServicesRegistryAPI.serviceDefinitionInfo 
                     serviceDefinitionInfo in serviceDefinitionInfos)
            {
                arrayCounter++;
                Array.Resize(ref uddiKeyList, arrayCounter);
                uddiKeyList[arrayCounter - 1] = serviceDefinitionInfo.key;
            }
            this.comboBox_UddiKeys.Items.AddRange(uddiKeyList);
            this.comboBox_UddiKeys.SelectedIndex = 0;
            
            if (serviceDefinitionInfos[0].configState != null)
            {
                this.textBox_ConfigState.Text = serviceDefinitionInfos[0].configState;
            }
            else { this.textBox_ConfigState.Text = "Not Defined"; }

            this.textBox_ServiceDesc.Text = serviceDefinitionInfos[0].description[0].text;
        }
    }
}

MVC - Controller

As I only wanted to get my little app running, I did not implement any serious logic here. Basically, I only route user events from the View down to the Model:

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace SOA_Test
{
    class CMainWindow_Controller : IMainWindow_Controller
    {
        #region MVC related part
        #region Attributes
        IMainWindow_Model theMainWindowModel;
        IMainWindow_View theMainWindowView;
        #endregion

        public CMainWindow_Controller(IMainWindow_Model inMainWindowModel, 
                                      IMainWindow_View inMainWindowView)
        {
            this.theMainWindowModel = inMainWindowModel;
            this.theMainWindowView = inMainWindowView;
        }

        public CMainWindow_Controller()
        {
        }

        public void setModel(IMainWindow_Model inMainWindowModel)
        {
            this.theMainWindowModel = inMainWindowModel;
        }

        public void setView(IMainWindow_View inMainWindowView)
        {
            this.theMainWindowView = inMainWindowView;
        }
        #endregion

        public CConstants.userSettings comboBox_SystemUrl_TextChanged(string systemURL)
        {
            return theMainWindowModel.comboBox_SystemUrl_TextChanged(systemURL);
        }

        public void buttonConnect_Click(CConstants.userSettings inUserSettings)
        {
            theMainWindowModel.buttonConnect_Click(inUserSettings);
        }

        public string[] getServiceDefinitions(string searchParameter)
        {
            return theMainWindowModel.getServiceDefinitions(searchParameter);
        }

        public SoaConnect.ServicesRegistryAPI.serviceDefinitionInfo[] 
               testService(string serviceName)
        {
            return theMainWindowModel.testService(serviceName);
        }
    }
}

MVC - Model

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SoaConnect;

namespace SOA_Test
{
    class CMainWindow_Model : IMainWindow_Model
    {

        #region MVC initialize
        IMainWindow_View theMainWindowView;

        public CMainWindow_Model()
        {
        }

        public void addObserverView(IMainWindow_View inMainWindowView)
        {
            theMainWindowView = inMainWindowView;
        }

        public void notifyObserverView()
        {
            theMainWindowView.updateUserInterface(this, null);
        }
        #endregion

        private CSettingsFile _theSettingsFileHandler;
        public CSettingsFile theSettingsFileHandler
        {
            get {
                if (_theSettingsFileHandler == null) {
                    _theSettingsFileHandler = new CSettingsFile();
                }
                return _theSettingsFileHandler; 
            }

            set {
                if (_theSettingsFileHandler == null)
                {
                    _theSettingsFileHandler = new CSettingsFile();
                }
                _theSettingsFileHandler = value; 
            }
        }

        public void buttonConnect_Click(CConstants.userSettings inUserSettings)
        {
            theSettingsFileHandler.theUserSettings = inUserSettings;
            theSettingsFileHandler.updateCurrentUserSettingsDoc();
            theSettingsFileHandler.saveCurrentUsersettings();
            SoaConnect.CSoaConnector.Instance.getServicesRegistryClient(
              inUserSettings.systemURL, inUserSettings.userName, 
              inUserSettings.password);
        }

        public CConstants.userSettings comboBox_SystemUrl_TextChanged(string systemURL)
        {
            CConstants.userSettings theUserSettings = new CConstants.userSettings();
            theUserSettings.userName = 
              theSettingsFileHandler.getUserSettingsForSystem(systemURL).userName;
            theUserSettings.password = 
              theSettingsFileHandler.getUserSettingsForSystem(systemURL).password;
            theUserSettings.systemURL = systemURL;
            return theUserSettings;
        }

        public string[] getServiceDefinitions(string searchParameter)
        {
            string[] theServiceNames = new string[0];
            int arraySize = theServiceNames.Count();

            SoaConnect.ServicesRegistryAPI.findServiceDefinitionsResponse 
              theServiceDefinitions = 
              SoaConnect.CSoaConnector.Instance.getServiceDefinitions(searchParameter);
            SoaConnect.ServicesRegistryAPI.serviceDefinitionInfo[] 
              theServiceDefinitionInfoList = 
              theServiceDefinitions.@return.serviceDefinitionInfos;
            foreach (SoaConnect.ServicesRegistryAPI.serviceDefinitionInfo 
                     serviceDefinitionInfo in theServiceDefinitionInfoList)
            {
                arraySize++;
                Array.Resize(ref theServiceNames, arraySize);
                theServiceNames[arraySize - 1] = serviceDefinitionInfo.name;
            }

            return theServiceNames;
        }

        public SoaConnect.ServicesRegistryAPI.serviceDefinitionInfo[] 
               testService(string serviceName)
        {
            SoaConnect.ServicesRegistryAPI.findServiceDefinitionsResponse 
               serviceDefinition = 
               SoaConnect.CSoaConnector.Instance.getFindServiceDefinition(
               serviceName, "");
            return serviceDefinition.@return.serviceDefinitionInfos;
        }
    }
}

Please note that I did not note down the interface definitions for the View, Controller, and Model.

CSettingsFile - Class to Read / Write User Settings

This class is used to write the connection data entered by the user in the UI to a configuration file. These data are read from the file and pre-fill the connection parameters at program start.

C#
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Linq;
using System.Security.Principal;

namespace SOA_Test
{
    class CSettingsFile
    {
        private XDocument userSettingsDocument;
        private string appDirectory = Path.GetDirectoryName(Application.ExecutablePath);
        private string userSettingsPath = "";
        private string currentUserName = WindowsIdentity.GetCurrent().Name;

        private CConstants.userSettings _theUserSettings;
        public CConstants.userSettings theUserSettings
        {
            get { return _theUserSettings; }
            set { _theUserSettings = value; }
        }

        #region public methods
        public CSettingsFile() {
            userSettingsPath = appDirectory + "\\UserSettings.xml";
            ///Open user settings file, if file not available, create new xml document
            userSettingsDocument = new XDocument();
            try { userSettingsDocument = XDocument.Load(userSettingsPath); 
            }
            catch (FileNotFoundException) {
                userSettingsDocument = createNewUserSettingsDocument();
            }
        }

        public CConstants.userSettings getSettingsForSystem(string systemURL) {

            XElement settingsForUser = null;
            IEnumerable<XElement> settingsForUserList;
            CConstants.userSettings theUserSettings;

            theUserSettings.systemURL = systemURL;

            try
            {
                settingsForUserList =
                    userSettingsDocument
                    .Descendants(CConstants.XElementName_UserSettings)
                    .Where(test => test.Element(
                      CConstants.XElementName_UserName).Value == currentUserName);
            }
            catch { settingsForUserList = null; }

            if (settingsForUserList.Count() == 1) {
                settingsForUser = settingsForUserList.ElementAt(0);
            }
            else {
            }

            XElement userSettingsForSystem =
                settingsForUser.Element(CConstants.XElementName_ServiceRegURLs);

            theUserSettings.userName = 
              userSettingsForSystem.Element(CConstants.XElementName_UserName).Value;
            theUserSettings.password = 
              userSettingsForSystem.Element(CConstants.XElementName_Password).Value;

            return theUserSettings;
        }

        public string[] getSystemURLs() {

            string[] systemURLArray = null;
            int systemURLArraySize = 0;

            IEnumerable<XElement> systemURLList = 
                userSettingsDocument
                .Descendants(CConstants.XElementName_UserSettings)
                .Elements(CConstants.XElementName_ServiceRegURLs);

            foreach (XElement systemURL in systemURLList)
            {
                if (systemURL.Attribute(CConstants.XAttribute_Value).Value != "")
                {
                    systemURLArraySize++;
                    Array.Resize(ref systemURLArray, systemURLArraySize);
                    systemURLArray[systemURLArraySize - 1] = 
                      systemURL.Attribute(CConstants.XAttribute_Value).Value;
                }
            }

            return systemURLArray;
        }

        public CConstants.userSettings getUserSettingsForSystem(string theSystemURL)
        {
            XElement userSettingsForSystem = null;
            CConstants.userSettings localUserSettings;
            localUserSettings.systemURL = "";
            localUserSettings.userName = "";
            localUserSettings.password = "";

            XElement currentUserSettings =
                userSettingsDocument
                .Descendants(CConstants.XElementName_UserSettings)
                .Where(test => test.Attribute(
                   CConstants.XAttribute_Value).Value == currentUserName)
                .ElementAt(0);

            if (currentUserSettings != null)
            {
                try
                {
                    userSettingsForSystem =
                        currentUserSettings
                        .Descendants(CConstants.XElementName_ServiceRegURLs)
                        .Where(test => test.Attribute(
                           CConstants.XAttribute_Value).Value == theSystemURL)
                        .ElementAt(0);
                }
                catch { }
            }

            if (userSettingsForSystem != null)
            {
                localUserSettings.systemURL = 
                  userSettingsForSystem.Attribute(
                  CConstants.XAttribute_Value).Value;
                localUserSettings.userName = 
                  userSettingsForSystem.Element(
                  CConstants.XElementName_UserName).Attribute(
                  CConstants.XAttribute_Value).Value;
                localUserSettings.password = userSettingsForSystem.Element(
                  CConstants.XElementName_Password).Attribute(
                  CConstants.XAttribute_Value).Value;
            }

            return localUserSettings;
        }

        public void updateCurrentUserSettingsDoc()
        {

            XElement currentUserElement = 
              new XElement(CConstants.XElementName_UserSettings);
            XElement currentSystemElement = 
              new XElement(CConstants.XElementName_ServiceRegURLs);

     &np;      try
            {
                currentUserElement =
                    userSettingsDocument
                    .Descendants(CConstants.XElementName_UserSettings)
                    .Where(test => test.Attribute(
                      CConstants.XAttribute_Value).Value == 
                      currentUserName).ElementAt(0);
            }
            catch { }

            if (currentUserElement != null)
            {
                try {
                    currentSystemElement =
                        currentUserElement
                        .Elements(CConstants.XElementName_ServiceRegURLs)
                        .Where(test => 
                           test.Attribute(CConstants.XAttribute_Value).Value == 
                           theUserSettings.systemURL).ElementAt(0);
                }
                catch (ArgumentOutOfRangeException) {
                    ///URL Entry does not exist --> create one
                    currentUserElement.Add(new XElement(
                        CConstants.XElementName_ServiceRegURLs, 
                        new XAttribute(CConstants.XAttribute_Value, 
                                       theUserSettings.systemURL),
                        new XElement(CConstants.XElementName_UserName, 
                        new XAttribute(CConstants.XAttribute_Value, 
                                       theUserSettings.userName)),
                        new XElement(CConstants.XElementName_Password, 
                        new XAttribute(CConstants.XAttribute_Value, 
                                       theUserSettings.password))));
                }
            }
        }

        public void saveCurrentUsersettings() {
            userSettingsDocument.Save(userSettingsPath);
        }
        #endregion

        #region private methods
        private XElement createNewUserElement()
        {
            XElement theUserXElement = 
                new XElement(CConstants.XElementName_UserSettings,
                new XAttribute(CConstants.XAttribute_Value, currentUserName));

            return theUserXElement;
        }

        private XDocument createNewUserSettingsDocument() {
            XDocument theUserSettings = new XDocument(
                new XDeclaration("1.0", "UTF-8", "false"),
                new XElement(CConstants.XElementName_UserSettingsRoot));

            theUserSettings.Element(
              CConstants.XElementName_UserSettingsRoot).Add(createNewUserElement());

            return theUserSettings;
        }
        #endregion
    }
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)