2018 年 3 月

第 33 卷,第 3 期

本文章是由機器翻譯。

資料點 - 從通用 Windows 平台呼叫 Azure Functions

Julie Lerman

讀取整個 EF 核心 2 和 UWP 應用程式資料序列:

使用 EF 核心 2 和 Azure 函式來儲存 UWP 應用程式資料在本機和全域、第 1 部分
使用 EF 核心 2 和 Azure 函式來儲存 UWP 應用程式資料在本機和全域、第 2 部分
使用 EF 核心 2 和 Azure 函式來儲存 UWP 應用程式資料在本機和全域、第 3 部分
使用 EF 核心 2 和 Azure 函式來儲存 UWP 應用程式資料在本機和全域、第 4 部分

Julie Lerman這是我數列上建置通用 Windows 平台 (UWP) 應用程式,將資料儲存在本機和雲端中的最後一篇。在第一篇,我可以建置 UWP CookieBinge 遊戲中,使用 Entity Framework Core 2 (EF 核心 2) 的遊戲  蝭  儲存到裝置的遊戲分數。在下面兩個機制,我向您說明如何建置雲端中儲存的遊戲的分數,以和從 Microsoft Azure Cosmos DB 資料庫擷取的 Azure 函式。最後,在此欄中,您會看到如何進行從 UWP 應用程式的要求來傳送分數,以及接收和顯示高分播放程式的所有其裝置,以及高分所有播放程式在世界各地那些 Azure 功能。

這個解決方案也可讓使用者在雲端中註冊,並將該註冊其裝置的任何繫結。當我將可以利用該註冊資訊,來傳送及擷取從 Azure 函式的分數時,我將不會描述應用程式的一部分。不過,您可以看到下載,包括建立註冊新的 Azure 函式的程式碼中的程式碼。

我們離開的地方

很少的重新整理程式可協助您 reacquaint UWP 應用程式與我將要連接的 Azure 函式。

