Creating a Client in C# Using WCF
This section explains how to create a WCF web service client for the AAA Server 6.8 SKI Connector service.
Generate the Web Service Client Files
Use the following command line to run svcutil.exe and generate the required web service client files:
-
A .cs file with the necessary client structures and functions.
-
An XML .config file defining the service configuration.
svcutil.exe /language:cs /out:<output_path>\generatedProxy.cs /config:<output_path>\app.config <wsdl_path>\ActivCardSKIConnectorV2.wsdl
Where:
-
<output_path> points to the folder where the generated files are to be stored.
-
<wsdl_path> points to the folder of the .wsdl file.
Configure the Web Service Client
-
Include the generated .cs file in the project.
The generated .cs file contains a class in charge of generating an instance of the client. In this sample, this is the ActivCardSKIConnectorV2SoapClient class.
-
To create a client, an instance of this class must be generated as follows:
CopyActivCardSKIConnectorV2SoapClient client = null;
client = new ActivCardSKIConnectorV2SoapClient();
-
If you want to use the app.config file to define the binding and endpoint URI, include the generated .config file in the project.
- Uri skiConnectorUri to store the endpoint URI.
- EndpointAddress skiConnectorEndpoint to store the skiConnectorUri.
- WSHttpBinding skiConnectorBinding to configure the web service binding.
Alternatively, you can configure the service directly in the code (as in the sample). To do so, add the following variables:
For AAA Server 6.8, the service endpoint URI should be as follows:
http://<hostname>:<port>/ws/ActivCardSKIConnectorV2
-
Modify the client generation code as follows:
CopyskiConnectorUri = new Uri("http://<hostname>:<port>/ws/ActivCardSKIConnectorV2");
skiConnectorBinding = new WSHttpBinding();
skiConnectorBinding.Security.Mode = SecurityMode.None;
skiConnectorEndpoint = new EndpointAddress(skiConnectorUri);
ActivCardSKIConnectorV2SoapClient client = null;
client = new ActivCardSKIConnectorV2SoapClient( skiConnectorBinding, skiConnectorEndpoint);
-
To test the client configuration and connection, it is recommended that you use a simple function such as getVersion().
If getVersion() returns nothing or indicates an error, the endpoint URL might be wrong or using an invalid format.
Use the ActivID SKI Connector Functions
-
To use the ActivID SKI Connector functions, call the corresponding methods of the client with the required variables.
For further information about the method names and input/output variables, refer to ActivID SKI Connector Service API Functions.
-
As most functions can only be used with a valid login handle, retrieve it using the Login() function before performing any other operation.
-
Instantiate and fill a single structure parameter for the inputs.
These structures are declared in the generated header file and should be named _<function_name>In.
-
If the returned value is a structure, it should one defined in the generated .cs file.
The output variables of the SKI Connector are the returned values of the generated functions.
Close the Service
-
Before closing the service, it is recommended that you use the Logout() function to invalidate the login handle.
If you do not, it is only invalidated after a defined time (10 minutes).
-
Use the Close() function to close the web service client:
client.Close();
Configure the Sample for SSL
This section explains how to configure the sample for SSL if the ActivID SKI Connector is using a secured connection.
You can either update the App.config file of the project (as illustrated below) or make the required modifications directly in the C# code.
To use SSL with the ActivID SKI Connector, you must import a client certificate into the certificate store of the local machine.
Modify the endpoint URL to use HTTPS instead of HTTP.
During the AAA Server setup, you can generate two certificates used for the AAA SKI Connector service (SKIConnector.p12) and client (WHD.p12). These certificates are generated in the AAA Server <installdir>\Certificates directory.
-
Define the following elements in the App.config file:
- A binding configuration that sets the security mode to Transport and requires the use of the client Certificate.
- A behavior configuration that defines the following clientCertificate credentials:
- storeLocation – LocalMachine
- storeName – My
- x509FindType – how to search for a certificate (by thumbprint, serial number, subject name etc).
- findValue – the value to be found (for example, certificate_thumbprint).
- An endpoint configuration containing the:
- Endpoint URL
- Binding defined above
- Behavior defined above
-
Remove any C# code that might override the elements defined in the App.config file.
Example of the App.config file configured for SSL:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<!-- behavior configuration -->
<behaviors>
<endpointBehaviors>
<behavior name="customBehavior">
<clientCredentials>
<!-- Endpoint configuration -->
<clientCertificate
findValue="<certificate_thumbprint>"
x509FindType="FindByThumbprint"
storeLocation="LocalMachine"
storeName="My" />
<serviceCertificate>
<authentication
certificateValidationMode="None"
revocationMode="NoCheck" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<!-- Binding configuration -->
<bindings>
<wsHttpBinding>
<binding name="ActivCardSKIConnectorV2Soap">
<security mode="Transport">
<transport clientCredentialType="Certificate"/>
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<!-- Endpoint configuration -->
<client>
<endpoint
address="http://localhost:8200/ws/ActivCardSKIConnectorV2"
binding="wsHttpBinding" bindingConfiguration="ActivCardSKIConnectorV2Soap"
contract="ActivCardSKIConnectorV2Soap" name="ActivCardSKIConnectorV2PortImpl"
behaviorConfiguration="customBehavior">
</endpoint>
</client>
</system.serviceModel>
</configuration>
Error Cases
With the WCF framework, all client function calls might throw an exception if the web service call did not perform correctly. Therefore, you need to wrap each function call in a try-catch.
In addition, most functions have a returned value (often a boolean) indicating if the operation was successful.
Implementation Example
try
{
int nTimeout = 10 * 60 * 1000; /* setting a 10 minutes timeout */
LoginIn loginInParameters = new LoginIn();
loginInParameters.LoginInUid = "<admin_uid>";
loginInParameters.LoginInPwd = "<admin_pwd>";
loginInParameters.LoginInTimeout = nTimeout;
long hLogin = client.Login(loginInParameters);
}
catch (Exception ex)
{
Console.WriteLine("ERROR: Login webservice call failed: {0}", ex.Message);
// Handle error case
}
if (hLogin > 0) Console.WriteLine("Login succeeded.");
else
{
Console.WriteLine("ERROR: invalid credentials.");
// Handle error case
}