作为一名C++程序员,如果厌倦了DCOM和RPC的繁琐实现和调试,可能想要寻找一种新的方式来管理代码。如果不想错过接触XML Web Service的机会,可能会考虑使用.NET(C#)来创建一个。但是,如果追求更高的性能,可能会选择ATL Server Web Service。本文基于MSDN的教程《使用ATL Server创建XML Web服务》,演示了如何使用C++和ATL Server创建一个将华氏温度转换为摄氏温度的XML Web服务。已经增强了ATL Server Web Service函数的功能,使其能够转换华氏温度和摄氏温度,并使用MFC客户端代替控制台应用程序来使用这个Web服务。代码是未管理的C++,而不是托管的。
在本教程的过程中,将完成以下活动:
首先,应该创建一个空白解决方案TempConvert。然后,可以使用向导添加一个新的XML Web服务项目,名为TempConvert到这个解决方案中。
ATL Server使用ISAPI扩展DLL来调用Web服务应用程序DLL中定义的函数处理程序,以响应XML Web服务请求。
1. 在接口ITempConvertService中,用以下代码替换TempConvert.h中的示例helloWorld方法:
__interface ITempConvertService
{
// 声明一个Web服务方法及其输入参数和输出参数
[id(1)] HRESULT ConTempFah2Cel([in] double dFahrenheit, [out, retval] double* pdCelsius);
[id(2)] HRESULT ConTempCel2Fah([in] double dCelsius, [out, retval] double* pdFahrenheit);
};
2. CTempConvertService类提供了XML Web服务的实现。将代码添加到TempConvert.h文件中。
class CTempConvertService : public ITempConvertService
{
public:
[soap_method] HRESULT ConTempFah2Cel(double dFahrenheit, double* pdCelsius)
{
if (!pdCelsius) return E_INVALIDARG;
*pdCelsius = ((dFahrenheit - 32) * 5) / 9;
return S_OK;
}
[soap_method] HRESULT ConTempCel2Fah(double dCelsius, double* pdFahrenheit)
{
if (!pdFahrenheit) return E_INVALIDARG;
*pdFahrenheit = dCelsius * 9 / 5 + 32;
return S_OK;
}
};
如果一切顺利,编译解决方案并将其部署到机器上,这里是本地站点localhost,可以在IE中查看:http://localhost/TempConvert/TempConvert.dll?Handler=GenTempConvertWSDL。它只显示XML。将使用以下MFC客户端调用XML Web服务。
1. 创建一个基于对话框的MFC应用程序TempConvertClient。
2. 使用URL添加Web引用:http://localhost/TempConvert/TempConvert.dll?Handler=GenTempConvertWSDL,一个可用的替代URL是:http://ws.bomege.com/bin/TempConvert.dll?Handler=GenTempConvertWSDL(源代码应用此URL),并将其重命名为TempConvert。
3. 向对话框添加新控件。
4. 打开文件TempConvertClientDlg.h,添加变量和方法到CTempConvertClientDlg类中:
class CTempConvertClientDlg : public CDialog
{
public:
CTempConvertClientDlg(CWnd* pParent = NULL);
enum { IDD = IDD_TEMPCONVERTCLIENT_DIALOG };
protected:
virtual void DoDataExchange(CDataExchange* pDX);
afx_msg void OnBnClickedC2F();
afx_msg void OnBnClickedF2C();
protected:
HICON m_hIcon;
double m_dTempF;
double m_dTempC;
protected:
virtual BOOL OnInitDialog();
afx_msg void OnSysCommand(UINT nID, LPARAM lParam);
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
afx_msg void OnConvert();
DECLARE_MESSAGE_MAP()
};
5. 在文件TempConvertClientDlg.cpp中,添加实现方法和转换按钮的事件处理程序:
void CTempConvertClientDlg::OnConvert()
{
UpdateData(TRUE);
CoInitialize(NULL);
HRESULT hr = S_OK;
UINT m_iRadio = GetCheckedRadioButton(IDC_RADIOF2C, IDC_RADIOC2F);
GetDlgItem(IDC_CONVERT)->EnableWindow(FALSE);
CTempConvertService *pTempCon = new CTempConvertService;
switch (m_iRadio)
{
case IDC_RADIOC2F:
{
double dFah;
hr = pTempCon->ConTempCel2Fah(m_dTempC, &dFah);
if (SUCCEEDED(hr))
{
m_dTempF = dFah;
GetDlgItem(IDC_CONVERT)->EnableWindow();
UpdateData(FALSE);
}
else
{
MessageBox(_T("Convert Service Failed!"), _T("Service Failed"), MB_OK | MB_ICONHAND);
}
}
case IDC_RADIOF2C:
{
double dCel;
hr = pTempCon->ConTempFah2Cel(m_dTempF, &dCel);
if (SUCCEEDED(hr))
{
m_dTempC = dCel;
GetDlgItem(IDC_CONVERT)->EnableWindow();
UpdateData(FALSE);
}
else
{
MessageBox(_T("Convert Service Failed!"), _T("Service Failed"), MB_OK | MB_ICONHAND);
}
}
}
delete pTempCon;
CoUninitialize();
}
6. 当点击单选控件时,将向名为Convert的按钮发送BM_CLICK消息:
void CTempConvertClientDlg::OnBnClickedC2F()
{
GetDlgItem(IDC_CONVERT)->SendMessage(BM_CLICK, 0, 0);
}
void CTempConvertClientDlg::OnBnClickedF2C()
{
GetDlgItem(IDC_CONVERT)->SendMessage(BM_CLICK, 0, 0);
}
1. Web服务项目构建成功但无法运行?需要在IIS配置中向ISAPI DLL添加一个"dll"解析,它将处理应用程序dll。
2. 源代码使用的是VS.NETC++2005,如果使用的是早期版本的VS C++,只需创建一个新的空白解决方案项目并添加*.cpp, *.h等项目即可。