您的第一个托管 C++ Web 服务






4.80/5 (10投票s)
使用托管扩展的 C++ 编写您的第一个 WebService 的简介。
引言
本文假设您熟悉 声明和使用托管类型 以及 .NET 垃圾回收器。
如果您使用 C# 或 VB.NET,创建第一个 Web 服务将非常容易(有关详细信息,请参阅我 之前的文章)。使用 .NET 中的托管 C++ 编写 WebService 也非常简单,但有几个“陷阱”可能会造成一些令人沮丧的时刻。
我的第一个建议是使用 Visual Studio .NET 向导来创建您的 WebService(事实上,对于您刚开始使用时所有的应用程序来说,这是一个绝佳的主意)。如果您正在更新 .NET 的各种 beta 版本,这一点尤其重要。在一个版本中完全可以接受的内容,在另一个版本中可能无法编译,并且很难弄清楚您缺少哪个环节。
使用向导可以在几分钟内启动并运行一个托管 C++ WebService,但当您尝试一些更具风险的操作时,事情会变得有点奇怪。
在此示例中,我通过使用向导创建了一个名为 MyCPPService
的服务。只需选择 File | New Project 并运行向导即可创建一个 C++ WebService。
将定义一个名为 CPPWebService
的新命名空间,并且在该命名空间内将是实现您 webservice 的类和结构。在此示例中,我称此类为 MyService
。向导创建的其他文件包括充当服务代理的 .asmx 文件;用于配置设置的 config.web 文件;以及用于服务发现的 .disco 文件。一旦您编译了该类,您的程序集将存储在 /bin 目录下的 CPPWebService.dll 中。
我想模仿我 之前的文章 中创建的 C# WebService,但做了一些小改动来演示使用值类型和引用类型。考虑到这一点,我在命名空间中定义了一个值类型结构 ClientData
和一个托管引用类型 ClientInfo
,它们都将分别包含一个名称和 ID(string
和 int
值)。
__value public struct ClientData { String *Name; int ID; };
__gc public class ClientInfo { String *Name; int ID; };
为了返回对象数组,还声明了一个快速的 typedef。
typedef ClientData ClientArray[];
同样,我将我的 MyService
类定义为一个简单的托管 C++ 类,其中包含三个方法。
MyMethod 是一个简单的方
法,它返回单个整数。GetClientData
返回单个ClientData
结构。GetClientsData
返回ClientInfo
对象数组。
// CPPWebService.h #pragma once #using "System.EnterpriseServices.dll" namespace CPPWebService { __value public struct ClientData { String *Name; int ID; }; __gc public class ClientInfo { String *Name; int ID; }; typedef ClientData ClientArray[]; __gc class MyService { public: [WebMethod] int MyMethod(); [WebMethod] ClientData GetClientData(); [WebMethod] ClientArray GetClientsData(int Number); }; }
关于函数原型要 ध्यान देने योग्य important thing 是 [WebMethod]
属性 - 这会告知编译器该方法将是 web service 的方法,并且应该提供适当的支持和基础结构。您附加此属性的方法也必须是公共可访问的。
实现 (.cpp) 文件如下。
#include "stdafx.h" #using <mscorlib.dll> #using "System.Web.dll" #using "System.Web.Services.dll" using namespace System; using namespace System::Web; using namespace System::Web::Services; #include "CPPWebService.h" namespace CPPWebService { int MyService::MyMethod() { return 42; } ClientData MyService::GetClientData() { ClientData data; data.Name = new String("Client Name"); data.ID = 1; return data; } ClientArray MyService::GetClientsData(int Number) { // simple sanity checks if (Number < 0 || Number > 10) return 0; ClientArray data = new ClientData __gc[Number]; if (Number > 0 && Number <= 10) { for (int i = 0; i < Number; i++) { data[i].Name = new String("Client "); data[i].Name->Concat(i.ToString()); data[i].ID = i; } } return data; } };
请注意 i.ToString()
语法的用法。在 .NET 中,值类型(如 int 和 enum)可以关联方法。i.ToString()
只是调用变量 i 的 Int32::ToString()
。
与 beta 1 相比,.NET beta 2 的一个巨大改进是您不再需要与 XmlIncludeAttribute
类进行繁琐的操作来告知序列化器有关您的结构。一些导致问题或更糟 - 完全无法运行的 bug 也得到了修复。使用 MC++ 编写 WebService 现在与 C# 一样容易,其优点是可以混合搭配本机和托管代码,同时保留 C++ 的强大功能。
进行更改后,您可以构建项目,然后通过在 Visual Studio 的 Solution Explorer 中右键单击 CPPWebService.asmx 并选择“在浏览器中查看”来测试服务。测试页面如下所示。

单击其中一个方法(例如 GetClientsData
)将显示一个代理页面,允许您直接从浏览器调用该方法。GetClientsData
方法接受一个 int
参数,您可以在编辑框中输入。
调用后,将返回以下结果:

结论
使用托管扩展的 Visual C++ 编写 WebServices 与使用 C# 或 VB.NET 编写它们一样简单,只要您记住一些简单的事情:使用属性,将类声明为托管的,并使其公共可访问。使用 Visual Studio.NET 向导使编写和部署这些服务变得轻而易举,但即使您想手动完成,涉及的步骤也极其简单。
历史
10 月 18 日 - 为 .NET beta 2 更新