在 Windows 通用应用中消费 Web 服务





5.00/5 (3投票s)
在本文中,我们将学习如何在 Windows 通用应用中调用 Web 服务。
引言
每当您希望您的应用程序与网络通信或从网络获取/发布数据时,都需要调用 Web 服务。因此,我们将在此处了解如何在 Windows 通用应用中使用 REST Web 服务。
描述
创建一个新项目,例如“空白应用(通用应用)”,并为其指定您想要的名称。
在解决方案资源管理器中查看时,您会发现这里有三种类型的项目 - Windows 应用商店应用、Windows Phone 应用和共享项目。在这里,我们共享代码但不共享设计,因此我们将为每种类型的应用在 XAML 中单独创建设计。
从 Nuget 在两个项目(Windows 和 Windows Phone)中安装 Json.Net。它将用于 JSON 的序列化和反序列化。
现在,我们将逐步了解以专业的方式调用 REST Web 服务的流程。
步骤 1
在共享项目中创建 Global
类,该类将包含所有全局变量。
//Global class in shared project
public class Global
{
public const string RawUrl = "http://api.geonames.org/";
public const string JsonContentType = "application/json";
public const string HtmlContentType = "application/x-www-form-urlencoded";
}
第二步
为方法名称和方法类型创建 enum
。
//enums in shared project
public enum WebMethod
{
citiesJSON=1
}
public enum MethodType
{
GET = 1,
POST = 2
}
步骤 3
创建 Utility
类,该类将创建不同类型的 Uri
。
//Utility Class in shared project
public class Utility
{
/// <summary>
/// Create html Url with parameters
/// </summary>
/// <param name="rawUrl"></param>
/// <param name="webModule"></param>
/// <param name="webMethod"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static Uri CreateUri(string rawUrl, Enumerations.WebMethod webMethod, object obj)
{
StringBuilder sb = new StringBuilder();
sb.Append(rawUrl);
sb.Append("/");
sb.Append(webMethod.ToString());
sb.Append("?");
Type t = obj.GetType();
PropertyInfo[] props = t.GetRuntimeProperties().ToArray();
foreach (PropertyInfo prp in props)
{
if (prp.GetValue(obj) != null)
{
sb.Append(prp.Name);
sb.Append("=");
sb.Append(prp.GetValue(obj).ToString());
sb.Append("&");
}
}
return new Uri(sb.ToString());
}//CreateUri
/// <summary>
/// Create html Url without parameters
/// </summary>
/// <param name="rawUrl"></param>
/// <param name="webModule"></param>
/// <param name="webMethod"></param>
/// <returns></returns>
public static Uri CreateUri(string rawUrl, Enumerations.WebMethod webMethod)
{
StringBuilder sb = new StringBuilder();
sb.Append(rawUrl);
sb.Append("/");
sb.Append(webMethod.ToString());
return new Uri(sb.ToString());
}//CreateUri
public static Uri CreateUri(string rawUrl, Enumerations.WebMethod webMethod, string parameter)
{
StringBuilder sb = new StringBuilder();
sb.Append(rawUrl);
sb.Append("/");
sb.Append(webMethod.ToString());
sb.Append("/");
sb.Append(parameter);
return new Uri(sb.ToString());
}//CreateUri
/// <summary>
/// Create html Url for parameters
/// </summary>
/// <param name="rawUrl"></param>
/// <param name="webModule"></param>
/// <param name="webMethod"></param>
/// <returns></returns>
public static string CreateUriParameter(Object obj)
{
StringBuilder sb = new StringBuilder();
Type t = obj.GetType();
PropertyInfo[] props = t.GetRuntimeProperties().ToArray();
foreach (PropertyInfo prp in props)
{
if (prp.GetValue(obj) != null)
{
sb.Append(prp.Name);
sb.Append("=");
sb.Append(prp.GetValue(obj).ToString());
sb.Append("&");
}
}
return sb.ToString();
}//CreateUriParameter
public static string CreateHtmlPostData(object obj)
{
StringBuilder sb = new StringBuilder();
Type t = obj.GetType();
PropertyInfo[] props = t.GetRuntimeProperties().ToArray();
foreach (PropertyInfo prp in props)
{
if (prp.GetValue(obj) != null)
{
sb.Append("&");
sb.Append(prp.Name);
sb.Append("=");
sb.Append(prp.GetValue(obj).ToString());
}
}
return sb.ToString();
}
}
步骤 4
创建网络处理程序类,该类将包含调用 Web 服务的相关方法。
//NetworkHandler class in shared project
public class NetworkHandler
{
async public static Task<string>
PostHtmlContent(WebMethod webMethod, object requestObj,
Encoding encoding, string contentType)
{
//Initialize WebClient
HttpClient httpClient = new HttpClient();
//Call service
HttpResponseMessage response = await httpClient.PostAsync
((Utilities.Utility.CreateUri(Global.Global.RawUrl, webMethod)),
new StringContent(Utilities.Utility.CreateUriParameter(requestObj), encoding, contentType));
//Read response
string responseText = await response.Content.ReadAsStringAsync();
//Return result
return responseText;
}
async public static Task<string> GetHtmlContentByUrl(string url)
{
//Initialize WebClient
HttpClient httpClient = new HttpClient();
//Call service
HttpResponseMessage response = await httpClient.GetAsync(new Uri(url));
//Read response
string responseText = await response.Content.ReadAsStringAsync();
//Return result
return responseText;
}
async public static Task<string>
GetHtmlContent(WebMethod webMethod, object requestObj,string contentType)
{
//Initialize WebClient
HttpClient httpClient = new HttpClient();
//Call service
HttpResponseMessage response = await httpClient.GetAsync
(Utilities.Utility.CreateUri(Global.Global.RawUrl,webMethod,requestObj));
//Read response
string responseText = await response.Content.ReadAsStringAsync();
//Return result
return responseText;
}
async public static Task<string> PostJsonContent
(WebMethod webMethod, object requestObj, Encoding encoding, string contentType)
{
//Initialize WebClient
HttpClient httpClient = new HttpClient();
//Call service
HttpResponseMessage response = await httpClient.PostAsync
((Utilities.Utility.CreateUri(Global.Global.RawUrl, webMethod)),
new StringContent(JsonConvert.SerializeObject(requestObj), encoding, contentType));
//Read response
string responseText = await response.Content.ReadAsStringAsync();
//Return result
return responseText;
}
}
步骤 5
为请求和响应创建 ViewModel
类。
请求
请求是 HTML 格式,因此我们将为它的请求参数创建类。
http://api.geonames.org/citiesJSON?north=44.1&south=-9.9&east=-22.4&west=55.2&lang=de&username=demo
//GetCityRequestViewModel class in shared project
public class GetCityRequestViewModel
{
public string north { get; set; }
public string south { get; set; }
public string east { get; set; }
public string west { get; set; }
public string lang { get; set; }
public string username { get; set; }
}
响应
响应是 JSON 格式,因此我们将为它的响应参数创建类。
{"geonames":[{"lng":-99.12766456604,"geonameId":3530597,
"countrycode":"MX","name":"Mexiko-Stadt",
"fclName":"city, village,...","toponymName":"Mexico City",
"fcodeName":"capital of a political entity",
"wikipedia":"en.wikipedia.org/wiki/Mexico_City","lat":19.428472427036,
"fcl":"P","population":12294193,"fcode":"PPLC"},
{"lng":116.397228240967,"geonameId":1816670,"countrycode":"CN",
"name":"Peking","fclName":"city, village,...",
"toponymName":"Beijing","fcodeName":"capital of a political entity",
"wikipedia":"en.wikipedia.org/wiki/Beijing","lat":39.9074977414405,
"fcl":"P","population":11716620,"fcode":"PPLC"},
{"lng":120.9822,"geonameId":1701668,"countrycode":"PH",
"name":"Manila","fclName":"city, village,...",
"toponymName":"Manila","fcodeName":"capital of a political entity",
"wikipedia":"en.wikipedia.org/wiki/Manila","lat":14.6042,"fcl":
"P","population":10444527,"fcode":"PPLC"},
{"lng":90.40743827819824,"geonameId":1185241,"countrycode":
"BD","name":"Dhaka","fclName":"city, village,...",
"toponymName":"Dhaka","fcodeName":"capital of a political entity",
"wikipedia":"en.wikipedia.org/wiki/Dhaka","lat":23.710395616597037,
"fcl":"P","population":10356500,"fcode":"PPLC"},
{"lng":126.9784,"geonameId":1835848,"countrycode":"KR",
"name":"Seoul","fclName":"city, village,...",
"toponymName":"Seoul","fcodeName":"capital of a political entity",
"wikipedia":"en.wikipedia.org/wiki/Seoul","lat":37.566,"fcl":
"P","population":10349312,"fcode":"PPLC"},
{"lng":106.84513092041016,"geonameId":1642911,"countrycode":"ID",
"name":"Jakarta","fclName":"city, village,...",
"toponymName":"Jakarta","fcodeName":"capital of a political entity",
"wikipedia":"en.wikipedia.org/wiki/Jakarta","lat":-6.214623197035775,
"fcl":"P","population":8540121,"fcode":"PPLC"},
{"lng":139.69171,"geonameId":1850147,"countrycode":"JP",
"name":"Tokyo","fclName":"city, village,...",
"toponymName":"Tokyo","fcodeName":"capital of a political entity",
"wikipedia":"de.wikipedia.org/wiki/Tokyo","lat":35.6895,"fcl":
"P","population":8336599,"fcode":"PPLC"},
{"lng":121.531846,"geonameId":1668341,"countrycode":"TW",
"name":"Taipeh","fclName":"city, village,...",
"toponymName":"Taipei","fcodeName":"capital of a political entity",
"wikipedia":"de.wikipedia.org/wiki/Taipei","lat":25.047763,
"fcl":"P","population":7871900,"fcode":"PPLC"},
{"lng":-74.08175468444824,"geonameId":3688689,"countrycode":"CO",
"name":"Bogotá","fclName":"city, village,...",
"toponymName":"Bogotá","fcodeName":"capital of a political entity",
"wikipedia":"en.wikipedia.org/wiki/Bogot%C3%A1","lat":4.609705849789108,
"fcl":"P","population":7674366,"fcode":"PPLC"},
{"lng":114.157691001892,"geonameId":1819729,"countrycode":"HK",
"name":"Hong Kong","fclName":"city, village,...",
"toponymName":"Hong Kong","fcodeName":"capital of a political entity",
"wikipedia":"en.wikipedia.org/wiki/Hong_Kong","lat":22.2855225817732,
"fcl":"P","population":7012738,"fcode":"PPLC"}]
通常,为任何 JSON 创建反序列化类非常复杂。因此,我们可以使用在线工具为任何 JSON 创建反序列化类。
因此,响应类将如下所示
//GetCityResponseViewModel class in shared project
public class GetCityResponseViewModel
{
public List<Geoname> geonames { get; set; }
}
public class Geoname
{
public double lng { get; set; }
public int geonameId { get; set; }
public string countrycode { get; set; }
public string name { get; set; }
public string fclName { get; set; }
public string toponymName { get; set; }
public string fcodeName { get; set; }
public string wikipedia { get; set; }
public double lat { get; set; }
public string fcl { get; set; }
public int population { get; set; }
public string fcode { get; set; }
}
步骤 6
架构已准备就绪,现在我们将将其用于我们的应用页面。
//MainPage.Cs
protected override void OnNavigatedTo(NavigationEventArgs e)
{
//Call Webservice method
this.CallWebService(new GetCityRequestViewModel
{
north = "44.1",
south = "-9.9",
east = "-22.4",
west = "55.2",
lang = "de",
username = "username"
});
}
/// <summary>
/// calling webservice
/// </summary>
/// <param name="obj"></param>
private async void CallWebService(object obj)
{
try
{
string responseText = await NetworkHandler.GetHtmlContent
(WebMethod.citiesJSON, obj, Global.Global.HtmlContentType);
//Initialize response view Model
GetCityResponseViewModel responseViewModel = new GetCityResponseViewModel();
responseViewModel = JsonConvert.DeserializeObject<GetCityResponseViewModel>(responseText);
}
catch (Exception ex)
{
}
finally
{
}
}//CallWebService