65.9K
CodeProject 正在变化。 阅读更多。
Home

从托管 C++ 调用 .NET My Services

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.92/5 (12投票s)

2002年2月5日

5分钟阅读

viewsIcon

106356

downloadIcon

2454

本白皮书将指导您完成编写一个客户端应用程序来调用示例 .NET My Services 服务的整个过程

引言

作为 Microsoft® .NET 计划的一部分,Microsoft 正在推出一个以用户为中心的体系结构和一套名为 .NET My Services(以前代号为“HailStorm”)的 XML Web 服务。基于 Microsoft .NET Alerts 和 Microsoft .NET Passport 的功能,.NET My Services 是一系列 XML Web 服务,在 2002 年可用时,将允许用户安全地存储和控制对个人信息的访问。 .NET My Services 平台是 XML Web 服务的一个集合,通过行业标准协议(包括 SOAP、XML 和 Universal Description, Discovery, and Integration (UDDI))在 Internet 上调用。 .NET My Services 能够对用户进行身份验证,提供发送警报的功能,并存储个人信息,包括联系人、电子邮件、日历、个人资料、列表、电子钱包、物理位置、文档存储、应用程序设置、收藏的网站、拥有的设备以及接收警报的偏好设置。

本白皮书将指导您完成编写一个客户端应用程序来调用示例 .NET My Services 服务的整个过程。该客户端将使用托管 C++、Visual Studio .NET 和 .NET My Services SDK 来编写。与 Visual C# 或 Visual Basic 客户端应用程序相比,用户需要执行额外的步骤。本白皮书假设您熟悉 Visual Studio XML Web 服务模型,该模型用于从客户端应用程序创建和调用通用 Web 服务。(请参阅 Visual Studio .NET 文档中关于使用托管 C++ 扩展、Visual Basic 或 Visual C# 创建和访问 XML Web 服务的说明)

为了鼓励开发人员开始开发使用这些服务的应用程序,Microsoft 于 2001 年 10 月在 Professional Developers Conference 上发布了 .NET My Services SDK – 其中包含示例服务以及 2 个允许 Visual Studio 与 Hailstorm 服务集成的开源项目。这些开源项目是用 Visual C# 编写的,并为 Visual Studio 提供了附加功能,以便用户可以无缝地处理下面描述的 .Net My Services 的特定特性。

首先,重要的是要理解 .NET My Services 使用一个名为 .NET Services 的中央元服务。该服务负责在客户端与其他 .NET Services(如 .NET Contacts 或 .NET Wallet)之间的交互。集中的 .NET Services 还代表用户管理其他服务的配置,并在运行时将其他服务的位置传达给客户端。因此,客户端应用程序在访问像 .NET Contacts 或 .NET Wallet 这样的特定请求服务之前,必须与中央 .NET My Services 协商事务。

.NET My Services 还使用 Kerberos 身份验证协议,并加密所有 SOAP 数据包,以确保用户私人数据的安全。这意味着所有客户端应用程序都必须提供请求 Kerberos 身份验证票证的功能,并在所有 SOAP 请求中提供这些票证。此外,客户端必须加密 SOAP 请求并解密 SOAP 响应。

.NET My Services 服务定位器和加密中使用的所有技术都基于开放标准,并且有文档记录,因此 .NET My Services 开发人员可以自由开发自己的应用程序层来处理这些功能。但是,.NET My Services SDK 包含两个共享源项目,它们将解决这些问题。对于 Visual C# 和 Visual Basic,用户只需在其客户端应用程序中包含对这些项目的引用,即可利用它们的功能,这些功能将基本允许开发人员像处理任何其他 Web 服务一样为 .NET My Services 进行编码。

我们将提供额外的步骤来解决 Visual Studio .NET 中“添加 Web 引用”对话框的一些限制,该对话框用于使用强类型数据集调用 Web 服务。在 Visual Studio .NET 的未来版本中,将不再需要这些额外的步骤。

