ATLServer WebService 如何返回任意内容的 SOAP 消息给客户 —— 改写atlsoap.h

ATLServer WebService 如何返回任意内容的 SOAP 消息给客户

cheungmine@gmail.com

2007-3-24

      (上篇文章存在问题,这里是可用的版本。)

如果想在下面的WebService方法中返回任意SOAP错误消息给客户,应该这样做:

// 宏定义,错误信息只支持英文半角
#define SOAP_FAULT(errCode,wszDetail)    m_fault.m_soapErrCode = errCode;  m_fault.m_strDetail = wszDetail

     [ soap_method ]
     HRESULT HelloWorld(/*[in]*/ BSTR bstrInput,/*[out,retval]*/ BSTR *bstrOutput)
     {
         CComBSTR bstrOut(L"Hello ");
         bstrOut += bstrInput;
         *bstrOutput = bstrOut.Detach();
        
         SOAP_FAULT(SOAP_E_SERVER,  L"Do you love me,my girl");
         return E_FAIL;
    }
然而,m_fault参数未定义,我们需要把它加入到atlsoap.h文件中。打开atlsoap.h,加入下面的代码,注意红色部分是我加的,其他地方不要改变:
template  < typename THandler >
class  CSoapHandler : 
    
public  CSoapRootHandler, 
    
public  CComObjectRootEx < CComMultiThreadModel > ,
    
public  IRequestHandlerImpl < THandler >
{
protected :
    HTTP_CODE    m_hcErr;
    CHttpResponse 
* m_pHttpResponse;

    
//  heap for SOAP requests
    CWin32Heap    m_heap;

    
//  default heap is COM heap (SOAP Servers can double as COM objects)
    CComHeap    m_comHeap;

    
// CL2: 这里添加成员用来返回用户定制的错误,而不是根据HRESULT值生成错误
    CSoapFault  m_fault;
public :

    BEGIN_COM_MAP(CSoapHandler
< THandler > )
        COM_INTERFACE_ENTRY(ISAXContentHandler)
        COM_INTERFACE_ENTRY(IRequestHandler)
    END_COM_MAP()

    CSoapHandler()
        :m_pHttpResponse(NULL), m_hcErr(HTTP_SUCCESS)
    {
        SetMemmgr(
& m_comHeap);
    }

    
void  SetHttpError(HTTP_CODE hcErr)
    {
        m_hcErr 
=  hcErr;
    }

    HRESULT SoapFault(
        SOAP_ERROR_CODE errCode, 
        
const  wchar_t  * wszDetail,
        
int  cchDetail)
    {
        ATLASSUME( m_pHttpResponse 
!=  NULL );

        SetHttpError(AtlsHttpError(
500 , SUBERR_NO_PROCESS));

        m_pHttpResponse
-> ClearHeaders();
        m_pHttpResponse
-> ClearContent();
        m_pHttpResponse
-> SetContentType( " text/xml " );
        m_pHttpResponse
-> SetStatusCode( 500 );
        
        
if (m_fault.m_soapErrCode ==  SOAP_E_UNK)
        {
            
if  (wszDetail  !=  NULL)
            {
                
if  (cchDetail  <   0 )
                {
                    cchDetail 
=  ( int ) wcslen(wszDetail);
                }

                _ATLTRY
                {
                    m_fault.m_strDetail.SetString(wszDetail, cchDetail);
                }
                _ATLCATCHALL()
                {
                    ATLTRACE( _T(
" CSoapHandler::SoapFault -- out of memory. "  ) );

                    
return  E_OUTOFMEMORY;
                }
            }

            m_fault.m_soapErrCode 
=  errCode;
        }

        m_fault.GenerateFault(m_pHttpResponse);

        
return  S_OK;
    }
    ... ...
以上就这些就可以了,运行就看到返回的错误信息“<Detail>Do you love me,my girl</Detail>”。
我使用VS2005+ATL8来写WebService。用其他语言写的WebService不知道存在这些问题不。如果要用好ATL Server,对它的代码做些修改是很正常的。我修改了它很多认的实现,比如CSessionStateService、CPerfMon等类。

相关文章

1.使用ajax调用varxhr;functioninvoke(){if(window.ActiveXO...
               好不容易把WebService服务器...
1新建一个工程项目用来做服务端增加一个MyService1类文件pac...
packagecom.transsion.util;importjava.io.BufferedReader;i...
再生产wsdl文件时重写描述文件1usingSystem;2usingSystem.Co...
一般情况下,使用eclipse自带的jax-ws生成webservice会自动生...