System.Net.Http for Silverlight


System.Net.Http 簡介

System.Net.Http 是微軟推出的最新的 HTTP 應用程序的編程接口, 微軟稱之為“現代化的 HTTP 編程接口”, 旨在提供如下內容:

  1. 用戶通過 HTTP 使用現代化的 Web Service 的客戶端組件;
  2. 能夠同時在客戶端與服務端同時使用的 HTTP 組件(比如處理 HTTP 標頭和消息), 為客戶端和服務端提供一致的編程模型。

命名空間 System.Net.Http 以及 System.Net.Http.Headers 提供了如下內容:

  1. HttpClient 發送和接收 HTTP 請求與響應;
  2. HttpRequestMessage and HttpResponseMessage 封裝了 RFC 2616 定義的 HTTP 消息;
  3. HttpHeaders 封裝了 RFC 2616 定義的 HTTP 標頭;
  4. HttpClientHandler 負責生成HTTP響應消息的HTTP處理程序。

System.Net.Http 能夠處理多種類型的 RFC 2616 定義的 HTTP 實體正文, 如下圖所示:

HttpContent Class Diagrams

此外, System.Net.Http 對 HTTP 消息的處理采用了職責鏈模式, 這里有一遍不錯的介紹, 這里就不再多說了。

Silverlight 版本的 System.Net.Http

System.Net.Http 最早和 Asp.Net Mvc4 同時出現, 可以在 .Net 4.0 中使用。 隨着 .Net 4.5 的發布, System.Net.Http 正式成為 .Net 基礎類庫, 目前已經可以在 .Net 4.0/4.5 、 Windows Phone 、 以及 Windows Store App 中使用, 唯獨沒有發布 Silverlight 版本的 System.Net.Http。 更加悲催的是, 隨着 Xamarin 2.0 的發布, Xamarin.Android 和 Xamarin.iOS 居然也開始支持 System.Net.Http , 真是讓做 Silverlight 開發的碼農心寒。

幸好, .Net 有開源的實現, 那就是 Mono , 其中有大量開源的 .Net 基礎類實現, 在 Mono 3.x 版本中, 就有開源的 System.Net.Http , Xamarin 發布的 Android 和 iOS 版本的 System.Net.Http 就是源自 Mono 的, 既然 Android 和 iOS 可以, 相信 Silverlight 也肯定可以, 抱着試試看的態度, 下載了 Mono 下的 System.Net.Http 源代碼, 並整理成了一個 Silverlight 項目。 經過一番努力, Silverlight 版本的 System.Net.Http 終於可以使用了, GitHub 項目地址: https://github.com/beginor/System_Net_Http , 歡迎圍觀。

由於 Silverlight 平台對 HTTP 的限制, 移除了部分功能, 例如 Proxy 、 AllowAutoRedirect 、 PreAuthenticate 以及 KeepAlive 設置等, 這些都是 Silverlight 不支持的。

對於 Silverlight 的 BrowserHttp , 僅僅支持 GET 和 POST 方法, 示例代碼如下:

HttpClient client = new HttpClient {
   BaseAddress = new Uri("http://localhost:8080/HttpTestWeb/api/")
};

// Get string from server
client.GetStringAsync("browserhttp/").ContinueWith(t => {
   if (t.IsFaulted) {
      // report error here
      //Application.Current.ReportError(t.Exception.GetBaseException());
   } else {
      string txt = t.Result;
      //Assert.IsFalse(string.IsNullOrEmpty(txt));
   }
});

// Post form data to server
var param = new Dictionary<string, string> {
   {"Name", "Client Post"},
   {"Age", "1"},
   {"Birthday", DateTime.Today.ToString("s")}
};
client.PostAsync("browserhttp/", new FormUrlEncodedContent(param)).ContinueWith(t => {
   if (t.IsFaulted) {
      // report error here
      // Application.Current.ReportError(t.Exception.GetBaseException());
   } else {
      HttpResponseMessage response = t.Result;
      //Assert.IsTrue(response.EnsureSuccessStatusCode);
   }
});

對於 ClientHttp , 除了 GET 和 POST 之外, 還支持 PUT 和 DELETE (其它的 HTTP 方法也可能支持, 未測試), 示例代碼如下:

// PUT to update
var param = new Dictionary<string, string> {
   {"Id", "1" },
   {"Name", "Client Post"},
   {"Age", "1"},
   {"Birthday", DateTime.Today.ToString("s")}
};
client.PutAsync("clienthttp/1", new FormUrlEncodedContent(param)).ContinueWith(t => {
   if (t.IsFaulted) {
      // report error here
      // Application.Current.ReportError(t.Exception.GetBaseException());
   } else {
      HttpResponseMessage response = t.Result;
      //Assert.IsTrue(response.EnsureSuccessStatusCode);
   }
});

// DELETE
client.DeleteAsync("clienthttp/1").ContinueWith(t => {
   if (t.IsFaulted) {
      // report error here
      // Application.Current.ReportError(t.Exception.GetBaseException());
   } else {
      HttpResponseMessage response = t.Result;
      //Assert.IsTrue(response.EnsureSuccessStatusCode);
   }
});

支持職責鏈模式的 MessageProcessingHandler , 如下面的代碼所示:

public class CustomProcessingHandler : MessageProcessingHandler {

   protected override HttpRequestMessage ProcessRequest(HttpRequestMessage request, CancellationToken cancellationToken) {
      if (request.Method != HttpMethod.Get && request.Method != HttpMethod.Post) {
         request.Headers.TryAddWithoutValidation("RequestMethod", request.Method.Method);
         request.Method = HttpMethod.Post;
      }
      return request;
   }

   protected override HttpResponseMessage ProcessResponse(HttpResponseMessage response, CancellationToken cancellationToken) {
      var request = response.RequestMessage;
      if (request.Headers.Contains("RequestMethod")) {
         IEnumerable<string> values;
         if (request.Headers.TryGetValues("RequestMethod", out values)) {
            request.Method = new HttpMethod(values.First());
         }
      }
      return response;
   }
}

使用起來也是非常簡單的:

var customHandler = new CustomProcessingHandler {
    InnerHandler = new HttpClientHandler()
};
var client = new HttpClient(customHandler, true) {
    BaseAddress = new Uri("http://localhost:8080/HttpTestWeb/api/")
};

參考資料:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM