朋友說開發電信的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