首先,我们需要构建 SDK 中提供的 HsSoapExtension 解决方案以获取 HsSoapExtension.dll。我们稍后将需要它。

  1. 创建一个新的 MC++ 应用程序项目,并将其命名为 MyServiceClient。

  2. 在命令行中,导航到 MyServiceClient 项目目录并运行以下命令:
  3. disco https:///WSDL/myFavouriteWebSites.wsdl

    此命令下载 soaprp.xsd、myFavouritewebsites.wsdl 并生成 results.discomap。生成的 .discomap 文件描述了 wsdl 和 xsd 文件之间的依赖关系。现在我们需要将这些文件添加到项目中。

  4. 在 Visual Studio 中,右键单击“项目”节点,选择“添加”菜单项,然后选择“添加现有项”子项。您可以浏览到项目的位置,并选择之前在该位置创建的 3 个文件:soaprp.xsd、myFavouritewebsites.wsdl 和 results.discomap。这将把这 3 个文件添加到您的项目中。请参阅下图。
  5. 右键单击 results.discomap 文件,选择“属性”,然后将“工具”选项值更改为“Web 服务代理生成器”。

  6. 右键单击 results.discomap 文件,选择“属性”,然后将“工具”选项值更改为“自定义生成工具”。

  7. 将之前构建的 HsSoapExtension.dll 从 .NET My Services SDK 解决方案文件夹复制到项目的源文件夹。

  8. 将 /reference:HsSoapExtension.dll 添加到 csc.rsp 文件中,该文件位于 %SystemRoot%\ Microsoft.NET\Framework\v1.0.xxxx,其中 xxxx 是 .NET Framework 的版本。

  9. 生成解决方案。这将导致为 Web 服务生成 C# 代理类:results.cs,然后将其构建到 results.dll 中。 **注意**:对于托管 C++ 应用程序,所有代理类都用 C# 生成,无论它们是用于 .NET My Services 还是其他 Web 服务。

要实际使用 .NET My FavoriteWebSites 服务,我们必须再执行一个步骤。

在 MyServicesClient.cpp 文件中添加以下几行:

 #using <HsSoapExtension.dll>
 #using <references.dll>

现在,所有设置都已完成,可以调用实际的 My Service 服务了。以下示例客户端代码显示了如何将网站添加到“收藏的网站”中、如何查询以及如何删除它。您可以在本文档开头提到的链接中找到完整的解决方案。

示例客户端代码

int _tmain(void)
{
    Microsoft::Hs::ServiceLocator::ServiceLocator* serviceLocator = 
               new Microsoft::Hs::ServiceLocator::ServiceLocator("http:///myServices", 
                                                                 "c:\\logfile.txt", true);
    try
    {
        //
        // Use the service locator to find and initialize the myFavoriteWebSites service / proxy
        //
        // TODO: if you are querying for a different user, specify the username instead 
        // of calling User.GetCurrentUser()
        // NOTE: User.GetCurrentUser will not work inside an ASP.NET application
        //
       
        myFavoriteWebSites* myFav = dynamic_cast<myFavoriteWebSites*> 
             (serviceLocator->GetService(System::Type::GetType("myFavoriteWebSites"), 
                                                               User::GetCurrentUser()));
           
        //
        // create a new favoriteWebSite
        //
        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;
        //
        // create an insertRequest and call insert
        //
        insertRequestType* insertRequest = new insertRequestType();
        insertRequest->select=S"/"; //we're going to insert into the root of the service
        insertRequest->Items = new Object*[1];
            insertRequest->Items[0] = newWebsite;
        insertResponseType* response = myFav->insert(insertRequest);
        //
        // check to make sure the operation was successful
        //
            if(response->selectedNodeCount != 1 || 
               response->status != responseStatus::success)
        {
            throw new Exception(S"Error inserting the new favoriteWebSite " + 
                                S"into myFavoriteWebSites");
        }
        //
        // now we've inserted the new favoriteWebSite, let's query for it
        //
        queryRequestType* queryRequest = new queryRequestType();
        xpQueryType* xpQuery = new xpQueryType();

        //NOTE: the m: prefix is declared automatically in the SoapExtension 
        //for the current service
        xpQuery->select=S"/m:myFavoriteWebSites/m:favoriteWebSite[./m:title='Hello.NET' " +
                        S"and ./m:url='http://www.microsoft.com']";

        //add the xpQuery to the xpQuery array
        queryRequest->xpQuery = new xpQueryType*[1];
            queryRequest->xpQuery[0] = xpQuery;
        queryResponseType* queryResponse = myFav->query(queryRequest);
        //
        // get the returned favoriteWebSite out of the response
        //
        favoriteWebSiteType* returnedWebSite = dynamic_cast<favoriteWebSiteType*> 
             (queryResponse->xpQueryResponse[0]->Items[0]);
       
        //
        // check to make sure the operation was successful
        //                   
            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");
        }       
        //
        // display the webSite in a messageBox
        //
            MessageBox::Show(String::Concat (S"The following favoriteWebSite was returned " +
                                             S"from myFavoriteWebSites: ",
                                             returnedWebSite->title[0]->Value));
       
        //
        // replace the cat/@ref attribute 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;
       
        //
        // delete the website
        //
        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);
         
        //
        // check to make sure we operated on at least one element and that the response 
        // indicates the operation was successful
        //
            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)
    {
        //
        // write the SoapException to the console
        //
            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)
    {
        //
        // write the exception to the console
        //
            Console::WriteLine(ex->ToString());
    }
    Console::WriteLine(S"Press return to exit." );
    Console::ReadLine();
   
    return 0;
}
© . All rights reserved.