首先,我們通過HttpWatch來分析此示例所發起的http請求,可擷取到全球本地化搜尋服務的請求路徑和相關的參數,下圖為HttpWatch請求跟蹤截圖:
由此,我們可以得到Google全球本地化搜尋服務的位址,通過分析并可得到所請求的URL位址中的q即為所查詢的地點名,詳細如下URL:
http://www.google.com/uds/GlocalSearch?callback=google.search.LocalSearch.RawCompletion&context=7&rsz=small&hl=zh-CN&gss=.com&sig=3268c2f995b8fbd3048de51c45033694&q=%E5%8C%97%E4%BA%AC&near=(39.904214%2C%20116.40741300000002)&key=ABQIAAAAjU0EJWnWPMv7oQ-jjS7dYxQ82LsCgTSsdpNEnBsExtoeJv4cdBSUkiLH6ntmAr_5O4EfjDwOa0oZBQ&v=1.0&nocache=1298294307822
實際上很多的很多的參數我們都是可以省略的,隻要保持關鍵的請求參數同樣不影響請求且能夠正确的傳回我們需要的結果,是以,可以對上面長段的URL位址進行瘦身,得到如下的簡化版全球本地化請求位址:
在實際使用中指需要将q參數替換為我們要搜尋的地點名就可以了,是以可以将上面的URL位址改寫為如下字元串格式,友善程式中靈活的設值并調用該服務。
http://www.google.com/uds/GlocalSearch?q={0}&key=ABQIAAAAjU0EJWnWPMv7oQ-jjS7dYxQ82LsCgTSsdpNEnBsExtoeJv4cdBSUkiLH6ntmAr_5O4EfjDwOa0oZBQ&v=1.0&nocache=1298223400032
做過Silverlight開發的朋友都知道,在Silverlight中發起HTTP請求會受到跨域安全性的限制,如果所請求的伺服器沒有配置Silverlight的安全通路政策,Silverlight所發起的HTTP請求将會産生“System.Security.SecurityException ---> System.Security.SecurityException: 安全性錯誤。”的異常。是以要想在Silverlight中直接向此位址發起HTTP請求是行不通的了,我們需要通過别的間接方式去實作通路該位址來達到我們的目的,實際上要做的工作就是避開HTTP通路安全性限制。
通常情況下我們有兩種方式可以避免HTTP請求安全通路的限制,既采用AJAX技術異步請求和在伺服器端實作HTTP的同步或異步請求。接下來将要介紹的就是通過伺服器端實作HTTP請求,然後将結果中轉到Silverlight用戶端。這裡我們需要開發一個HTTP接口供Silverlight調用。
/// <summary>
/// 接口實作向Google全球本地化搜尋服務發起HTTP請求,然後将結果處理後傳回到用戶端。
/// </summary>
public class GoogleHandler : IHttpHandler
{
private string url = @"http://www.google.com/uds/GlocalSearch?q={0}&key=ABQIAAAAjU0EJWnWPMv7oQ-jjS7dYxQ82LsCgTSsdpNEnBsExtoeJv4cdBSUkiLH6ntmAr_5O4EfjDwOa0oZBQ&v=1.0&nocache=1298223400032";
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
if (context.Request.QueryString["q"] == null) return;
string q = HttpUtility.UrlEncode(context.Request.QueryString["q"]).ToUpper();
url = string.Format(url, q);
WebClient client = new WebClient();
string result = client.DownloadString(new Uri(url));
result = result.Substring(result.IndexOf("GsearchResultClass")-2);
result = result.Substring(0, result.IndexOf("cursor") - 3);
context.Response.Write(result);
}
public bool IsReusable
get
{
return false;
}
}
public class QueryResult
public string GsearchResultClass { get; set; }
public string listingType { get; set; }
public string lat { get; set; }
public string lng { get; set; }
public string accuracy { get; set; }
public string title { get; set; }
public string titleNoFormatting { get; set; }
public string ddUrl { get; set; }
public string ddUrlToHere { get; set; }
public string ddUrlFromHere { get; set; }
public string streetAddress { get; set; }
public string city { get; set; }
public string region { get; set; }
public string country { get; set; }
public string staticMapUrl { get; set; }
public string url { get; set; }
public string postalCode { get; set; }
public string maxAge { get; set; }
public string addressLines { get; set; }
有了上面的實體對象,當得到請求所傳回的JSON字元串後就可以通過JSON序列化既可實作JSON字元串到對象的轉換,是以我們還需要定義一個JSON序列号方法以便開發中使用。
public sealed class JsonHelper<T>
/// <summary>
/// 解析JSON格式字元串為指定的對象資料結構
/// </summary>
/// <param name="jsonString">JSON字元串</param>
/// <returns>T</returns>
public static T ResolveObject(string jsonString)
DataContractJsonSerializer ds = new DataContractJsonSerializer(typeof(T));
MemoryStream ms = new MemoryStream(Encoding.Unicode.GetBytes(jsonString));
T t = (T)ds.ReadObject(ms);
return t;
到處,就隻剩下最後一步了,在Bing Maps(Silverlight)中将要搜尋的地名通過自己開發的接口傳遞給Google全球本地化搜尋服務接口。下圖為示例程式解決方案截圖:
在示例程式中提供一個文本輸入空間實作地名錄入,通過按鈕發起請求,然後将部分結果呈現在地圖指定的UI面闆上,傳回的資料中由于帶有地理坐标(經度,緯度),還可以使用此地理坐标進行地圖定位,每當成功搜尋到某地名後就将地圖定位帶該地名所在的位置。
<StackPanel Margin="2" Width="160" Height="140" VerticalAlignment="Top" HorizontalAlignment="Right">
<TextBox Name="tbAddress" Margin="5" Height="23"></TextBox>
<Button Content="搜尋" x:Name="btnQuery" Width="70" Height="30" Click="btnQuery_Click"></Button>
<Border CornerRadius="8" BorderThickness="1" Height="70" Margin="3" x:Name="queryResult">
<StackPanel>
<StackPanel.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#FF305867" Offset="0" />
<GradientStop Color="#FFABE2F7" Offset="1" />
</LinearGradientBrush>
</StackPanel.Background>
<TextBlock Text="{Binding city}" Height="23" Margin="0,8,0,0"></TextBlock>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding lng}" Height="30" Width="Auto"></TextBlock>
<TextBlock Text="," Height="30" Width="Auto"></TextBlock>
<TextBlock Text="{Binding lat}" Height="30" Width="Auto"></TextBlock>
</StackPanel>
</StackPanel>
</Border>
<StackPanel.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#cccccc" Offset="0" />
<GradientStop Color="White" Offset="1" />
</LinearGradientBrush>
</StackPanel.Background>
</StackPanel>
在Silverlight中可以通過WebClient發起簡單的HTTP請求,如下代碼塊所示:
/// 請求Google全球本地化搜尋服務的接口位址
private string service = "http://localhost:28768/GoogleHandler.ashx?q={0}";
private void btnQuery_Click(object sender, RoutedEventArgs e)
var address = this.tbAddress.Text.Trim();
var client = new WebClient();
client.DownloadStringCompleted += client_DownloadStringCompleted;
client.DownloadStringAsync(new Uri(string.Format(service, address), UriKind.Absolute));
private void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
if (e.Error == null)
try
QueryResult result = JsonHelper<QueryResult>.ResolveObject(e.Result);
this.queryResult.DataContext = result;
this.map.Center = new Location(double.Parse(result.lat), double.Parse(result.lng));
catch (Exception)
通過這種方式請求所得到的結果是英文的,如果要傳回中文資料,隻需要将Google全球本地化搜尋服務的請求路徑稍加修改,在請求參數中加上hl=zh-CN就行了。
本文轉自 beniao 51CTO部落格,原文連結:http://blog.51cto.com/beniao/498747,如需轉載請自行聯系原作者