WCF REST 工作總結(二)
上一篇 我們搭建了WCF REST 的服務 平且通過 三種方式發送get請求 實現了獲取json 沒看過的朋友可以先去看下----REST 工作總結一
今天主要寫下 POST等其他方式 發送請求 以及 流方式 文件的上傳與下載
一.Post 提交數據
先來想下 POST和Get 的不同 Get 方式 我們直接通過 url 來傳遞參數 先來看下我們的 創建方法吧
[WebInvoke(UriTemplate = "Tasks/Add", Method = "POST", RequestFormat = WebMessageFormat.Json)]
void Create(PocoTask pocoTask);
我們需要接受一個實體類 格式為json格式 這就再次出現上文的問題 我們的客戶端沒有實體類 沒法把實體類序列化為json 難道要自己拼接json么? 當然不用。那簡直太痛苦了。
這里給大家推薦 Json.Net 這里有兩個類 可以幫我們完成 單個實體的轉換 以及集合實體的轉換 分別是 JObject 和 JArray
我們只需聲明這兩個類后 .toString 就可得到他的json格式了 很方便吧~ 看代碼

這里完全可以不用dynamic的 像注釋那樣的寫法就行 這樣即使服務器不支持.net4.0 也可以使用的
知道了如何構建POST 提交的數據 就開始實現POST提交吧~ 上代碼 依然是三種方式 放一起 對比


這三個方式 個人很推薦 第三種 也是目前最新的 .net4.5里集成的 訪問REST 非常的方便 因為他支持 直接點出來 PUT 以及 DELETE請求
簡直是為rest 量身定制的~~ 看下 PUT請求

這里需要注意下 因為我們發送的是json 不論是哪種發送請求的方式 都要記得 設置ContentType=application/json
否則會拋出 HTTP 400的錯誤 400-錯誤的請求 很多都是客戶端請求不正確造成的 所以一般出來400錯誤 可以重點檢查下 客戶端請求的問題
因為 PUT 與 DELETE 和 POST 基本類似 我就不上代碼了
二.REST 的文件上傳 與下載
流文件的上傳和下載
先來看服務端的接口與實現

我們要實現三個功能
1. 展示一張圖片
2.下載一個文件
3.上傳一個文件
一個一個說 先說展示圖片 實現代碼
這個是在瀏覽器中直接打開 比較簡單 這里記得設置輸出的 ContentType 有時我們想打開的是別的格式 這里有個小方法 根據文件擴展名獲得輸出的ContentType
也就是上面用到的GetContentType方法 在園子的知識庫里發現的 GetContentType
客戶端 非常簡單 直接引用連接即可

2.下載
上面的是直接把文件顯示在瀏覽器中 如果我們希望下載資源呢 方法也很簡單和以前的方法是一樣的 直接上代碼
文件下載
public void GetExecl(string execlName)
{
string folder = System.Web.Hosting.HostingEnvironment.MapPath("~/Files");
var FullFileName = Path.Combine(folder, execlName);
if (File.Exists(FullFileName))
{
FileInfo DownloadFile = new FileInfo(FullFileName);
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Buffer = false;
HttpContext.Current.Response.ContentType = "application/octet-stream";
HttpContext.Current.Response.AppendHeader("Content-Disposition", "attachment;filename=" + HttpUtility.UrlEncode(DownloadFile.FullName, System.Text.Encoding.ASCII));
HttpContext.Current.Response.AppendHeader("Content-Length", DownloadFile.Length.ToString());
HttpContext.Current.Response.WriteFile(DownloadFile.FullName);
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
}
}
3.上傳
這個文件上傳 才是重點要說的 折騰了好久~
首先要說的是 一定要記得配置文件 如果用REST 模版 配置方法如下
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints >
<webHttpEndpoint >
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name="" maxReceivedMessageSize="3000000" defaultOutgoingResponseFormat="Json" helpEnabled="true" automaticFormatSelectionEnabled="true">
<readerQuotas maxArrayLength="300000"/>
</standardEndpoint>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
這樣就可以上傳大文件了
客戶端實現上傳很簡單 借助 HttpClient

本來寫到這 以為上傳很簡單的就能完成了 結果卻弄了好久
先說下以前的寫法

以前這樣 都能成功 誰知道這次移到 REST WCF 中 竟然報錯 發現不能讀取Stream.Length 在這里問下各位高手 ~為什么讀取Stream.Length 會報錯?
CSDN 的 fangxinggood 給了解釋 非常感謝
因為它被封裝成了MessageBodyStream,就像WCF Streamed的數據一樣,Length是不支持的。WCF里是客戶端一邊傳服務端一邊收。到達服務端開始寫IO時,流并沒有全部傳輸完,所以 MessageBodyStream不支持Length。但REST時是Http協議,所以其實Stream已經全部到達服務端了。如果你想取長度,可以 用: var len = WebOperationContext.Current.IncomingRequest.ContentLength;來獲得。
如圖

最后就會拋出Http 400的錯誤
百思不得其解 只好換了另一種方法這種方法不需要 長度length

可是卻發現在 轉化成byte 這次是報錯 輸入的不是有效的 Base-64 字符串,因為它包含非 Base-64 字符、兩個以上的填充字符,或者填充字符間包含非空白字符。
再次請問原因? 希望遇到過的朋友告知
解決辦法
后來 通過谷歌 發現另外一種 獲得長度的方法 在WCF REST里 這樣就能用第一種方法了
把最早方法里的
long ByteLength=stream.Length;
換成
long ByteLength = WebOperationContext.Current.IncomingRequest.ContentLength;
這樣就可以得到長度了 上傳問題也就解決了~~
這里說下 如果上傳的是圖片 有個很簡單的方法 核心代碼 簡單兩行即可~

三.Session與Cookie
在WCF 里 是可以使用session的 但是在REST 的WCF 里 貌似卻不能使用session 查了些資料 沒有發現使用session的辦法
可能是因為使用session會讓服務器和客戶端耦合。 后來找到了 REST 常見誤區 http://www.prescod.net/rest/mistakes/
里面提到了一條 session 是無關緊要的。
cookie 還是可以正常使用的 這里說下 客戶端讀取cookie的方法 webclient 貌似不能讀到 要使用更加靈活的 HttpWebRequest

主要是這兩句
CookieContainer Cookie = new CookieContainer();
request.CookieContainer = Cookie;
四.總結
在做這方面的工作 把經驗分享給大家 也希望會的人 能解答下我問中的問題~~
REST WCF 體現了ROA 面向資源編程 感覺更好了解耦了客戶端與服務端 而且調用 REST 服務 也簡單了很多 沒有了代理等 效率也提高了 喜歡這種風格的方式
參考:
http://blog.csdn.net/fangxinggood/article/details/6235662
原文:
http://www.rzrgm.cn/wlflovenet/archive/2011/10/28/WCFREST2.html

浙公網安備 33010602011771號