Windows Phone - 與Mobile Service - 資料庫存取,交個朋友
過去在撰寫WP的App時,如果程式的內容物來自Server的話總是要去找一台Server放置自己撰寫好的Service,
對於有主機代管或家裡有強大Server的開發者也許不是問題,但如果是像我這種小型的開發者其實就沒有這麼方便。
好在現在MS在Azure上推出了Mobile Service,透過熟悉的REST API的方式與它進行交互,維護自訂好的Data Table與Object,
相當的方便與實用,因此,該篇將撰寫個人在與Mobile Service交流的過程。
〉Mobile Service:
參考<如何透過WP7存取Mobile Services(BETA)>所介紹的方式,建立一個Mobile Service與建立個Table,
以本文範例則是建立一個Reject的物件。透過圖示加以說明:
(a) 建立一個Mobile Service;
(b) 建立一個Table與定義該Table Schema;
該Table命名為:Reject,具有欄位:id、Icon、Responser、DateTime、PhoneNumber、Message。
(c) 設定Table的操作權限(需透過application key進行操作);
從以上定義好的Mobile Service與要操作的Table,接下來要針對Table內的物件進行操作。
〉WP7 with Mobile Service:
由於Mobile Service沒有提供WP 7操作的SDK,所以需要透過REST API與JSON來進行操作,操作前準備一下相關的URI:
‧Mobile Service Name:https://wpproject.azure-mobile.net/;
‧操作資料表:Reject;
‧id(編號):按照資料儲存的id欄位值為主;
REST API | URI |
GET - 取得所有資料 | https://[Mobile Service Name].azure-mobile.net/tables/[Table Name]/ |
GET - 得指定資料 | https://[Mobile Service Name].azure-mobile.net/tables/[Table Name]/[id(編號)] |
POST - 新增一筆資料 | https://[Mobile Service Name].azure-mobile.net/tables/[Table Name]/ |
PATCH - 更新指定資料 | https://[Mobile Service Name].azure-mobile.net/tables/[Table Name]/[id(編號)] |
DELETE - 刪除指定資料 | https://[Mobile Service Name].azure-mobile.net/tables/[Table Name]/[id(編號)] |
這些URI搭配我們將該資料表物件化後,再轉換成JSON發送給Mobile Service即可以完成以上五種的操作。
(a) 建立將物件與JSON互相轉換的類別;
詳細資料參考<[教學影片][研討會] Windows Azure Mobile Services 三部曲>的內容;
1: //需加入"System.Runtime.Serialization"與"System.Servicemodel.Web"二個參考至專案
2:
3: using System.Runtime.Serialization;
4: using System.Runtime.Serialization.Json;
5:
6: public class JsonHelper
7: {
8: /// <summary>
9: /// Json to Object。
10: /// </summary>
11: /// <param name="pJson">Json</param>
12: /// <param name="pType">Object Type</param>
13: /// <returns>Object</returns>
14: public static object JsonToObject(string pJson, Type pType)
15: {
16: try
17: {
18: object tObj = null;
19: MemoryStream tMStream = new MemoryStream(Encoding.UTF8.GetBytes(pJson));
20: DataContractJsonSerializer tSer = new DataContractJsonSerializer(pType);
21: tObj = tSer.ReadObject(tMStream);
22: tMStream.Close();
23: return tObj;
24: }
25: catch (Exception)
26: {
27: throw;
28: }
29: }
30:
31: /// <summary>
32: /// Object to Json。
33: /// </summary>
34: /// <param name="pObj">Object</param>
35: /// <param name="pType">Object Type</param>
36: /// <returns>Json</returns>
37: public static string ObjectToJson(object pObj, Type pType)
38: {
39: try
40: {
41: MemoryStream tMStream = new MemoryStream();
42: DataContractJsonSerializer tSer = new DataContractJsonSerializer(pType);
43: tSer.WriteObject(tMStream, pObj);
44: byte[] tJson = tMStream.ToArray();
45: tMStream.Close();
46: return Encoding.UTF8.GetString(tJson, 0, tJson.Length);
47: }
48: catch (Exception)
49: {
50: throw;
51: }
52: }
(b) 定義Reject資料表中的物件,並且加上Serialized的宣告;
1: //記得宣告該類別為DataContract。
2: [DataContract()]
3: public class MobileService_Reject
4: {
5: // id為Mobile Service必要的欄位,需採用IgnoreDataMember來避免它產生代號。
6: [IgnoreDataMember()]
7: public int id { get; set; }
8: [DataMember()]
9: public string Icon { get; set; }
10: [DataMember()]
11: public string Responser { get; set; }
12: [DataMember()]
13: public string DateTime { get; set; }
14: [DataMember()]
15: public string PhoneNumber { get; set; }
16: [DataMember()]
17: public string Message { get; set; }
18: }
(c) 利用REST API操作Reject資料表的資料;
c-1. 取得指定id = 1的資料表;
1: private void btnGet_Click(object sender, RoutedEventArgs e)
2: {
3: WebClient tWebClient = new WebClient();
4: tWebClient.UploadStringCompleted += tWebClient_UploadStringCompleted;
5: tWebClient.DownloadStringCompleted += tWebClient_DownloadStringCompleted;
6:
7: //Get Reject Data
8: tWebClient.DownloadStringAsync(new Uri(gURI + "1"));
9: }
c-2. 新增一個新的資料;
1: private void btnInsert_Click(object sender, RoutedEventArgs e)
2: {
3: WebClient tWebClient = new WebClient();
4: tWebClient.UploadStringCompleted += tWebClient_UploadStringCompleted;
5: tWebClient.DownloadStringCompleted += tWebClient_DownloadStringCompleted;
6:
7: //Insert Reject Data
8: tWebClient.Headers["Content-Type"] = "application/json";
9: tWebClient.Headers["X-ZUMO-APPLICATION"] = gAppKey;
10: tWebClient.UploadStringAsync(
11: new Uri(gURI),
12: "POST",
13: JsonHelper.ObjectToJson(GetObject(), typeof(MobileService_Reject)));
14: }
c-3. 更新id=1的資料;
1: private void btnUpdate_Click(object sender, RoutedEventArgs e)
2: {
3: WebClient tWebClient = new WebClient();
4: tWebClient.UploadStringCompleted += tWebClient_UploadStringCompleted;
5: tWebClient.DownloadStringCompleted += tWebClient_DownloadStringCompleted;
6:
7: //Update Reject Data
8: tWebClient.Headers["Content-Type"] = "application/json";
9: tWebClient.Headers["X-ZUMO-APPLICATION"] = gAppKey;
10: tWebClient.UploadStringAsync(
11: new Uri(gURI + "1"),
12: "PATCH",
13: JsonHelper.ObjectToJson(GetObject(), typeof(MobileService_Reject)));
14: }
c-4. 刪除id=1的資料;
1: private void btnDelete_Click(object sender, RoutedEventArgs e)
2: {
3: WebClient tWebClient = new WebClient();
4: tWebClient.UploadStringCompleted += tWebClient_UploadStringCompleted;
5: tWebClient.DownloadStringCompleted += tWebClient_DownloadStringCompleted;
6:
7: //Delete Reject Data
8: tWebClient.Headers["Content-Type"] = "application/json";
9: tWebClient.Headers["X-ZUMO-APPLICATION"] = gAppKey;
10: tWebClient.UploadStringAsync(
11: new Uri(gURI + "1"),
12: "DELETE",
13: JsonHelper.ObjectToJson(GetObject(), typeof(MobileService_Reject)));
14: }
c-5. 處理DownloadStringCompleted與UploadStringCompleted;
1: void tWebClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
2: {
3: string tMsg = string.Empty;
4:
5: if (e.Error == null)
6: {
7: tMsg = e.Result;
8: }
9: else
10: {
11: tMsg = e.Error.Message;
12: }
13: Dispatcher.BeginInvoke(() =>
14: {
15: MessageBox.Show(tMsg, "Get Data from Azure", MessageBoxButton.OK);
16: });
17:
18: }
19:
20: void tWebClient_UploadStringCompleted(object sender, UploadStringCompletedEventArgs e)
21: {
22: string tMsg = string.Empty;
23:
24: if (e.Error == null)
25: {
26: tMsg = "Success";
27: }
28: else
29: {
30: tMsg = e.Error.Message;
31: }
32: Dispatcher.BeginInvoke(() =>
33: {
34: MessageBox.Show(tMsg, "UploadString to Azure", MessageBoxButton.OK);
35: });
36: }
以上是介紹透過WP7配合REST API存取Mobile Service中的資料表。
〉WP8 with Mobile Service:
如果WP8操作Mobile Service則不需像上方WP7這麼辛苦,可以直接透過Mobile Service上下載範例程式,如下圖:
以下透過程式碼來加以說明:
(a) 建立一個Reject物件;
1: public class Reject
2: {
3: //[IgnoreDataMember()]
4: public int id { get; set; }
5: [DataMember(Name = "Icon")]
6: public string Icon { get; set; }
7: [DataMember(Name = "Responser")]
8: public string Responser { get; set; }
9: [DataMember(Name = "DateTime")]
10: public string DateTime { get; set; }
11: [DataMember(Name = "PhoneNumber")]
12: public string PhoneNumber { get; set; }
13: [DataMember(Name = "Message")]
14: public string Message { get; set; }
15:
16: public string TitleData { get { return string.Format("{0}:{1}", Responser, DateTime); } }
17: }
(b) 在WP8中的App.xaml.cs中宣告使用Mobile Service的參數;
1: public partial class App : Application
2: {
3: public static MobileServiceClient MobileService = new MobileServiceClient(
4: "https://wpproject.azure-mobile.net/",
5: "{Application Key}"
6: );
7: }
(c) 透過App.MobileService API來操作Reject物件;
c-1. 取得Reject的物件集合;
1: private MobileServiceCollectionView<Reject> items;
2:
3: private IMobileServiceTable<Reject> todoTable =
4: App.MobileService.GetTable<Reject>();
5:
6: private void RefreshTodoItems()
7: {
8: // 透過App.MobileService取得指定Table Name的所有資料集合
9: items = todoTable.ToCollectionView();
10: ListItems.ItemsSource = items;
11: }
c-2. 新增Reject物件;(由於MobileService API採用Async機制,所以在方法上記得加上async):
1: private async void InsertTodoItem(Reject todoItem)
2: {
3: await todoTable.InsertAsync(todoItem);
4: items.Add(todoItem);
5: }
c-3. 更新Reject物件;(由於MobileService API採用Async機制,所以在方法上記得加上async):
1: private async void UpdateCheckedTodoItem(Reject item)
2: {
3: await todoTable.UpdateAsync(item);
4: items.Remove(item);
5: }
透過Mobile Service API是不是非常方便呢,不用在去管HTTP的操作方式,因為這些內容均被包裝好了,
因此操作上只需管理物件的使用, 搭配GetTable()、InsertAsync()、UpdateAsync()、DeleteAsync()完成資料的操作。
[範例程式]
======
以上是介紹透過WP8與WP7操作Mobile Service的學習筆記,其實WP8裡擁有Azure包裝好的SDK比較方便,
但學習透過WP7以REST API的方式進行交互也是個不錯的練習,希望對大家有所幫助。謝謝。
References:
‧如何透過WP7存取Mobile Services(BETA)
‧Windows Phone 7 Azure Mobile services
‧Using Azure Mobile Services with Windows Phone
‧Windows Phone 7存取Mobile Service問題
‧isdaviddong - 教學影片 (重要)
‧Windows Azure示範教學:建立基本WorkerRole WP7 Push Notification訊息發送
‧http://www.codeproject.com/Articles/585792/Android-and-iOS-Mobile-Device-Development-with-Azu