在建設網站的時候,有時會遇到根據不同國家的訪客顯示不同信息的需求。尤其是網站所用語言的國際化要求,比如對美國的訪客顯示英語,對中國的訪客顯示中文。
有兩種途徑能夠解決此問題。
一. 使用CultureInfo與RegionInfo類
public static string GetISORegionName(HttpRequest request) { var lan = request.UserLanguages.First(); var cultureInfo = CultureInfo.CreateSpecificCulture(lan); var regionInfo = new RegionInfo(cultureInfo.LCID); return regionInfo.TwoLetterISORegionName; }
- 通過Request取得訪客客戶端所用語言
- 由該語言代碼生成CultureInfo
- 由所生成的CultureInfo的LCID生成RegionInfo
- 取得RegionInfo的TwoLetterISORegionName值,即ISO 3166中使用兩位字母所代表的國家/地區
* 使用中文環境的客戶端(zh-CN)會得到"CN"的結果,而使用英文環境的客戶端(en-US)則會得到"US"。
* 這種方法很明顯會有個問題,判斷的結果依賴訪客的客戶端語言環境而非真實的所在國家地理位置。
二. 使用MaxMind的免費數據庫及相關API
通過IP地址取得對應的國家地理位置,可以采用數據供應商所提供的數據庫,以一般查詢的方式獲得相應的信息。不過這些數據庫通常是需要付費的。
當然也有免費的產品,比如MaxMind發布的免費數據庫。
數據庫的下載地址:http://geolite.maxmind.com/download/geoip/database/GeoLite2-Country.mmdb.gz
需要用到的dll可以由NuGet方法取得, PM> Install-Package MaxMind.GeoIP2 ,安裝完成后項目中會新加MaxMind.Db以及MaxMind.GeoIP2兩個dll引用。
在調用GeoIP2的API之前,還需要完成一項工作,即取得訪客的IP地址。
最簡單的方式是使用 HttpContext.Current.Request.UserHostAddress ,不過在訪客使用代理服務器的場景下,此方式所獲得的IP地址就是不正確的了。
因此需要變更方法,改用下列的代碼:
public static string GetClientIpAddress(HttpRequest request) { var userHostAddress = request.UserHostAddress; var xForwardedFor = request.ServerVariables["X_FORWARDED_FOR"]; if (string.IsNullOrEmpty(xForwardedFor)) return userHostAddress; var forwardingIps = xForwardedFor.Split(',').ToList(); return forwardingIps.Any() ? forwardingIps.Last() : userHostAddress; }
當這一步完成后,就可以進入正題,調用GeoIP2的API以獲得訪客所處的國家。
public static string GetISOCodeByMaxMind(HttpRequest request) { using (var reader = new DatabaseReader(HttpContext.Current.Server.MapPath("~/GeoLite2-Country.mmdb"))) { var ipAddress = GetClientIpAddress(request); var country = reader.Country(ipAddress); return country.Country.IsoCode; } }
- 實例化DatabaseReader,將數據庫所在路徑作為其構造方法的參數
- 取得客戶端IP地址
- 由IP地址查詢所在國家
- 得到國家的IsoCode,同樣是ISO 3166中使用兩位字母所代表的國家/地區
* 如果無法從數據庫中取得對應信息,上述方法會拋出異常,所以在實際開發時有必要加上try/catch語句加以控制。