有時候,爲了讓數據能夠「跨國經營」,尤爲是HTTP Web有關的東東,會將數據內容以 XML 或 JSON 的格式返回,這樣一來,無論客戶端平臺是四大文明古國,仍是處於矇昧時代的原始部落,均可以使用這些數據。web
在WCF中實現將數據以XML或JSON格式返回有Y多種方法,無論你用什麼方法,只要獲得預期結果就好,米芾說了,筆能夠八面出鋒,固然了,人家指的是繪畫。json
這裏,老周就挑兩種方法來演示,僅供參考,沒有考古價值,建議司馬子長不要把本文收入《史記》。瀏覽器
第一種方法是用到 WebServiceHost 類,它能夠自動完成一些與HTTP通訊相關的配置,不過,使用該類,要以管理身份運行,否則,會無權限監聽。服務器
首先定義一個 Book 類,稍後我們會把一個Book實例以XML或JSON數據返回。函數
public sealed class Book { public string BookName { get; set; } public decimal Price { get; set; } public string BarCode { get; set; } }
而後,很重要一步,就是聲明服務協定,它是個接口,能夠對客戶端公開,固然客戶端也能夠從新定義。測試
[ServiceContract] interface IService { [OperationContract] [WebGet(UriTemplate = "getdata?f={format}")] Message GetXml(string format); }
加上ServiceContract特性代表它是服務協定,若是沒有明確指定Name,則它的名字與接口的名字相同;協定接口中,但願向客戶端公開的方法要加上OperationContract特性,不然不會被認爲是服務操做,沒法被客戶端使用。spa
服務協定接口容許在服務器和客戶端使用不一樣定義,只要協定的名稱相同,而且方法的參數和返回值類型和數目相同便可。.net
WebGet特性指定URI的使用方法,地址爲相對路徑,假如基址是http://dog.net/,那麼訪問GetXml方法的路徑爲 http://dog.net/getdata?f=xml。原本我只想返回XML數據的,因此叫GetXml,後來一想,單返回XML格式的內容也過小氣了,索性弄一個參數,來指定格式,能夠傳入xml或json。?f後面的{format}會自動把值傳給方法的format參數,因此,UriTemplate的參數名字不要寫錯,若是寫成 ?f={firmat},那就識別不了參數了。3d
而後要實現服務,實現協定接口的類型沒必要向客戶端公開,由於它是在服務器上執行的。code
public class MyService : IService { public Message GetXml(string format) { WebOperationContext context = WebOperationContext.Current; Book b = new Book { BookName = "賣女孩的小火柴", Price = 25.2M, BarCode = "2811365801" }; Message msgreturn = null; // 判斷格式 if (format.ToLower() == "xml") { msgreturn = context.CreateXmlResponse<Book>(b); } else { msgreturn = context.CreateJsonResponse<Book>(b); } return msgreturn; } }
這裏經過一個很好玩的方法來完成,因此方法返回類型爲Message。靜態屬性WebOperationContext.Current能夠獲得與當前調用的操做協定關聯的上下文對象,即WebOperationContext實例。它公開了一堆方法,名字都是 CreateXXXResponse,其中XXX是啥取決於返回內容,要返回JSON,就調用CreateJsonResponse方法,返回XML就調用CreateXmlResponse方法。
實例化Book對象後,能夠傳給帶泛型參數的CreateJsonResponse或CreateXmlResponse方法,把類型參數T指定爲Book,就會自動把Book對象序列化,而後返回給客戶端。
最後,在配置文件中給服務設定一個基址,能夠在代碼中寫,也能夠在配置文件中寫,此處老周選用配置文件,好處是能夠動態修改而沒必要從新編譯應用程序。
<system.serviceModel> <services> <service name="getXmlSample.MyService"> <host> <baseAddresses> <add baseAddress="http://localhost:1888/"/> </baseAddresses> </host> </service> </services> </system.serviceModel>
可能有初學的朋友說WCF的配置文件很難寫,其實啊,是有規律的,你不妨細心研究一下,掌握規律後你會發現配置文件並不難寫。
service的 name 屬性的值就是服務類的Type的名字(類型名,帶命名空間名稱)。
在Main中實例化WebServiceHost。
static void Main(string[] args) { WebServiceHost host = new WebServiceHost(typeof(MyService)); host.Open(); Console.WriteLine("服務已打開。"); Console.Read(); host.Close(); }
注意,傳給構造函數的Type是服務類的類型,與配置文件中service/name的值相同。
以管理員身份運行這個例子,而後打開瀏覽器,輸入http://localhost:1888/getdata?f=xml,回車後,你會看到這樣的內容:
把xml改成json,再看看。
怎麼樣,好玩吧。下面老周再演示另外一種方法。
這種方法沒使用WebServiceHost,而是使用普通的ServiceHost類來承載服務,可經過WebHttpBinding來獲得HTTP交互的支持,不過,不要忘了給終結點配置WebHttpBehavior行爲。
一樣,先定義一個類,隨後用來作測試。
[DataContract(Namespace = "http://sample",Name = "student")] public sealed class Student { [DataMember(Name = "stu_id")] public int StuID { get; set; } [DataMember(Name = "stu_name")] public string StuName { get; set; } }
這一次,我們經過將對象進行XML或JSON序列化的方式生成數據,並轉爲字符串返回。服務協定以下:
[ServiceContract] public interface IData { [OperationContract] [WebGet(UriTemplate = "getdata?f={format}")] string GetData(string format); }
和前面差很少,只是返回類型改成string。
下面代碼實現協定接口:
public class MyService : IData { public string GetData(string format) { string res = null; Student stu = new Student { StuID = 3, StuName = "小白" }; using (MemoryStream ms=new MemoryStream()) { XmlObjectSerializer sz = null; if (format != null && format.ToLower() == "xml") { sz = new DataContractSerializer(stu.GetType()); } else { sz = new DataContractJsonSerializer(stu.GetType()); } sz.WriteObject(ms, stu); res = Encoding.UTF8.GetString( ms.ToArray()); } return res; } }
接着,在配置文件中配置一下。
<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="hb"> <webHttp automaticFormatSelectionEnabled="true"/> </behavior> </endpointBehaviors> </behaviors> <services> <service name="getXmlSample2.MyService"> <endpoint address="http://localhost:2008" binding="webHttpBinding" contract="getXmlSample2.IData" behaviorConfiguration="hb"/> </service> </services> </system.serviceModel>
behaviors節點下能夠配置兩種行爲——服務行爲和終結點行爲。此處咱們只需配置終結點的行爲,須要一個webHttp元素,它映射到 WebHttpBehavior 類。記得要爲behavior節點分配名字,隨後在/services/service/endpoint節點下,才能經過behaviorConfiguration屬性來引用前面的behavior。
實現HTTP交互,應使用webHttpBinding。
在配置webHttp行爲時,應該把automaticFormatSelectionEnabled的值設置爲true,這樣一來,返回給調用方的內容會自動識別格式,其實主要目的是讓返回的字符串中可以去掉最外層的雙引號。
回到代碼,實例化ServiceHost,而後打開服務。
static void Main(string[] args) { using (ServiceHost host=new ServiceHost(typeof(MyService))) { host.Open(); Console.WriteLine("服務已打開。"); Console.Read(); } }
運行應用程序,在瀏覽中輸入http://localhost:2008/getdata?f=xml,獲得結果以下。
而後再輸入http://localhost:2008/getdata?f=json看看。
好了,就演示這兩種方法吧,你願意探索的話,方法是有不少種的。