C# Web Services clients

This section contains step-by-step instructions and sample code for creating C# Web Services clients that access the SA API.

Required software for C# clients

To develop C# Web Services clients, your development environment must have the following software:

  • Microsoft .NET Framework SDK version 1.1
  • C# client stubs for SA API

Obtaining the C# client stubs

SA provides a stub file for each service, for example, FolderService.cs. All stubs have the same namespace: OpswareWebServices. In addition to the stubs, SA provides shared.cs, the file that contains shared classes such as ServerRef.

To obtain a ZIP file containing the C# stubs, specify the following URL, where occ_host is the core server running the OCC component:

https://occ_host:1032/twister/opswcsharpclient.zip

The constants defined in services and objects are not defined in the C# stubs. To get information about the constants, use the API documentation (javadocs), as described in Constant field values.

Building the C# demo program

To build the demo program:

  1. From the support site, obtain the SA_Platform_Developer_Guide_examples.zip file bundled with the All Manuals Download SA 10.5 folder. For information about downloading the demo file see, Platform Developer Guide examples.

    The SA_Platform_Developer_Guide_examples.zip contains the following demo program files at the SA_Platform_Developer_Guide_examples\api_examples\web_services\csharp location:
    • App.config - Application settings
    • WebServicesDemo.cs - Client code that invokes service methods
    • MyCertificateValidation.cs - Certificate validation class
  2. Create the following directory:
    C:\wsapi
  3. From the Visual Studio 2008 Start Page, select New Project and create a project with the following values:
    • Project Type: Visual C# Projects
    • Template: Console Application
    • Name: WSAPIDemo
    • Location: C:\wsapi

    This action creates the new directory C:\wsapi\WSAPIDemo, which contains some files.

  4. In the new project, delete the default program and AssemblyInfo.cs from the list of objects.
  5. Copy the files you obtained in step 1 into the C:\wsapi\WSAPIDemo directory.
  6. Download the client stubs from the URL specified in Obtaining the C# client stubs.
  7. Copy the C# client stubs into the C:\wsapi\WSAPIDemo directory.
  8. Add the files copied in the preceding two steps to the WSAPIDemo project:
    • In Visual Studio, from the Project menu, select Add Existing Item.
    • Browse to the directory C:\wsapi\WSAPIDemo, and select all the demo files (.cs and .config).
  9. Add a reference to System.Web.Services.dll:
    • In Visual Studio, from the Project menu, select Add Reference.
    • Under the .NET tag, browse to Component with Name: System.Web.Services.dll.
    • Click System.Web.Services.dll, click Select, and then click OK.
  10. If you used a different template when creating the project, you might need to add references to System, System.XML, and System.Data. Check the Project References to determine if you need to add these references.
  11. In the App.config file, change the values for username, password, host, and the hardcoded object IDs such as serverID.
  12. In Visual Studio, from the Build menu, select Build WSAPIDemo.

Caution If the target core is running a minimum protocol version of TLSv1.x, the Powershell version (the bound underlying .NET Framework version) must support it. For more information see, https://msdn.microsoft.com/en-us/library/system.net.securityprotocoltype(v=vs.110).aspx

Also, it must be explicitly enabled from the C# application.

Code sample: System.Net.ServicePointManager.SecurityProtocol |= System.Net.SecurityProtocolType.Tls12 | System.Net.SecurityProtocolType.Tls11;"

Running the C# demo program

To run the demo program:

  1. Open the Visual Studio 2008 command prompt:

    Start > All Programs > Microsoft Visual Studio 2008 >
    Visual Studio Tools > Visual Studio 2008 Command Prompt
  2. Change the directory to:

    C:\wsapi\WSAPIDemo\bin\Debug
  3. Enter the following command:

    WSAPIDemo.exe

Sample C# code

The following code snippets are from WebServicesDemo.cs, a C# program contained in the Zip file you downloaded previously.

Set up certificate handling

# This setup is required just once for the client.
#
ServicePointManager.CertificatePolicy = new MyCertificateValidation();

Assign the URL prefix

