这个帖子本16号放在首页,不知道为何不见了,也许是我误删除了吧,重新补上,放在我自己的首页。
最近在做手机上一程序,需要通过移动cmwap访问外部的webservice,但使用wsdl生成的代理类通过cmwap网关访问会出现"Client found response content type of 'text/vnd.wap.wml',but expected 'text/xml' ".的异常信息,换用cmnet网络则正常。
应该是通过cmwap网关请求返回的数据被转化为wml类型了,wsdl代理类只认xml;
把google翻了也找不到解决方案,只好自己用最笨的办法,用HttpWebRequest和HttpWebResponse实现访问soap协议。
代码如下:

SoapClient

/**//*
code by Ivan Chin
http://www.eeay.cn/mini/
http://www.cnblogs.com/drw/
ivan@eeay.cn
转载请保留此信息。
*/

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using System.Xml;

namespace IvanCF.Soap


{
internal class SoapClient

{

属性#region 属性

private string nameSpace = "http://tempurl.org/";
private Uri serviceUrl;
private IWebProxy webProxy = null;
private ICredentials credentials = null;
private int timeOut = 30000;
private Encoding encoding = Encoding.GetEncoding("UTF-8");

//设置请求的webservice命名空间
public string Namespace

{

get
{ return nameSpace; }

set
{ nameSpace = value; }
}

//webservice地址
public Uri ServiceUrl

{

get
{ return serviceUrl; }

set
{ serviceUrl = value; }
}

//客户端使用代理
public IWebProxy Proxy

{

get
{ return webProxy; }

set
{ webProxy = value; }
}

//客户端验证
public ICredentials Credentials

{

get
{ return credentials; }

set
{ credentials = value; }
}

//webservice请求编码格式
public Encoding ContentEncoding

{

get
{ return encoding; }

set
{ encoding = value; }
}

//超时时间
public int TimeOut

{

get
{ return timeOut; }

set
{ timeOut = value; }
}

#endregion
private const int BUFFER_SIZE = 512;


异步方法#region 异步方法

//用于操作等待线程。
public static ManualResetEvent allDone = new ManualResetEvent(false);


实现事件完成通知#region 实现事件完成通知

//异步调用完成的事件
public event SoapInvokeCompletedEventHandler SoapInvokeCompleted;
protected virtual void OnSoapInvokeCompleted(SoapInvokeCompleteArgs args)

{
if (SoapInvokeCompleted != null)
SoapInvokeCompleted(this, args);
}

#endregion


/**//// <summary>
/// 异步调用webService的方法
/// </summary>
/// <param name="methodName">调用的webService的方法名称</param>
/// <param name="parameters">发送的数据</param>
public void InvokeAsync(string methodName, PostDataArray parameters)

{
RequestState state = new RequestState();
state.MethodName = methodName;
state.Parameters = parameters;
try

{
state.Request = (HttpWebRequest) WebRequest.Create(ServiceUrl);
if (TimeOut > 0) state.Request.Timeout = TimeOut;
if (Proxy != null) state.Request.Proxy = Proxy;
if (Credentials != null) state.Request.Credentials = Credentials;
state.DataSend.Append(ResloveSendData(methodName, parameters));
state.Request.ContentLength = ContentEncoding.GetByteCount(state.DataSend.ToString());
state.Request.Method = "POST";
state.Request.ContentType = "application/soap+xml; charset=" + ContentEncoding.WebName.ToLower();

//开始获取请求流
state.Request.BeginGetRequestStream(new AsyncCallback(ReqCall), state);

//阻塞当前进程,直到收到完成的通知。
allDone.WaitOne();
}
catch (Exception ex)

{
state.Error = ex;
allDone.Set();
}
finally

{
allDone.Reset();
}

string rData = null;
if (state.Error == null)

{
XmlDocument doc = new XmlDocument();
doc.LoadXml(state.DataRecived.ToString());
rData = ResloveRecivedData(methodName, doc);
}
string sData = state.DataSend.ToString();
SoapInvokeCompleteArgs args = new SoapInvokeCompleteArgs(methodName,
sData,
rData,
state.Error);
//访问完成通知Soap完成事件。
OnSoapInvokeCompleted(args);
state.Close();
GC.WaitForPendingFinalizers();
GC.Collect();
}

private void ReqCall(IAsyncResult ar)

{
RequestState state = (RequestState) ar.AsyncState;
try

{
//写入请求
StreamWriter streamWriter = new StreamWriter(state.Request.EndGetRequestStream(ar));
streamWriter.Write(state.DataSend.ToString());
streamWriter.Flush();
streamWriter.Close();

//开始取得响应。
state.Request.BeginGetResponse(new AsyncCallback(ResCall), state);
}
catch (Exception ex)

{
state.Error = ex;
allDone.Set();
}
}

private void ResCall(IAsyncResult ar)

{
RequestState state = (RequestState) ar.AsyncState;
try

{
//取响应完毕。
state.Response = (HttpWebResponse) state.Request.EndGetResponse(ar);
state.ResponseStream = state.Response.GetResponseStream();
//开始读取流。
state.ResponseStream.BeginRead(state.BufferRead, 0, BUFFER_SIZE,
new AsyncCallback(ReadCall), state);
}
catch (Exception ex)

{
state.Error = ex;
allDone.Set();
}
}

private void ReadCall(IAsyncResult ar)

{
RequestState state = (RequestState) ar.AsyncState;
try

{
//分段读取流。
int read = state.ResponseStream.EndRead(ar);
if (read > 0)

{
string strRes = ContentEncoding.GetString(state.BufferRead, 0, read);
state.DataRecived.Append(strRes);
state.ResponseStream.BeginRead(state.BufferRead, 0, BUFFER_SIZE,
new AsyncCallback(ReadCall), state);
}
else

{
allDone.Set();
}
}
catch (Exception ex)

{
state.Error = ex;
allDone.Set();
}
}

#endregion


同步方法#region 同步方法


/**//// <summary>
/// 同步调用webService的方法
/// </summary>
/// <param name="methodName">方法名称</param>
/// <param name="data">发送的xml数据</param>
/// <returns>返回的xml数据</returns>
public InvokeResult Invoke(string methodName, PostDataArray data)

{
InvokeResult result = new InvokeResult();
result.MethodName = methodName;
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(ServiceUrl);

if (TimeOut > 0) request.Timeout = TimeOut;
if (Proxy != null) request.Proxy = Proxy;
if (Credentials != null) request.Credentials = Credentials;

result.DataSend = ResloveSendData(methodName, data);
request.ContentLength = ContentEncoding.GetByteCount(result.DataSend);
request.Method = "POST";
request.ContentType = "application/soap+xml; charset=" + ContentEncoding.WebName.ToLower();

StreamWriter streamWriter = new StreamWriter(request.GetRequestStream());
streamWriter.Write(result.DataSend);
streamWriter.Flush();
streamWriter.Close();

HttpWebResponse response = null;
Stream responseStream = null;
try

{
response = (HttpWebResponse) request.GetResponse();
responseStream = response.GetResponseStream();
XmlDocument doc = new XmlDocument();
doc.Load(responseStream);
result.DataRecived = ResloveRecivedData(methodName, doc);
}
catch (Exception ex)

{
result.Error = ex;
//AppNet.GetLog().wLog(ex.ToString(), "Exception at " + invokeMethod + " Invoke");
}
finally

{
if (response != null) response.Close();
if (responseStream != null) responseStream.Close();
GC.WaitForPendingFinalizers();
GC.Collect();
}
return result;
}

#endregion


helper Method#region helper Method

//将发送的数据从PostDataArray转化成soap1.2的xml数据格式。
private string ResloveSendData(string invokeMethod, PostDataArray data)

{
string soapNs = "http://www.w3.org/2003/05/soap-envelope";
string strSoapData;
using (MemoryStream stream = new MemoryStream())

{
using (XmlTextWriter writer = new XmlTextWriter(stream, ContentEncoding))

{
writer.WriteStartDocument();
writer.WriteStartElement("soap12", "Envelope", soapNs);
writer.WriteStartElement("soap12", "Body", soapNs);
writer.WriteStartElement(invokeMethod, Namespace);
AddData2XmlWriter(writer, data);
writer.WriteEndElement();
writer.WriteEndElement();
writer.WriteEndElement();
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
using (StreamReader reader = new StreamReader(stream))

{
strSoapData = reader.ReadToEnd();
}
}
}
![]()