【.net 深呼吸】聊聊WCF服務返回XML或JSON格式數據

有時候,爲了讓數據能夠「跨國經營」,尤爲是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看看。

 

 

好了,就演示這兩種方法吧,你願意探索的話,方法是有不少種的。

示例源代碼下載地址

相關文章
相關標籤/搜索