# This is the URL prefix for all services.
#
wsdlUrlPrefix = protocol + "://" + host + ":" + port + "/" + contextUri + "/";

Initiate the service

FolderService fs = new FolderService();
fs.Url = wsdlUrlPrefix + "com.opsware.folder/FolderService";

Invoke service methods

FolderRef root = fs.getRoot();
FolderVO vo = fs.getFolderVO(root);

Handle interface return types

            # In the API, FolderVO.getMembers returns an array of
# FNodeReference interfaces, but Web Services does not support
# interfaces. In the C# stub, the return type of
# FolderVO.members is Object[]. If a returned Object type will
# be used as a parameter that must be a specific type, then you
# must cast it to that type. For example, the following code
# casts elements of the returned array to FolderRef as
# appropriate.
#
Object[] members = vo.members;
for(int i=0;i<members.Length;i++)
{
Console.WriteLine("Got object: " + members[i].GetType().FullName + " --> " +
((ObjRef)members[i]).name);
	if(members[i] is FolderRef) {
	Console.WriteLine("I am a FolderRef: " +
	((FolderRef)members[i]).name);
	}
}
        

Update or create a VO

            # When updating a VO, the changed attributes must be set in
# dirtyAttributes. (The VO passed to a create method has
# the same requirement.)
#
# Note: If you update a VO that was returned from a service
# method invocation, such as getFolderVO, then you must
# set the logChange attribute of the VO to false:
# vo.logChange = false;
#
# The following code changes the name of a folder.
#
Console.WriteLine("Changing name from " + vo.name +
" to yo_csharp.");
vo.name = "yo_csharp";
vo.dirtyAttributes = new String[]{"name"};
# Manually set dirty fields being changed.
#
vo = fs.update(folder, vo, true, true);
Console.WriteLine("Folder name changed to: " + vo.name);
        

Handle exceptions

            # .NET converts Web Services faults into SoapExceptions
# without trying to deserialize them into application
# exceptions first. As a result, your code cannot catch
# application exceptions. As a workaround, the C# stubs
# provided by SA include SOAPExceptionParser,
# a class that enables you to get information from
# SOAPExceptions. The following code shows how to get the
# exception name and error message by calling the getDetail
# method of SOAPExceptionParser.
#
try{
// Try to get a non-existent folder here.
} catch(SoapException e){
	SoapExceptionDetail detail =
	SoapExceptionParser.getDetail(e);
	Console.WriteLine("SoapExceptionDetail.name: " +
	detail.exceptionName);
	Console.WriteLine("SoapExceptionDetail.msg: " +
	detail.message);
...
}
        

Password security with C#

The FolderService method reads the user and password pair from the file App.config. The following shows an example of this method.

            User user = new User();
user.username = "user";
user.password = "password";
FolderService fs = new FolderService();
fs.Url = wsdlUrlPrefix + "com.opsware.folder/FolderService";
fs.user = user;
        

If you do not want to store the password in clear text in the App.config file, you can use the SecureUser class to encrypt the password. The SecureUser class uses the C# SecureString in .NET 2.0. Passwords are stored encrypted in a SecureString. Furthermore, the getPassword() method is only visible internally. SecureUser is a static class, so you only need to set your user name and password once or each time you switch users.

Each service retrieves the user name and password from SecureUser first and then its user member variable and then App.config, for backward compatibility. SecureUser takes either a String or a SecureString for the password. In either case, clients are responsible to clean up the password variable passed to the SecureUser.setUser() method.

At some point the password will need to be converted to a regular C# string in memory, which will only get freed when the next garbage collection occurs. Using SecureUser will only ensure internal password storage is secure.

The following example shows how to set the user name and password securely.

            SecureString passwd = new SecureString();
passwd.AppendChar('p');
passwd.AppendChar('a');
passwd.AppendChar('s');
passwd.AppendChar('s');
passwd.AppendChar('w');
passwd.AppendChar('d');
SecureUser.setUser("username", passwd); // that's it, no need to set up user
for each service.
passwd.Dispose(); // resets passwd and frees up memory so no copy remains from
caller.