在 CookieBinge 遊戲中,當使用者完成 binge,需可從中選擇,告訴他們完成的應用程式的兩個按鈕。其中一個是 「 必要 」 按鈕,指出它們完成時,且會滿意這些 scarfed 向下的所有 cookie 的相關。另一個是 「 不值得 」 按鈕。按一下 [以回應這些事件、 邏輯通往 BingeServices.RecordBinge 方法,用來儲存資料至本機資料庫的 EF 核心 2。

應用程式也會有此功能可顯示前的五個分數,從本機資料庫。

有三個我我最後幾個資料行內建的 Azure 函式。第一個收到的遊戲的分數,以及 (指定註冊功能) 的播放程式的使用者識別碼和裝置已播放的遊戲的名稱。然後,函式會將這項資料儲存到 Cosmos DB 資料庫。從 Cosmos DB 資料庫資料的要求回應其他兩個函式。其中一個接收播放程式的使用者識別碼,並傳回其寄件者的所有裝置玩的前五個分數。其他只會傳回儲存在資料庫中,不論播放程式的前五個分數。

因此,現在該工作是整合遊戲 Azure 函式。首先,在遊戲的分數會儲存到本機資料庫的時間,應用程式應該也傳送分數以及其他相關資料 StoreScore 函式。第二,在應用程式會從本機資料庫讀取分數記錄的時間,它應該也將要求傳送至函式傳回的分數,以及顯示這些要求,結果中所示圖 1

從 Azure Cosmos DB 資料庫分數擷取自 Azure 函式
圖 1 分數,從 Azure Cosmos DB 資料庫擷取自 Azure 函式

與從 UWP Web 通訊

UWP 架構會使用一組特殊的 Api 提出 Web 要求和接收回應。事實上,具有可從中選擇的兩個命名空間,建議您閱讀 MSDN 部落格文章:在 「 demystifying HttpClient 應用程式開發介面中的通用 Windows 平台 」 bit.ly/2rxZu3f。我將使用的 Api,從 windows.web.http 應用程式開發的命名空間。這些應用程式開發介面有非常特定的需求的任何要求,以及傳送資料的方式,也就是說,只要一點點額外的努力。我要傳送我的要求以及一些 JSON 的情況下,我已經運用 HttpJsonContent 會結合 JSON 內容以及標頭內容,並執行某些額外邏輯,協助程式類別。HttpJsonContent 需要 Windows.Data.Json.JsonValue 格式傳送我的 JSON。因此,您會看到我已在此取得這些步驟。或者,我可以上 HttpRequest 中明確設定的標頭內容,然後張貼為字串,使用 StringContent 方法,在所示bit.ly/2BBjFNE

我封裝中所有類別,稱為 CloudService.cs 互動與 Azure 函式的邏輯。

一旦我說,找出使用 UWP 要求方法,以及如何建立 JsonValue 物件的模式,我會建立稱為 CallCookieBingeFunctionAsync 封裝大部分的該邏輯的方法。此方法採用兩個參數: Azure 函式呼叫和 JsonValue 物件的名稱。我也會建立此並不需要 JsonValue 物件參數的方法多載。

以下是該方法的簽章:

private async Task<T> CallCookieBingeFunctionAsync<T>(string apiMethod,
  JsonValue jsonValue)

當有三個不同 Azure 函式需要呼叫,讓我們開始與最簡單 — GetTop5GlobalUserScores。此函式不接受任何參數或其他內容,並傳回結果為 JSON。

CloudService 類別中的 GetTopGlobalScores 方法呼叫傳入函式,我新 CallCookieBingeFunctionAsync 方法,然後傳回 [函式的回應中包含的結果。

public async Task<List<ScoreViewModel>> GetTopGlobalScores()
{
  var results= await CallCookieBingeFunctionAsync<List<ScoreViewModel>>
    ("GetTop5GlobalUserScores");
  return results;
}

請注意,我不傳遞第二個參數的方法。這表示將呼叫的多載建立,不需要 JsonValue:

private async Task<T> CallCookieBingeFunctionAsync<T>(string apiMethod)
{
  return await CallCookieBingeFunctionAsync<T>(apiMethod, null);
}

這會依次呼叫方法的另一個版本,並只傳遞 null 卻 JsonValue。以下是 CallCookieBingeFunctionAsync 方法 (這肯定需要說明) 的完整清單:

private async Task<T> CallCookieBingeFunctionAsync<T>(string apiMethod, JsonValue jsonValue)
{
  var httpClient = new HttpClient();
  var uri = new Uri("https://cookiebinge.azurewebsites.net/api/" + apiMethod);
  var httpContent = jsonValue != null ? new HttpJsonContent(jsonValue): null;
  var cts = new CancellationTokenSource();
  HttpResponseMessage response = await httpClient.PostAsync(uri,
    httpContent).AsTask(cts.Token);  string body = await response.Content.ReadAsStringAsync();
  T deserializedBody = JsonConvert.DeserializeObject<T>(body);
  return deserializedBody;
}

在第一個步驟中,方法會建立 Windows.Web.Http.HttpClient 的執行個體。然後方法會建構從 HttpClient,開頭為所要呼叫的函式的網址提出要求時所需的資訊。所有函式會將開始 https://cookiebinge.azurewebsites.net/api/,我已硬式編碼至方法的值,並再附加函式名稱傳遞至方法。

接下來,我必須定義標頭和傳遞至函式的任何內容。如同稍早所說明,我選擇要使用的 helper 類別,HttpJsonContent,進行此步驟。從 Windows 通用的官方範例 JSON 區段複製這個類別 (bit.ly/2ry7mBP),其中提供我方法來轉換該物件會實作 IHttpContent JsonValue 物件。(您可以看到完整的下載中複製的類別)。 如果沒有 JsonValue 傳遞至方法,在此情況下 GetTop5GlobalUserScores 函式之後,httpContent 變數將會是 null。

在方法中的下一個步驟定義 CancellationTokenSource 變數 cts 中。當我將不會處理取消我的程式碼中時,我想要以確定您已知道此模式,包括了語彙基元,不過。

所有現在建構我片段 — URI、 httpContent CancellationTokenSource,我可以最後對我的 Azure 函式呼叫使用 HttpClient.PostAsync 方法。回應會傳回為 JSON。我的程式碼讀取,並使用 JSON。要序列化回應呼叫的方法所指定的任何物件的網路的 JsonConvert 方法。

如果您查看上一步的程式碼的 GetTopGlobalScores,您會看到我所指定的結果應該清單 < ScoreViewModel >。ScoreViewModel 是要比對的兩個 Azure 函式所傳回的分數資料結構描述建立的類型。類別也有一些額外的屬性的資料會根據我要如何顯示在 UWP 應用程式中該格式。假設 ScoreViewModel 類別的完整清單,我會讓您檢查其下載範例中的程式碼。

呼叫 Azure 函式接受參數

仍有兩個其他的 Azure 函式,來瀏覽。讓我們看現在會傳回分數的資料,另一個。此函式必須傳入,使用者識別碼,而先前的函數所不需的任何輸入。但在此情況下,我是因為,如果您還記得函式,如下所述上個月的發行項,它會預期要當做 URI 的一部分,在傳遞的使用者識別碼值建置 HttpJsonContent 仍不需要。從上個月的文件的簡單範例只會使用字串 54321 做為這個 URI 中的 UserId: https://cookiebinge.azurewebsites.net/api/GetUserScores/54321。加上的應用程式的身分識別管理功能,使用者識別碼將會是 GUID。

我將不會進入深層的程式碼如何管理使用者的身分識別,但以下是 [快速瀏覽。您可以查看這段程式碼的下載中。建立新的一組 Azure 函式的使用者管理。當使用者選擇要向分數追蹤雲端時,這些函式的其中一個建立的新 GUID 的使用者識別碼、 將它儲存在個別的集合,在 CookieBinge Cosmos DB 資料庫和 UWP 應用程式傳回的 GUID。UWP 應用程式接著會使用 EF 核心 2 到本機資料庫中的新資料表中儲存該使用者識別碼。GUID 的一部分顯示給使用者在其帳戶] 頁面中所示圖 1。當使用者播放 CookieBinge 遊戲其他裝置上時,它們可以傳送它們已向另一個 Azure 函式的任何其他裝置上的可用部分 GUID 來取得完整的 GUID。該函數會傳回完整的 GUID 和應用程式將然後儲存該使用者識別碼在目前的裝置上。如此一來,使用者可以張貼分數從任何裝置到雲端,一律使用相同的使用者識別碼。此外,應用程式可以使用該相同的使用者識別碼,從他們的裝置從雲端的所有擷取的分數。AccountService.cs 類別具有使用者識別碼,包括儲存和擷取從本機資料庫使用者識別碼相關的本機互動功能。我隨附此模式我自己,並自行 patted 背面,腦中充滿因此聰明,即使我無法可能有運用現有的架構。

GetUserTopScores 是 CloudServices GetUserScores 函式呼叫中的方法。類似上一個方法,它會呼叫 CallCookieBingeFunctionAsync 方法,一次必須是要 ScoreViewModel 物件清單傳回的型別。我一次傳遞中只單一參數,而不是函式,但應該取得附加至基底 URL 的完整字串的名稱。我使用字串插值函式名稱結合 AccountService.AccountId 屬性的結果:

public async Task<List<ScoreViewModel>> GetUserTopScores()
{
  var results = await CallCookie­Binge­Function­Async<List<ScoreViewModel>>
    ($"GetUserScores\\­{AccountService.AccountId}");
  return results;
}

呼叫 Azure 函式必須要有要求中的 JSON 內容

最後的 Azure 函式,StoreScores,讓我示範如何將 JSON 附加至 HttpRequest 機會。StoreScores 會 JSON 物件,並將其資料儲存到 Cosmos DB 資料庫。圖 2做為如何我測試函式在 Azure 入口網站傳送給依照預期的結構描述的 JSON 物件,以提醒。

JSON 要求主體測試 StoreScores 函式在 Azure 入口網站檢視
圖 2 Azure 入口網站檢視測試的 JSON 要求主體的 StoreScores 函式

要比對該結構描述的 UWP 應用程式中建立名為 StoreScoreDto,幫助我建立 JSON 要求主體的資料傳輸物件 (DTO) 結構。這裡的 CloudService.SendBingeToCloudAsync 方法,其會接受所得遊戲 Binge 資料播放,並將它傳送至 Azure 函式,用來呼叫其他兩個函式的相同 CallCookieBingeFunctionAsync 方法的協助:

public async void SendBingeToCloudAsync(int count, bool worthIt,
  DateTime timeOccurred)
{
  var storeScore = new StoreScoreDto(AccountService.AccountId,
                                     "Julie", AccountService.DeviceName,
                                     timeOccurred, count, worthIt);
  var jsonScore = JsonConvert.SerializeObject(storeScore);
  var jsonValueScore = JsonValue.Parse(jsonScore);
  var results = await CallCookieBingeFunctionAsync<string>("StoreScores",
    jsonValueScore);
}

SendBingeToCloudAsync 先佔據儲存有關 Binge 相關的資料 — 使用 cookie 的計數、 binge 是否是值得和發生的時間。資料和使用 JsonConvert 一次,這次將 StoreScoreDto 序列化為 JSON 物件,然後建立 StoreScoreDto 物件。下一個步驟是建立 JsonValue,如前所述,Windows.Json.Data 命名空間中的一種特殊類型。我該使用 JsonValue.Parse 方法,傳入 jsonScore 所代表的 JSON 物件。產生 JsonValue 是傳送 JSON 物件,以及 HTTP 要求所需的格式。現在,我有格式正確的 JsonValue,我可以傳送給 CallCookeBingeFunctionAsync 方法以及 StoreScores 函式的名稱。請注意,會傳回預期的類型為字串,將會是來自 StoreScores Azure 函式的函式的成功或失敗的通知。

連接至 CloudService UI

就地 CloudService 方法與最後確認 UI 與它們互動。前文提過 Binge 儲存時,在 mainpage.xaml.cs 中的程式碼會呼叫這些方法 BingeService 儲存資料至本機資料庫中。中所顯示的相同方法圖 3,現在也會 binge 資料傳送到 CloudService,將它儲存在雲端透過 StoreScores Azure 函式。

圖 3 現存 RecordBinge 方法現在會傳送 Binge 至雲端

public static  void RecordBinge(int count, bool worthIt)
{
  var binge = new CookieBinge{HowMany = count, WorthIt = worthIt,
                              TimeOccurred = DateTime.Now};
  using (var context = new BingeContext(options))
  {
    context.Binges.Add(binge);
    context.SaveChanges();
  }
  using (var cloudService = new BingeCloudService())
  {
    cloudService.SendBingeToCloudAsync(count, worthIt, binge.TimeOccurred);
  }
}

兩個 Azure 函式與互動的方法會傳回 ScoreViewModel 物件清單。

若要顯示儲存在雲端,因此分數中所示圖 1,我將方法加入 MainWindow.xaml.cs 呼叫 CloudService 方法來擷取分數,然後將它們繫結至頁面上相關的 Listview。我名為 ReloadScores 這個方法,因為它也可以呼叫相同頁面上的 [重新整理] 按鈕:

private async Task ReloadScores()
{
  using (var cloudService = new BingeCloudService())
  {
    YourScoresList.ItemsSource = await cloudService.GetUserTopScores();
    GlobalScoresList.ItemsSource =
      await cloudService.GetTopGlobalScores();
  }
}

然後,UI 會顯示針對每個頁面上的清單定義的範本為基礎的分數資料。例如,圖 4 GlobalScores 顯示在 UI 中會顯示 XAML。

圖 4 XAML 資料繫結從 Azure 的函式傳回的分數資料

<ListView  x:Name="GlobalScoresList"    >
  <ListView.ItemTemplate>
    <DataTemplate >
      <StackPanel Orientation="Horizontal">
        <TextBlock FontSize="24" Text="{Binding score}"
                   VerticalAlignment="Center"/>
        <TextBlock FontSize="16" Text="{Binding displayGlobalScore}"
                   VerticalAlignment="Center" />
      </StackPanel>
    </DataTemplate>
  </ListView.ItemTemplate></ListView>

此四部分的系列的換行

項目開始做為試用 Windows 行動裝置上對我而言,會變成相當 adventure EF 核心 2 的最新版本的練習,並且希望很好玩有趣和教育歷程,以及。使用新.NET 標準 2.0 為基礎的 UWP,尤其是在發行前版本的早期,是肯定一項挑戰這個後端開發人員。但我愛能夠在本機和雲端中的資料儲存和取得新的技能,一路的概念。

數列中的第二個和第三個資料行我了 Azure 函式的第一次經驗而且我很高興複選若要這樣做,因為我現在是這項技術的大型風扇藉口和已完成與它執行更多,因為第一個步驟。我希望您已經同樣啟發 !

如同在本文中,這些函式,從 UWP 應用程式與互動不像是那樣我之前進行 Web 呼叫從其他平台的經驗。我個人了極大滿足,找出工作流程。

如果您查看下載時,您會看到我對應用程式的其他加入 — 所有註冊至雲端儲存體儲存 Azure 產生的使用者識別碼,以及裝置的名稱和註冊其他裝置,然後存取的邏輯StoreScores 和 GetUserScores 方法中使用的使用者識別碼及裝置名稱。我已下載整個 Azure 函式應用程式到.NET 專案,所以您可以查看並與所有支援的應用程式的函式互動。我所花費的時間令人感到困惑透過身分識別流程令人意外數量,並變成稍微 obsessed 娛樂的工作時使用。可能會撰寫了解吧,以及。


Julie LermanMicrosoft 地區主管、 Microsoft MVP、 軟體小組指導,以及位於 Vermont 山區顧問。您可以找到其呈現在資料存取和使用者群組和所做的心得世界各地的其他主題。在她部落格thedatafarm.com/blog和以及 Code First DbContext 版本中的,所有從 O'Reilly Media 是"程式設計 Entity Framework"的作者。在 Twitter 上關注她: @julielerman ,請參閱在她 Pluralsight 課程juliel.me/PS 影片

非常感謝下列技術專家檢閱這篇文章:Ginny Caughey (Carolina 軟體 Inc.)
Ginny Caughey 是總統的 Carolina 軟體,Inc.,提供軟體和服務,整個美國和加拿大的實心廢棄物產業。在她閒暇她也是密碼掛鎖適用於 Windows 和 Windows phone 的作者。她是在 Twitter 上作用中 (@gcaughey) 和 Windows 開發 MVP。


MSDN Magazine 論壇中的這篇文章的討論