Publish, Discover and Invoke Web Services using SOAP and UDDI

Introduction
The project contains code that allows to Describe, Discover and Invoke a web service in .NET using SOAP SDK 3.0 and UDDI SDK 2.0 beta on .NET SDK 1.1.

Background
UDDI (Universal Description Discovery and Integration) is a standard that defines common registry where web service providers register themselves and describe/publish their services and details thereof including the URIs to access services. The authority that provides centralised UDDI services is known as Business Registry Node. There could be a public or private node, public being accessible to everyone over the internet. Some commonly used public nodes include microsoft (uddi.microsoft.com), IBM, SAP and others. We'll be making use of Microsoft Test UDDI node (test.uddi.microsoft.com) for our testing purposes. The public UDDI node can be searched by an API that conforms with a UDDI specification set by UDDI.org. e.g. Microsoft's UDDI SDK 2.0 beta can be used in .NET environment to make inquiry and publish requests to microsoft uddi site.

SOAP (Simple Object Access Protocol) is a communication standard based on XML and used in communications between web service calls. Microsoft's SOAP SDK facilitates to invoke web service methods without creating a proxy class for the web service. We'll be making use of SOAP SDK 3.0 for our testing environment.

Code Usage
As discussed earlier, we'll communicate with microsoft's test uddi node, in order to publish our business and services we need to have a passport ID and need to register ourselves as a service provider manually at the https://test.uddi.microsoft.com/register.aspx . I'm going to use a web service written by someone that converts/translates the supplied string to a funny word.

Following are related to UDDI and SOAP SDKs

using Microsoft.Uddi;
using Microsoft.Uddi.Api;
using MSSOAPLib30;

After including the appropriate namespaces, define the initial parameters.

string passportUserId="uddisoap@hotmail.com",
passportPassword=@"/find?\//",
inquireUrl="https://test.uddi.microsoft.com/inquire",
publishUrl="https://test.uddi.microsoft.com/publish", //mind the HTTPS for
publishing
webService=
"https://www.aspxpressway.com/maincontent/webservices/piglatin.asmx"; string serviceProvider= "SOAP UDDI WS
Testers";
//our test service provider name

Publishing a service provider and the service.

private void publish_Click(object sender, System.EventArgs e)
{
try
{
Publish.Url = publishUrl;
Publish.User = passportUserId;
Publish.Password = passportPassword;

SaveBusiness sb = new SaveBusiness();

sb.BusinessEntities.Add();
sb.BusinessEntities[0].Names.Add(serviceProvider);

sb.BusinessEntities[0].Descriptions.Add("en", "This business is all about testing web services.");

sb.BusinessEntities[0].CategoryBag.Add("Washington", "US-WA", "uuid:4e49a8d6-d5a2-4fc2-93a0-0411d8d19e88");

// Add contact details for responsible/support people
sb.BusinessEntities[0].Contacts.Add();
sb.BusinessEntities[0].Contacts[0].PersonName = "Sumit Amar";
sb.BusinessEntities[0].Contacts[0].UseType = "Programmer";
sb.BusinessEntities[0].Contacts[0].Addresses.Add("#code", "PBMS");
sb.BusinessEntities[0].Contacts[0].Addresses[0].AddressLines.Add("35 Downing Street");
sb.BusinessEntities[0].Contacts[0].Addresses[0].AddressLines.Add("New London");
sb.BusinessEntities[0].Contacts.Add("Veronica","CTO"); //UseType specified in IInd parameter

// Add service details
sb.BusinessEntities[0].BusinessServices.Add();
sb.BusinessEntities[0].BusinessServices[0].Names.Add("pigLatin");
sb.BusinessEntities[0].BusinessServices[0].Descriptions.Add("Pig Latin funny!");

// Specify a binding where the service can be located
sb.BusinessEntities[0].BusinessServices[0].BindingTemplates.Add();
sb.BusinessEntities[0].BusinessServices[0].BindingTemplates[0].AccessPoint.Text = webService;
sb.BusinessEntities[0].BusinessServices[0].BindingTemplates[0].AccessPoint.URLType = Microsoft.Uddi.Api.URLType.Http;
sb.BusinessEntities[0].BusinessServices[0].BindingTemplates[0].Descriptions.Add("Converts the text to funny pig latin");

// Send the built save business request
BusinessDetail businessDetail = sb.Send();

// Print the generated business key
Response.Write("Business: " + businessDetail.BusinessEntities[0].Names[0].Text);
Response.Write("Key: " + businessDetail.BusinessEntities[0].BusinessKey);
Response.Write("Service published in Microsoft test UDDI site");
}
catch (UddiException ex)
{
if(ex.Number==UddiException.ErrorType.E_accountLimitExceeded)
Response.Write("UDDI Exception: Service Provider "+serviceProvider+" already exists");
else if(ex.Number==UddiException.ErrorType.E_unknownUser)
Response.Write("UDDI Exception: Passport authentication failed, double check your userId ("+passportUserId+") and password ("+passportPassword+")");
else
Response.Write("UDDI exception: " + ex.Number + " - " + ex.Message); }
catch (Exception ex)
{Response.Write("Other exception: " + ex.Message);}

}

Discovering the web service provider and service
private void discover_Click(object sender, System.EventArgs e)
{
try
{

Inquire.Url = inquireUrl;

// Create an object to find a business
FindBusiness fb = new FindBusiness();
fb.Names.Add(serviceProvider);

// Send the prepared find business request
BusinessList businessList = fb.Send();

if (businessList.BusinessInfos.Count>0)
{
GetBusinessDetail detailObject = new GetBusinessDetail();

// Associate the business key with detailObject, returned by fb.Send call
detailObject.BusinessKeys.Add(businessList.BusinessInfos[0].BusinessKey);
// Send the request to the UBR node
BusinessDetail businessDetail = detailObject.Send();

//Scan through all business entities returned
if (businessDetail.BusinessEntities.Count>0)
{
// Scan categories specified for this business
for (int i=0; i < businessDetail.BusinessEntities[0].CategoryBag.Count; i++)
{
Response.Write(" Categories: ");
Response.Write("Name : " + businessDetail.BusinessEntities[0].CategoryBag[i].KeyName);
Response.Write("Value : " + businessDetail.BusinessEntities[0].CategoryBag[i].KeyValue);
Response.Write("tModel : " + businessDetail.BusinessEntities[0].CategoryBag[i].TModelKey);
}

// Scan identifiers for the same
for (int j=0; j < businessDetail.BusinessEntities[0].IdentifierBag.Count; j++)
{
Response.Write("Identifiers:");
Response.Write("Name : " + businessDetail.BusinessEntities[0].IdentifierBag[j].KeyName);
Response.Write("Value : " + businessDetail.BusinessEntities[0].IdentifierBag[j].KeyValue);
Response.Write("tModel : " + businessDetail.BusinessEntities[0].IdentifierBag[j].TModelKey);
}

// scan contacts
for (int k=0; k < businessDetail.BusinessEntities[0].Contacts.Count; k++)
{
Response.Write("Contact ("+(k+1)+"):" );
Response.Write("Name : " + businessDetail.BusinessEntities[0].Contacts[k].PersonName);
Response.Write("Type : " + businessDetail.BusinessEntities[0].Contacts[k].UseType);
}

// Scan through business services
for (int m=0; m < businessDetail.BusinessEntities[0].BusinessServices.Count; m++)
{
Response.Write("Services:");
Response.Write("Name : " + businessDetail.BusinessEntities[0].BusinessServices[m].Names[0].Text);
// There might be multiple access points for this service
for (int n=0; n < businessDetail.BusinessEntities[0].BusinessServices[m].BindingTemplates.Count; n++)
{
//display and put the AccessPoint in variable wsUri
Response.Write("Access point : " + (businessDetail.BusinessEntities[0].BusinessServices[m].BindingTemplates[n].AccessPoint.Text));
wsUri=businessDetail.BusinessEntities[0].BusinessServices[m].BindingTemplates[n].AccessPoint.Text;
}
}
}
}
}
catch (UddiException er)
{Response.Write("UDDI exception: (" + er.Number + ") - " + er.Message);}
catch (Exception er)
{Response.Write("Other exception: " + er.Message);}
}

Invoking the web service: Now we'll invoke the web service method using the SOAP SDK provided by microsoft. Invoking services using SoapClient(n) class is fairly easy. Here n means the major version appended to the classes. this number is not associated with SOAP SDK's previous versions than 3.0.
MSSoapInit method in SoapClient(n) class initialises the web service for the given WSDL and accepts service name and service port.

private void invoke_Click(object sender, System.EventArgs e)
{
SoapClient30 sc = new SoapClient30();
string translateText=textToTran.Text;
string wsdl=null;
try
{
if(wsUri==null)
throw new Exception("Please Discover the service first");
if((new Regex("(wsdl)$")).IsMatch(wsUri)) //check if it's the real WSDL
wsdl=wsUri;
else
wsdl=wsUri+"?wsdl"; //otherwise append WSDL to the service

sc.MSSoapInit(wsdl, "piglatin", "piglatinSoap",""); //specify the service name and port name
Type type =sc.GetType();

object []args = {translateText}; //specified service accepts just one argument (textToTranslate)
Response.Write("Invoking method using MS SOAP SDK ...");
object ox = type.InvokeMember("toPigLatin", BindingFlags.InvokeMethod,null,sc,args); //Dynamic Invocation No Proxy class, no web reference
Response.Write("Translated String "+ox.ToString());
}
catch(Exception sEx){Response.Write("Exception occurred "+sEx.Message);}
}

Further Enhancements
This sample code might be further enhanced to present a dashboard for testing web services and it's methods in UDDI registry.

Sumit Amar