天天看點

[轉]Xml WebService完全執行個體解析

    最近閑來無事,想起blog很久沒寫新文章了,幹脆來寫個專題好了,想來想去,幹脆寫個有關webservice的示例文章吧.

        首先,我們必須了解什麼是webservice.就概念上來說,可能比較複雜,不過我們可以有個宏觀的了解:webservice就是個對外的接口,裡面 有函數可供外部客戶調用(注意:裡面同樣有客戶不可調用的函數).假若我們是服務端,我們寫好了個webservice,然後把它給了客戶(同時我們給了 他們調用規則),客戶就可以在從服務端擷取資訊時處于一個相對透明的狀态.即是客戶不了解(也不需要)其過程,他們隻擷取資料.

        webservice傳遞的資料隻能是序列化的資料,典型的就是xml資料,這裡我們也隻讨論xml資料的傳輸.

        有了一些對xml webservice的初步了解後,我們将切入正題,即是用一個具體的webservice事例的形式來講解具體的webservice用法,用具體的事例來講解一個概念我想怎麼也要比單純的說理能讓人容易了解吧.

        這裡,我們将以一個簡單的分布式課件搜尋系統為例來講解.使用VS2003為編譯環境,C#為語言,SqlServcer2000為資料庫.(這個例子來 源于一位網上朋友的文章的啟發,覺得很能代表webservice的特點,就按那個想法做了這麼個系統來示例了)

       首先,明确我們要做什麼.我們需要一個對客戶的接口,也就是個站點,我們把它稱做ServiceGatherSite,它是何種形式都無所謂,甚至它本身 并不需要資料庫,它隻是提供給使用者一個查詢的接口,真正的服務,普通使用者是不接觸到的.然後,這裡我們還需要若幹個提供服務的站點,我們可以稱它們為資源 站,這裡為簡單起見,假設有兩個資源站,分别叫WebSiteA,WebSiteB,它們可以是不對外公布的,隻是為了豐富查詢資料而存在.最後,是我們 最需要關注的東西---資源站提供給ServiceGatherSite的服務.兩個資源站,就有兩個服務,我們稱為SiteAService和 SiteBService.兩個服務間沒有任何關系,内部提供的方法也完全沒關聯,隻是需要把方法如何使用告訴ServiceGatherSite,意思 是,服務隻提供查詢接口,傳回的資料如何處理,服務本身并不管,全由使用服務的站點配置設定.

       寫了這麼多,算是簡要的介紹了下有關xml webservice的概念和我們這個例子的結構,下篇文章,我們将開始真正進入代碼的設計階段.

    上篇文章介紹了些webservice的基本特性和我們例子的結構,這篇文章我們将開始具體的代碼編寫工作.

      這個專題主要講述的是webservice,是以這裡我們的代碼以Webservice相關為主,而其他工程,例如:ServiceGatherSite,WebSiteA等,隻将簡略介紹.

      在VS2003中,開發一個webservice并不是件困難的事,首先,我們建立一個webservice項目(檔案->建立->項目->C#->Web服務應用程式)

      建完這個工程,我們将看到一個叫Service1.asmx的檔案,這就是webservice的标準檔案,它也有UI的概念,不過我們一般不關注,因 此,我們檢視其cs代碼檔案.如果你什麼都還沒做的話,将看見一個被注釋掉的helloworld的WebMethod,把注釋去掉,在運作,你就可以得 到最簡單的webservice運作執行個體了.點選"helloworld"将執行其方法.顯然,這個函數對我們的意義隻在于宏觀的了解了下web服務的寫 法.

      下面,我們将開始具體介紹webservice的寫法.在代碼檔案裡,如果我們寫了一個函數後,希望此函數成為外部可調用的接口函數,我們必須在函數上面 添上一行代碼[WebMethod(Description="函數的描述資訊")],如果你的函數沒有這個申明,它将不能被使用者引用.如:

[WebMethod(Description = " 最簡單的方法 " )]

   public   string  HelloWorld()

  {

    return   " Hello World " ;

  }

      這個函數就是外部可調用的接口函數,對使用者來說相當于一個API.如果某使用者在引用了這個服務後,他調用HelloWorld()方法,他就将獲得"HelloWorld"這個傳回值.

       看到這裡,我們是不是發現,其實webservice并不是那麼的神秘,它也不過隻是個接口,對我們而言,側重點依然是接口函數的編寫.下面,我将給出我們的例子所需要的接口函數.

[WebMethod(Description = " 查詢以擷取需要的課件資訊 " )]

   public  XmlDataDocument GetSiteAData( string  AssignName)

  {

   XmlDataDocument xd = new  XmlDataDocument();  //

   DataSet ds = new  DataSet();

   CStoreProc cp = new  CStoreProc( " SearchAssign " );

   cp.AddParIn( " @keywords " ,SqlDbType.VarChar, 30 ,AssignName);

   cp.AddParOut( " @res " ,SqlDbType.Int);

    if (cp.SelectProc())  // 如果執行成功,存儲過程

   {

    cp.myData.EnforceConstraints = false ;  // 不進行格式嚴格檢查

     if (( int )cp.GetReturnValue( " @res " ) ==- 1 )

    {

      string  xml = " <NewDataSet></NewDataSet> " ;

     xd.LoadXml(xml);

      return  xd;

    }

    xd = new  XmlDataDocument(cp.myData);

    XmlNode root1 = xd.DocumentElement;

    XmlNodeList roots = root1.SelectNodes( " list " );  

     foreach (XmlNode roota  in   roots)   // 為所有元素加上站點名稱标記

   {

     XmlElement Link = xd.CreateElement( " SiteName " );

     Link.InnerText = ConfigurationSettings.AppSettings[ " SiteName " ].ToString();

     roota.AppendChild(Link);

    }

     return  xd;

   }

    else   return   null ;

  }

 這是擷取資源站點資訊的一個接口函數.裡面大部分的代碼,我想對于有一定asp.net基礎的朋友來說,都應該是一看就明白,這裡隻說明下CStoreProc,這是我封裝的一個存儲過程類,主要功能是執行各種類型的存儲過程.

         細心的朋友可能會發現這個函數的傳回類型似乎比較特殊,是個xml的文檔.我們在前面已經說過,webservice隻能傳輸序列化資料,xml顯然滿足 條件,但比如hash表之類的非序列化資料,是不能傳輸的,xml使用最為廣泛,而且考慮到跨平台應用,是以這裡我們隻以xml資料的傳輸來示例.

         在下篇文章,我們将深入解析webservice的精髓---xml 資料傳輸.

    接上篇文章,我們先簡單解釋下GetSiteAData(string AssignName)函數.

         函數功能很簡單,隻是要傳回查詢結果,其資料格式是XmlDataDocument.當查詢失敗時(無比對查詢結果),我們構造一個xml,傳回一個空記 錄.否則,我們把查詢後的dataset生成一個XmlDataDocument,接下來,由于該項目的需要,我加入了一個循環,添加dataset裡所 沒有的節點,站點名稱.在這之後,算是完成了一個符合我們期望格式的xml資料文檔,我們把它傳回.

         好了,webservice的方法函數介紹完了(這裡還有個web服務方法,稍後介紹),接下來我們的任務是怎麼調用它了.首先把webservice的 項目編譯完成,假定我們這個服務是針對資源站點A的,我們不妨稱其為ServiceA.先單獨運作asmx檔案,執行GetSiteAData (string AssignName)方法,将提示你輸入參數,你輸入要搜尋的内容,點确認,将傳回給你一個xml資料,并在ie上顯示出來,這就是你搜尋到的内容拉.

        這裡對ServiceA的工作再做點介紹,在我們這個項目裡,它是資源站點A提供的服務,意思是,它查詢的資料将全來源于站點A,而站點A資源添加在本項目也有專門的工程實作.

        好了,回到正題.這裡我介紹vs調用webservice的方法,其實其他平台的調用方法也是大同小異.首先我們介紹web引用方式,這種方式我強烈建議 調試時使用,非常友善.右擊引用,點添加web引用,輸入你的webservice位址,如:http: //localhost/aspxproject/WebServiceSolution/SiteBService/service1.asmx,你必 須保證你輸入的webservice存在.然後引用即可,注意:web引用名将作為你加入的webservice的名字空間.比如你輸入了:SiteA, 那服務的執行個體化将是這樣:SiteA.Service1 serviceA=new SiteA.Service1();(Service1是服務的類名).

        完成了這一步,service的調用似乎變的那麼簡單,我們已經實作了遠端執行個體化,接下來的遠端調用也是一樣的容易.下面給出資源采集站ServiceGatherSite的綁定代碼(隻采集A站點的資訊)

// 綁定資料

   public   void  BindData()

  {

   serviceA = new  SiteA.Service1();

   DataSet ds = new  DataSet();

   XmlNode xmlNode1;

   XmlDataDocument xd = new  XmlDataDocument();

   StringBuilder xmlString1;

   xmlNode1 = serviceA.GetSiteAData(strSearch);

    if (xmlNode1 == null )  // --存儲過程執行失敗

     return ;

   xmlString1 = new  StringBuilder(xmlNode1.OuterXml);

    if (xmlString1.ToString().Equals( " <NewDataSet xmlns= """" ></NewDataSet> " ))

     return  ;

   xd.LoadXml(xmlString1.ToString());

   ds.ReadXml( new  XmlNodeReader(xd));

   DataGrid1.DataSource = ds.Tables[ " list " ].DefaultView;

   DataGrid1.DataBind();

  }

        此段代碼給出了xml轉化成dataset的解決方案,雖然這不是必須的,但畢竟在asp.net裡,dataset占的作用之重,誰都知道的.其他的請 朋友們先看(呵呵,個中高手就免了),在下篇文章中将會有對它的一些解釋與及多服務分布調用的解決方案,寫了三篇了,發現似乎還是有些朋友看的,那我就獻 醜繼續寫下去好了,大家有什麼意見也希望提出,在下的了解存在偏駁也再所難免,希望諒解:)

    接上篇文章,我們先簡單說明下綁定函數.首先執行個體化ServiceA,這個和一般類的執行個體化并沒有不同..接下來用xmlNode1來接受函數的傳回值,接下來是構造xml,并将其轉化為dataset,這是通用的方法,如果是剛接觸不久的朋友,最好能記下這種方法.

      接下來給出異步調用兩個服務的代碼

// 綁定資料

   public   void  BindData()

  {

   IAsyncResult ar1;

   IAsyncResult ar2;

   serviceA = new  SiteA.Service1();

   serviceB = new  SiteB.Service1();

   DataSet ds = new  DataSet();

   XmlNode xmlNode1,xmlNode2;

   XmlDataDocument xd = new  XmlDataDocument();

   StringBuilder xmlString1,xmlString2;

    // --簡單的異步調用

   ar1 = serviceA.BeginGetSiteAData(strSearch, null , null );

   ar2 = serviceB.BeginGetSiteAData(strSearch, null , null );

   xmlNode1 = serviceA.EndGetSiteAData(ar1);

   xmlNode2 = serviceB.EndGetSiteAData(ar2);

    // ----------

    if (xmlNode1 == null && xmlNode2 == null )  // --存儲過程執行失敗

     return ;

 xmlString1 = new  StringBuilder(xmlNode1.OuterXml);

   xmlString2 = new  StringBuilder(xmlNode2.OuterXml);

   xmlString1 = MakeNewXmlString(xmlString1,xmlString2);   // 生成新的xml

    if (xmlString1.ToString().Equals( " <NewDataSet xmlns= """" ></NewDataSet> " ))

     return  ;

   xd.LoadXml(xmlString1.ToString());

   ds.ReadXml( new  XmlNodeReader(xd));

   DataGrid1.DataSource = ds.Tables[ " list " ].DefaultView;

   DataGrid1.DataBind();

  }

   // 生成新XML

   public  StringBuilder MakeNewXmlString(StringBuilder str1,StringBuilder str2)

  {

   str1 = str1.Replace( " </NewDataSet> " , "" );

   str2 = str2.Replace( " <NewDataSet xmlns= """" > " , "" );

   str1.Append(str2.ToString());

    return  str1;

  }

    這有兩個需要注意的地方,一個是xml構造,還有就是異步調用的實作,請讀者,自己了解

    下面講下通過dll來引用webservice的方法,我隻把流程介紹下.

    首先,在ie輸入服務的位址,如:http://www.xxx.com/service.asmx

    然後寫輸入http://www.xxx.com/service.asmx?wsdl

打開後,另存為xxx.wsdl

   然後用vs的指令提示符來編譯:wsdl /namespace:SiteA ServiceA.wsdl

  生成名字空間為sitea的代理類

  最後csc /out:ServiceA.dll /t:library Service1.cs ,其中service1.cs為代理類檔案

 最後引用dll就可以了.

  到這裡,我們的例子基本也就介紹完了,由于個人的原因,最後一篇可能寫的比較倉促,非常慚愧.

  不知道寫這麼多,對學習中的朋友會不會有幫助,裡面的東西,很多也算是個人了解,如果出錯,還請各位海涵:)

轉載于:https://www.cnblogs.com/raindust/archive/2007/09/11/890083.html