關於經過webclient和JSON格式報文與服務器之間通信的解決方法和遇到的難題

話說作這個好久了,不過我比較磨洋工。因此託了好久,今天才真正跑通了整個流程。linux

一開始老師要我作的時候,我有點沒明白意思,後來看了msdn後明白了很多。web

我要作的是用一句話來歸納就是,經過JSON來與後臺的J2EE通信,操做數據。json

但就是這樣一個簡單的任務,我大概有認真作了一個禮拜吧。瀏覽器

下面說說主要的實現方法:服務器

首先咱們要提到webclient這個類,這是system自帶的一個模仿web瀏覽器的類,用它來模仿POST訪問(其實還能GET、PUT、DELETE)。app

具體的思路是:首先實體化一個webclient,打開端口下載或者上傳JSON字符串,而後經過綁定實體類的方法來序列化或者反序列化JSON報文,最後作到咱們須要的數據操做。ui

具體代碼以下:編碼

一、首先咱們須要綁定實體類,以後用微軟的自帶類庫來解析(也能夠用JSON.NET這個開源的第三方類庫,不過有些方法我還不懂)url

[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; }
           
        }

二、而後實例一個webclinet.net

WebClient webclient = new WebClient();            
if (!webclient.IsBusy)
{
    webclient.Encoding = System.Text.Encoding.UTF8;//防止亂碼
    json = webclient.DownloadString(address);
}

三、序列化和反序列化,這裏我就寫在一塊兒了

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());
        }
    }
}

四、經過調用前面的方法以及實體類,真正的解析了JSON,固然如今只是下載了數據,以後我會說如何上傳。

var ppp = iotmonSerial.parse<jsontext>(json);
foreach (var item in ppp.rows)
{
    myTextBlock.Text += item.id + "\t" + item.weatherType + "\t" + item.weatherName + "\n";
}

五、而後咱們來講說怎麼上傳數據吧~(太艱辛了)

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-...(最後有提到)

可是坑爹的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");,否則沒法上傳。

相關文章
相關標籤/搜索