話說做這個很久了,不過我比較磨洋工。所以托了很久,今天才真正跑通了整個流程。
一開始老師要我做的時候,我有點沒明白意思,后來看了msdn后明白了不少。
我要做的是用一句話來概括就是,通過JSON來與后台的J2EE通訊,操作數據。
但就是這樣一個簡單的任務,我大概有認真做了一個禮拜吧。
下面說說主要的實現方法:
首先我們要提到webclient這個類,這是system自帶的一個模仿web瀏覽器的類,用它來模仿POST訪問(其實還能GET、PUT、DELETE)。
具體的思路是:首先實體化一個webclient,打開端口下載或者上傳JSON字符串,然后通過綁定實體類的方法來序列化或者反序列化JSON報文,最后做到我們需要的數據操作。
具體代碼如下:
1、首先我們需要綁定實體類,之后用微軟的自帶類庫來解析(也可以用JSON.NET這個開源的第三方類庫,不過有些方法我還不懂)
[DataContract] public class jsontext { [DataMember(Order = 0, IsRequired = true)] public int total { get; set; } [DataMember(Order = 1, IsRequired = true)] public weatherInfo[] rows { get; set; } } [DataContract] public class weatherInfo { [DataMember(Order = 0, IsRequired = true)] public int id { get; set; } [DataMember(Order = 1)] public double weatherType { get; set; } [DataMember(Order = 2)] public string weatherName { get; set; } [DataMember(Order = 3)] public double maxTemperature { get; set; } [DataMember(Order = 4)] public double minTemperature { get; set; } [DataMember(Order = 5)] public double rainFall { get; set; } [DataMember(Order = 6)] public double snowFall { get; set; } } [DataContract] public class weatherInsert { [DataMember(Order = 0, Name = "weatherInfo.iweatherType")] public double iweatherType { get; set; } [DataMember(Order = 1, Name = "weatherInfo.cweatherName")] public string cweatherName { get; set; } [DataMember(Order = 2, Name = "weatherInfo.imaxTemperature")] public double imaxTemperature { get; set; } [DataMember(Order = 3, Name = "weatherInfo.iminTemperature")] public double iminTemperature { get; set; } [DataMember(Order = 4, Name = "weatherInfo.irainFall")] public double irainFall { get; set; } [DataMember(Order = 5, Name = "weatherInfo.isnowFall")] public double isnowFall { get; set; } }
2、然后實例一個webclinet
WebClient webclient = new WebClient(); if (!webclient.IsBusy) { webclient.Encoding = System.Text.Encoding.UTF8;//防止亂碼 json = webclient.DownloadString(address); }
3、序列化和反序列化,這里我就寫在一起了
public static class iotmonSerial { //反序列化 public static T parse<T>(string jsonstring) { using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonstring))) { return (T)new DataContractJsonSerializer(typeof(T)).ReadObject(ms); } } //序列化 public static string stringify(object jsonObject) { using (var ms = new MemoryStream()) { new DataContractJsonSerializer(jsonObject.GetType()).WriteObject(ms, jsonObject); return Encoding.UTF8.GetString(ms.ToArray()); } } }
4、通過調用前面的方法以及實體類,真正的解析了JSON,當然現在只是下載了數據,之后我會說如何上傳。
var ppp = iotmonSerial.parse<jsontext>(json); foreach (var item in ppp.rows) { myTextBlock.Text += item.id + "\t" + item.weatherType + "\t" + item.weatherName + "\n"; }
5、然后我們來說說怎么上傳數據吧~(太艱辛了)
Uri address = new Uri("http://localhost:8080/iotMon/WeatherInfo/listWeatherInfoPaged.action"); WebClient webClient = new WebClient(); webClient.UploadStringAsync(address, "POST", testString);
看上去很簡單吧,但是這才是最坑人的地方,因為弄完之后,我發現死活傳不上去。我比對了很多次JSP頁面上發送的字符串,都是一模一樣的。
這是我苦惱了很久的問題,最后和老師調試了好久,終於找到了問題所在。
首先得定義發過去字符串的標頭,詳見http://msdn.microsoft.com/zh-cn/library/system.net.webclient(v=vs.95).aspx(最后有提到)
但是坑爹的MSDN也沒有說解決方案,最后還是感謝強大的百度和谷歌!
標頭是如下(不同的服務器可能不一樣,需要調整,第一個是保證編碼是UTF-8的,我們的項目UTF-8的):
webClient.Encoding = System.Text.Encoding.UTF8; webClient.Headers.Add(HttpRequestHeader.Accept, "json"); webClient.Headers.Add(HttpRequestHeader.ContentType,"application/x-www-form-urlencoded; charset=UTF-8"); webClient.Headers.Add(HttpRequestHeader.UserAgent, "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.2; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)");
然后這么折騰之后我發現還是不行,最后通過瀏覽器看上傳過去的數據,發現了問題所在!
url發送過去的東西,會有一個url編碼的轉換,JSON報文里面最多的“{”和“[”都被轉換成了“%7B”和“%5B”,所以我們需要Microsoft.JScript.GlobalObject.encodeURIComponent來將已經做好的需要上傳的報文轉換格式。(需要說明的是,我們的J2EE后台寫的比較奇怪,所以上傳和下載下來的格式是不一樣的,這一點我一開始沒發現,走了不少彎路。)
到這里,就可以實現上傳和下載了!真是不容易那(大変だ)!
下面是一些需要到的庫文件:
System.Runtime.Serialization; 解析JSON報文
System.Runtime.Serialization.Json;
System.ServiceModel; 綁定實體類需要
System.ServiceModel.Web;
System.IO;
System.Xml;
System.Net; 解析JSON報文
System.Net.Http;
System.Net.Http.Formatting;
System.Web.Script.Serialization;
System.Json;
最后一點忘記補充了,上傳上去的時候需要通過URL編碼,這個視具體項目要不要轉碼。
最新問題,當服務器為linux系統時,需要加上webClient.Headers.Add(HttpRequestHeader.AcceptLanguage, "zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3");,不然無法上傳。