Introduction
As part of the Microsoft� .NET
initiative, Microsoft is introducing a user-centric architecture and set of XML
Web services, named .NET My Services (formerly codenamed "HailStorm.")
Building upon the capabilities of Microsoft .NET Alerts and Microsoft .NET
Passport, .NET My Services is a family of XML Web services that, when available
in 2002, will allow users to securely store and control access to personal
information.�The .NET My Services
platform is a collection of XML Web services that are invoked over the Internet
by means of industry-standard protocols including SOAP, XML, and Universal
Description, Discovery, and Integration (UDDI). .NET My Services authenticates
users, provides the ability to send alerts, and stores personal information,
including contacts, e-mail, calendar, profile, lists, electronic wallet,
physical location, document stores, application settings, favorite Web sites,
devices owned, and preferences for receiving alerts.
This white paper guides you
through the process of writing a client application that will consume a sample
.NET My Services service.� The client
will be written using Managed C++, Visual Studio .NET, and the .NET My Services
SDK. There are additional steps that the user will have to take when, compared
to a Visual C# or a Visual Basic client application. This white paper assumes
you are familiar with the Visual Studio XML Web Services model for creating and
consuming generic web services from client applications. (See Visual Studio .NET documentation for Creating and Accessing XML Web Services
using Managed Extensions for C++, Visual Basic or Visual C#)
As a way to encourage developers
to start developing applications that will use these services, Microsoft
released at the Professional Developers Conference in October 2001 the .NET My
Services SDK � This
contains sample services as well as 2 open source projects that allow Visual
Studio to integrate with Hailstorm services.�
These open source projects are written in Visual C# and provide
additional functionality to Visual Studio so users can seamlessly deal with the
specific characteristics of .Net My Services described below.
First, it is important to
understand that .NET My Services uses a central meta-service named .NET
Services. This service brokers the interactions between clients and the other
.NET Services such as .NET Contacts or .NET Wallet. The centralized .NET
Services also manages the provisioning of other services on behalf of users and
conveys the location of other services to clients at run time. So a client
application must negotiate a transaction with the central .NET My Services
before addressing a specific requested service like .NET Contacts or .NET
Wallet.
.NET My Services also uses the
Kerberos authentication protocol and encrypts all SOAP packets in order to
ensure the security of user's private data. This means that all client
applications must provide the functionality to request Kerberos authentication
tickets and present those in all SOAP requests. Also, the client must encrypt
SOAP requests and decrypt SOAP responses.
All of the technologies used in
the .NET My Services service locator and encryption are based on open standards
and are documented so .NET My Services developers are free to develop their own
application layers to handle these features. However, .NET My Services SDK
contains two shared source projects that will address these issues. For Visual
C# and for Visual Basic, the user only needs to include references to these
projects in their client applications in order to take advantage of their
functionality that will essentially allow the developer to code for .NET My
Services as if they were any other Web Service.
We will provide the additional
steps needed to workaround some limitations of the Add Web Reference dialog for
Managed C++ client applications that consume web services using strongly typed
datasets. In future releases of Visual Studio .NET these additional steps will
not be necessary. �
First we need to build the
HsSoapExtension solution provided in the SDK to obtain HsSoapExtension.dll. We
will need this later
- Create
a new MC++ Application project and call it MyServiceClient.
- At the
command line, navigate to the MyServiceClient� project directory and run the following command:
disco http://localhost/WSDL/myFavouriteWebSites.wsdl.
This command downloads soaprp.xsd,
myFavouritewebsites.wsdl and generates results.discomap. The resulting.discomap
file describes the dependencies between the wsdl and the xsd files. We now have
to add these files to the project.
- In
Visual Studio, right click on the Project node, select the Add menu item
and then the �Add Existing item� subitem. You can browse to the location
of your project and select the 3 files previously created in that
location: �soaprp.xsd,
myFavouritewebsites.wsdl and results.discomap. This will add the 3 files
to your project. See figure below.
- Right
click on the results.discomap file, select Properties, and change the
�Tool� option value to �Web Service Proxy Generator�.
- Right
click on theresults.discomap file, select Properties, and change the
�Tool� option value to �Custom Build Tool�.
- Copy
the previously built HsSoapExtension.dll from the .NET My Services SDK
solution folder �to your project�s
source folder.
- Add /reference:HsSoapExtension.dll
to the csc.rsp file located in %SystemRoot%\ Microsoft.NET\Framework\v1.0.xxxx�where xxxx is the
version of the .NET Framework.
- Build the
solution. This will cause the C# proxy class to be generated for the web service: results.cs, that
will in turn be built into results.dll. Note: For Managed C++ applications, all proxy classes
are generated in C#, regardless of whether they are for �.NET My Services or other web services.
To actually use the .NET My FavoriteWebSites service we have
to perform just one more step:
In the MyServicesClient.cpp file add the following lines:
#using <HsSoapExtension.dll>
#using <references.dll>
Now everything is set up to call the actual My Service
service. The following sample client code shows how to add a web site to your
Favorite Web Sites, query for it and delete it. You can find the complete
solution at the link mentioned in the beginning of this document.
Sample client code:
int _tmain(void)
{
Microsoft::Hs::ServiceLocator::ServiceLocator* serviceLocator =
new Microsoft::Hs::ServiceLocator::ServiceLocator("http:",
"c:\\logfile.txt", true);
try
{
myFavoriteWebSites* myFav = dynamic_cast<myFavoriteWebSites*>
(serviceLocator->GetService(System::Type::GetType("myFavoriteWebSites"),
User::GetCurrentUser()));
favoriteWebSiteType* newWebsite = new favoriteWebSiteType();
localizableString* title = new localizableString();
title->lang = S"en";
title->Value = S"Hello.NET";
newWebsite->title = new localizableString*[1];
newWebsite->title[0] =title;
newWebsite->url = S"http://www.microsoft.com";
catType* cat = new catType();
cat->ref = S"system";
newWebsite->cat = new catType*[1];
newWebsite->cat[0] = cat;
insertRequestType* insertRequest = new insertRequestType();
insertRequest->select=S"/";
insertRequest->Items = new Object*[1];
insertRequest->Items[0] = newWebsite;
insertResponseType* response = myFav->insert(insertRequest);
if(response->selectedNodeCount != 1 ||
response->status != responseStatus::success)
{
throw new Exception(S"Error inserting the new favoriteWebSite " +
S"into myFavoriteWebSites");
}
queryRequestType* queryRequest = new queryRequestType();
xpQueryType* xpQuery = new xpQueryType();
xpQuery->select=S"/m:myFavoriteWebSites/m:favoriteWebSite[./m:title='Hello.NET' " +
S"and ./m:url='http://www.microsoft.com']";
queryRequest->xpQuery = new xpQueryType*[1];
queryRequest->xpQuery[0] = xpQuery;
queryResponseType* queryResponse = myFav->query(queryRequest);
favoriteWebSiteType* returnedWebSite = dynamic_cast<favoriteWebSiteType*>
(queryResponse->xpQueryResponse[0]->Items[0]);
if(String::Compare (returnedWebSite->title[0]->Value, S"Hello.NET") != 0 ||
String::Compare (queryResponse->xpQueryResponse[0]->status , S"success")!= 0)
{
throw new Exception(S"Error retrieving the new favoriteWebSite " +
S"from myFavoriteWebSites");
}
MessageBox::Show(String::Concat (S"The following favoriteWebSite was returned " +
S"from myFavoriteWebSites: ",
returnedWebSite->title[0]->Value));
topLevelAttributeType* redAttribute = new topLevelAttributeType();
redAttribute->name = S"ref";
redAttribute->value = S"newvalue";
replaceRequestType* replaceRequest = new replaceRequestType();
replaceRequest->select=S"/m:myFavoriteWebSites/m:favoriteWebSite/m:cat/@ref[.='system']";
replaceRequest->attribute = new topLevelAttributeType*[1];
replaceRequest->attribute[0] = redAttribute;
deleteRequestType* deleteRequest = new deleteRequestType();
deleteRequest->select = S"/m:myFavoriteWebSites/m:favoriteWebSite[./m:title='Hello.NET' " +
S"and ./m:url='http://www.microsoft.com']";
deleteResponseType* delResponse = myFav->__identifier(delete)(deleteRequest);
if(delResponse->selectedNodeCount == 0 || delResponse->status != responseStatus::success)
{
throw new Exception(S"Error deleting the new favoriteWebSite from myFavoriteWebSites");
}
MessageBox::Show(S"Successfully deleted the favoriteWebSite from myFavoriteWebSites");
}
catch(SoapException* se)
{
Console::Write(S"A SoapException was thrown\n\nException:\n");
Console::WriteLine(se->ToString());
Console::Write(S"\n\nExtended SoapFault information returned from .NET My Services:\n");
Console::Write(se->Detail->InnerXml);
}
catch(Exception* ex)
{
Console::WriteLine(ex->ToString());
}
Console::WriteLine(S"Press return to exit." );
Console::ReadLine();
return 0;
}