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


有時候,為了讓數據可以“跨國經營”,尤其是HTTP Web有關的東東,會將數據內容以 XML 或 JSON 的格式返回,這樣一來,不管客戶端平台是四大文明古國,還是處於蒙昧時代的原始部落,都可以使用這些數據。

在WCF中實現將數據以XML或JSON格式返回有Y多種方法,不管你用什么方法,只要得到預期結果就好,米芾說了,筆可以八面出鋒,當然了,人家指的是繪畫。

 

這里,老周就挑兩種方法來演示,僅供參考,沒有考古價值,建議司馬子長不要把本文收入《史記》。

 

第一種方法是用到 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特性,否則不會被認為是服務操作,無法被客戶端使用。

服務協定接口允許在服務器和客戶端使用不同定義,只要協定的名稱相同,並且方法的參數和返回值類型和數目相同即可。

WebGet特性指定URI的使用方法,地址為相對路徑,假如基址是http://dog.net/,那么訪問GetXml方法的路徑為 http://dog.net/getdata?f=xml。本來我只想返回XML數據的,所以叫GetXml,后來一想,單返回XML格式的內容也太小氣了,索性弄一個參數,來指定格式,可以傳入xml或json。?f后面的{format}會自動把值傳給方法的format參數,所以,UriTemplate的參數名字不要寫錯,如果寫成 ?f={firmat},那就識別不了參數了。

 

然后要實現服務,實現協定接口的類型不必向客戶端公開,因為它是在服務器上執行的。

    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看看。

 

 

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

示例源代碼下載地址

 


免責聲明!

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



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