朋友说开发电信的MMS,其实需要图片作为附件放在调用WebService接口上,使用Http的Content-Type: Multipart/Related;来发送,真让人感觉不伦不类的。不知道为什么不设计成一个字段是BASE64编码得了呗。
难道只能用朋友说的拼字段的方法了不? 我用Reflect分析了一下,貌似这样也可以实现。
我们知道,我们添加一个WebService引用时,会自动生成从 SoapHttpClientProtocol 的子类。我的想法是,我们写一个 继承自"SoapHttpClientProtocol” 的子类SoapHttpClientProtocolEX, 重写方法:GetWebRequest() 返回我们写的代码 HttpWebRequestEx类,然后在原始 HttpWebRequest 类的GetRequestStream()时,返回我们的流转移器:NetwordStreamEx ,并在方法关闭流 Close() 前,加入自定义的附件信息。
不知道说清楚没有, 这里列了部分代码框架:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Services.Protocols;
using System.Net;
using System.Net.Sockets;
using System.IO;
namespace Foundway.Util.WebService
{
public class SoapHttpClientProtocolEx : SoapHttpClientProtocol
{
private List<string> attachments = new List<string>();
/// <summary>
/// 添加一个附件
/// </summary>
/// <param name="attachment">附件全路径</param>
public void AddAttachment(string attachment)
{
attachments.Add(attachment);
}
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest request = base.GetWebRequest(uri);
if (attachments.Count > 0)
{
HttpWebRequest httpRequest = request as HttpWebRequest;
if (httpRequest != null)
{
httpRequest.SendChunked = true; //使用多段发送
HttpWebRequestEx httpRequestEx = new HttpWebRequestEx(httpRequest, attachments.ToArray());
return httpRequestEx;
}
}
return request;
}
}
public class HttpWebRequestEx : WebRequest
{
private string[] attachments;
private HttpWebRequest httpRequest = null;
public HttpWebRequestEx(HttpWebRequest httpRequest, string[] attachments)
{
this.httpRequest = httpRequest;
this.attachments = attachments;
}
public override System.IO.Stream GetRequestStream()
{
Stream stream = httpRequest.GetRequestStream();
//返回自定义的流代理,来完成附件的信息
return new NetworkStreamEx(stream, this.attachments);
}
#region 重写其它全部公共方法
public override void Abort()
{
httpRequest.Abort();
}
public override IAsyncResult BeginGetRequestStream(AsyncCallback callback, object state)
{
return httpRequest.BeginGetRequestStream(callback, state);
}
public override IAsyncResult BeginGetResponse(AsyncCallback callback, object state)
{
return httpRequest.BeginGetResponse(callback, state);
}
public override System.Net.Cache.RequestCachePolicy CachePolicy
{
get
{
return httpRequest.CachePolicy;
}
set
{
httpRequest.CachePolicy = value;
}
}
public override string ConnectionGroupName
{
get
{
return httpRequest.ConnectionGroupName;
}
set
{
httpRequest.ConnectionGroupName = value;
}
}
public override long ContentLength
{
get
{
return httpRequest.ContentLength;
}
set
{
httpRequest.ContentLength = value;
}
}
public override string ContentType
{
get
{
return httpRequest.ContentType;
}
set
{
httpRequest.ContentType = value;
}
}
public override System.Runtime.Remoting.ObjRef CreateObjRef(Type requestedType)
{
return httpRequest.CreateObjRef(requestedType);
}
public override ICredentials Credentials
{
get
{
return httpRequest.Credentials;
}
set
{
httpRequest.Credentials = value;
}
}
public override Stream EndGetRequestStream(IAsyncResult asyncResult)
{
return httpRequest.EndGetRequestStream(asyncResult);
}
public override WebResponse EndGetResponse(IAsyncResult asyncResult)
{
return httpRequest.EndGetResponse(asyncResult);
}
public override WebResponse GetResponse()
{
return httpRequest.GetResponse();
}
public override WebHeaderCollection Headers
{
get
{
return httpRequest.Headers;
}
set
{
httpRequest.Headers = value;
}
}
public override string Method
{
get
{
return httpRequest.Method;
}
set
{
httpRequest.Method = value;
}
}
public override bool PreAuthenticate
{
get
{
return httpRequest.PreAuthenticate;
}
set
{
httpRequest.PreAuthenticate = value;
}
}
public override IWebProxy Proxy
{
get
{
return httpRequest.Proxy;
}
set
{
httpRequest.Proxy = value;
}
}
public override object InitializeLifetimeService()
{
return httpRequest.InitializeLifetimeService();
}
public override Uri RequestUri
{
get
{
return httpRequest.RequestUri;
}
}
public override int Timeout
{
get
{
return httpRequest.Timeout;
}
set
{
httpRequest.Timeout = value;
}
}
public override string ToString()
{
return httpRequest.ToString();
}
public override bool UseDefaultCredentials
{
get
{
return httpRequest.UseDefaultCredentials;
}
set
{
httpRequest.UseDefaultCredentials = value;
}
}
public override bool Equals(object obj)
{
return httpRequest.Equals(obj);
}
public override int GetHashCode()
{
return httpRequest.GetHashCode();
}
#endregion
}
public class NetworkStreamEx :Stream
{
private string[] attachments;
private Stream baseStream;
public NetworkStreamEx(Stream baseStream, string[] attachments)
{
this.baseStream = baseStream;
}
/// <summary>
/// 在关闭时,加入附件信息
/// </summary>
public override void Close()
{
///TODO:这里添加附件信息,
///这里就不加代码了
///
base.Close();
}
#region 把其它公共方法转发到原流
public override bool CanRead
{
get { return baseStream.CanRead; }
}
public override bool CanSeek
{
get { return baseStream.CanSeek; }
}
public override bool CanWrite
{
get { return baseStream.CanWrite; }
}
public override void Flush()
{
baseStream.Flush();
}
public override long Length
{
get { return baseStream.Length; }
}
public override long Position
{
get
{
return baseStream.Position;
}
set
{
baseStream.Position = value;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
return baseStream.Read(buffer, offset, count);
}
public override long Seek(long offset, SeekOrigin origin)
{
return baseStream.Seek(offset, origin);
}
public override void SetLength(long value)
{
baseStream.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
baseStream.Write(buffer, offset, count);
}
#endregion
}
}
引自:51aspx