作者:Dflying Chen ( http://dflying.cnblogs.com/ )
在前一篇文章(在ASP.NET Atlas中呼叫Web Service-建立Mashup呼叫遠端Web Service(基礎知識以及簡單範例))中,我介紹了一些Atlas中對遠端Web Service進行Mashup的基礎知識,並給了一個最基礎的沒有絲毫用處例子。今天再回到這個主題上,我將給出一個更複雜點的,但有一些用處的例子——Yahoo! Weather。
廢話到此為止,讓我們先熟悉一下Yahoo! Weather服務:Yahoo!在其網站上提供了天氣預報服務( http://weather.yahoo.com/ ),並且它也提供了Web Service的介面( http ://developer.yahoo.com/weather/ )
從上面兩個網頁上面,我們可以知道Yahoo!提供的天氣Service的URL為http://xml.weather.yahoo.com/forecastrss ,該服務還有兩個參數:
p:要查詢天氣的地點代碼(可以在http://weather.yahoo.com/查詢到不同地方的這個程式碼)。
u:回傳結果中溫度的單位,f代表華氏度,c代表攝氏度。
看來這個Yahoo! Weather服務還蠻簡單的,讓我們測試下好不好用。先到http://weather.yahoo.com/查出來上海的地點代號為CHXX0116。然後在瀏覽器中輸入http://xml.weather.yahoo.com/forecastrss?p=CHXX0116&u=c ,嗯,回傳瞭如下的一段不是很複雜的XML:
Yahoo Weather Service XML Result
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<rss version="2.0" xmlns:yweather=" http://xml.weather.yahoo.com/ns/rss/1.0 " xmlns:geo=" http://www.w3.org/2003/01/geo /wgs84_pos #">
<channel>
<title>Yahoo! Weather - Shanghai, CH</title>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/Shanghai__CH/*http://xml.weather.yahoo.com/forecast/CHXX0116_c.html</link>
<description>Yahoo! Weather for Shanghai, CH</description>
<language>en-us</language>
<lastBuildDate>Thu, 25 May 2006 11:00 am CST</lastBuildDate>
<ttl>60</ttl>
<yweather:location city="Shanghai" region="" country="CH" />
<yweather:units temperature="C" distance="km" pressure="mb" speed="kph" />
<yweather:wind chill="21" direction="260" speed="14" />
<yweather:atmosphere humidity="78" visibility="299" pressure="0" rising="0" />
<yweather:astronomy sunrise="4:52 am" sunset="6:50 pm" />
<image>
<title>Yahoo! Weather</title>
<width>142</width>
<height>18</height>
<link>http://weather.yahoo.com/</link>
<url>/u/info_img/2009-06/30/main_142b.gif</url>
</image>
<item>
<title>Conditions for Shanghai, CH at 11:00 am CST</title>
<geo:lat>31.17</geo:lat>
<geo:long>121.43</geo:long>
<link>http://us.rd.yahoo.com/dailynews/rss/weather/Shanghai__CH/*http://xml.weather.yahoo.com/forecast/CHXX0116_c.html</link>
<pubDate>Thu, 25 May 2006 11:00 am CST</pubDate>
<yweather:condition text="Fog" code="20" temp="21" date="Thu, 25 May 2006 11:00 am CST" />
<description>
<![CDATA[
<img src=" <b>Current Conditions:</b><br />
Fog, 21 C<BR /><BR />
<b>Forecast:</b><BR />
Thu - Scattered Thunderstorms. High: 25 Low: 20<br />
Fri - AM Showers. High: 26 Low: 18<br />
<br />
<a href=" http://us.rd.yahoo.com/dailynews/rss/weather/Shanghai__CH/*http://xml.weather.yahoo.com/forecast/CHXX0116_c.html"> Full Forecast at Yahoo! Weather</a><BR/>
(provided by The Weather Channel)<br/>
]]>
</description>
<yweather:forecast day="Thu" date="25 May 2006" low="20" high="25" text="Scattered Thunderstorms" code="38" />
<yweather:forecast day="Fri" date="26 May 2006" low="18" high="26" text="AM Showers" code="39" />
<guid isPermaLink="false">CHXX0116_2006_05_25_11_0_CST</guid>
</item>
</channel>
</rss>
<!-- p1.weather.scd.yahoo.com uncompressed/chunked Thu May 25 20:49:07 PDT 2006 -->
我們可以看到,它提供的資訊非常全面(連日出日落時間都有…) ,下面讓我們書寫asbx Bridge頁面來對這個Service進行Mashup。
首先,參考在ASP.NET Atlas中呼叫Web Service-建立Mashup呼叫遠端Web Service(基礎知識以及簡單範例)這篇文章中的那個asbx的聲明,我們可以寫出如下一段:
<?xml version= "1.0" encoding="utf-8" ?>
<bridge namespace="Dflying" className="YahooWeatherService">
<proxy type="Microsoft.Web.Services.BridgeRestProxy"
serviceUrl=" http://xml.weather.yahoo.com/forecastrss " />
<method name="GetWeather">
<input>
<parameter name="p" />
<parameter name="u" value="c" />
</input>
</method>
</bridge>
其中:
<bridge>的namespace和className屬性以及<method>的name屬性讓我們在客戶端JavaScript中可以透過Dflying.YahooWeatherService.GetWeather()這樣的方法簽章來存取這個Mashup。
<proxy>的serviceUrl屬性指定了Yahoo! Weather Service的URL。
GetWeather方法中定義了上面列出來的p和u兩個參數,其中u參數我們指定了它的預設值為c(代表攝氏度),p參數將由呼叫者負責傳過來。
寫到這一步驟其實也夠了,客戶端將會收到上面瀏覽器中看到的那一段XML String,並且可以在客戶端處理並顯示。但客戶端對XML的處理並不是那麼容易,也不是那麼高效,同時透過網路傳輸太多不必要的資訊也是一種浪費。所以這裡我們利用asbx中內建的Transformer對這段XML處理一下,提取出我們感興趣的內容並以JSON的形式發給客戶端。在<method>段中加入下面一段:
<transforms>
<transform type="Microsoft.Web.Services.XPathBridgeTransformer">
<data>
<attribute name="selector" value="channel" />
<dictionary name="namespaceMapping">
<item name="yweather" value=" http://xml.weather.yahoo.com/ns/rss/1.0 " />
</dictionary>
<dictionary name="selectedNodes">
<item name="Title" value="title" />
<item name="Description" value="item/description" />
<item name="CurrentCondition" value="item/yweather:condition/@text" />
</dictionary>
</data>
</transform>
</transforms>
其中<transforms>宣告表示這個Mashup方法的回傳值將會被一些transformer改變一下,裡面宣告了一個型別為Microsoft.Web.Services.XPathBridgeTransformer的transformer,表示將會用XPath表達式來轉換。在這個XPathBridgeTransformer中要聲明如下部分:
name為selector的attribute段,其中指定的value屬性為XPath表達式,將選取整個XPathBridgeTransformer將使用到的資料段。
name為namespaceMapping的一個dictionary段,其中指定了這個XML檔案中的namespace映射。如果在下面的選擇節點過程中我們用到了某個namespace,那麼這裡就必須有它的宣告。這裡我們在其中加入一個對yweather的映射,因為下面要用到。
name為selectedNodes的一個dictionary段,其中每一個item的value屬性是一個XPath String,用來從XML中選擇對應的值,name屬性用來指定對應的在JavaScript中的屬性名稱。這裡作為範例,我只取得其中三段內容,你可以看到,其中CurrentCondition的XPath中使用了上面指定的namespaceMapping。
關於XPath的知識,我就不多講了,有興趣或是不太熟悉的朋友可以自行Google,網路資源很多。關於其他類型的Transformer,我也不是很熟悉,今後如果遇到了我再講講。完成後的YahooWeatherBridge.asbx檔案如下:
<?xml version="1.0" encoding="utf-8" ?>
<bridge namespace="Dflying" className="YahooWeatherService">
<proxy type="Microsoft.Web.Services.BridgeRestProxy"
serviceUrl=" http://xml.weather.yahoo.com/forecastrss " />
<method name="GetWeather">
<input>
<parameter name="p" />
<parameter name="u" value="c" />
</input>
<transforms>
<transform type="Microsoft.Web.Services.XPathBridgeTransformer">
<data>
<attribute name="selector" value="channel" />
<dictionary name="namespaceMapping">
<item name="yweather" value=" http://xml.weather.yahoo.com/ns/rss/1.0 " />
</dictionary>
<dictionary name="selectedNodes">
<item name="Title" value="title" />
<item name="Description" value="item/description" />
<item name="CurrentCondition" value="item/yweather:condition/@text" />
</dictionary>
</data>
</transform>
</transforms>
</method>
</bridge>
現在建立一個ASP.NET Page測試一下,首先依然是重複了一千遍的ScriptManager,還有對Bridge的引用: <atlas:ScriptManager ID="sm" runat="server">
<Services>
<atlas:ServiceReference Path="YahooWeatherBridge.asbx" />
</Services>
</atlas:ScriptManager>
然後一個HTML Select元素,裡面列入了幾個城市以及相應的城市代碼:
<!-- place selector -->
<select id="place">
<option selected="selected" value="CHXX0116">Shanghai, CH</option>
<option value="USCA0746">Mountain View, CA</option>
<option value="CHXX0008">Beijing, CH</option>
</select>
一個HTML Button,用來觸發對Service的呼叫:
<!-- invoke the service -->
<input id="getWeather" type="button" value="Get Weather" onclick="return getWeather_onclick()" />
一段HTML用來顯示結果:
<!-- display result -->
<div id="result" style="display: none;">
<div style="background-color: Gray; font-weight: bold;">Title</div>
<div id="title"></div>
<div style="background-color: Gray; font-weight: bold;">Description</div>
<div id="description"></div>
</div>
然後是JavaScript,可以看到透過Dflying.YahooWeatherService.GetWeather()呼叫了Mashup,並在方法返回後把經過transform的值輸出到了頁面上: function getWeather_onclick() {
// new atlas 'Select' control
var place = new Sys.UI.Select($('place'));
// invoke the bridge method
Dflying.YahooWeatherService.GetWeather({'p': place.get_selectedValue()}, onGetComplete);
}
function onGetComplete(result) {
$('result').style.display = "block";
$('title').innerHTML = result[0].Title;
$('description').innerHTML = result[0].Description;
}