共用方式為


開始使用 Azure 雲端服務 (傳統) 和 ASP.NET

概觀

這很重要

截至 2024 年 9 月 1 日,所有客戶的雲端服務 (傳統) 均已淘汰。 從 2024 年 10 月開始,Microsoft 將停止並關閉任何現有的執行中部署,且資料將會永久遺失。 新的部署應該使用新的 Azure Resource Manager 型部署模型 Azure 雲端服務(外延支援)。

本教學課程說明如何使用 ASP.NET 模型-View-Controller (MVC) 前端建立多層式 .NET 應用程式,並將其部署至 Azure 雲端服務。 應用程式會使用 Azure SQL DatabaseAzure Blob 服務和Azure 佇列服務。 您可以從 Microsoft 開發人員網路 (MSDN) 程式代碼庫 下載 Visual Studio 專案

本教學課程將示範如何在本機建置並執行應用程式、如何將應用程式部署至 Azure 並且在雲端執行,以及如何從頭建置應用程式。 之後,如果需要,也可以自從頭建置應用程式開始,然後執行測試和部署步驟。

Contoso Ads 應用程式

此應用程式是廣告看板。 使用者透過輸入文字和上傳影像來建立廣告。 他們可以看到含有縮圖影像的廣告清單,也可以在選取廣告來查看詳細資料時查看完整大小的影像。

影像顯示廣告清單

應用程式會使用 以隊列為中心的工作模式 ,將建立縮圖的CPU密集型工作卸除至後端進程。

替代架構:App Service 和 WebJob

本教學課程示範如何在 Azure 雲端服務中執行前端與後端。 替代方法是在 Azure App Service 中執行前端,並使用 後端的 WebJobs 功能。 如需使用 WebJobs 的教學課程,請參閱 開始使用 Azure WebJobs SDK。 如需如何選擇最符合案例之服務的資訊,請參閱 Azure App Service、雲端服務和虛擬機比較

學習目標

  • 如何安裝 Azure SDK 好讓電腦適合用於進行 Azure 開發。
  • 如何使用 Visual Studio 建立具有 ASP.NET MVC 網頁角色和工作角色的雲端服務專案。
  • 如何使用 Azure 儲存體模擬器在本機測試雲端服務專案。
  • 如何將雲端專案發行至 Azure 雲端服務,並使用 Azure 儲存體帳戶加以測試。
  • 如何上傳檔案並將檔案儲存在 Azure Blob 服務。
  • 如何將 Azure 佇列服務用於層級之間的通訊。

先決條件

本教學課程假設您已經了解 Azure 雲端服務的基本概念 ,例如 Web 角色工作角色 術語。 它也假設您知道如何在 Visual Studio 中使用 ASP.NET MVCWeb Forms 專案。 範例應用程式使用 MVC,但大多數的教學課程內容亦適用於 Web Form。

您不需 Azure 訂用帳戶即可在本機執行應用程式,但需要 Azure 訂用帳戶才能將應用程式部署至雲端。 如果您沒有帳戶,您可以 啟用 MSDN 訂閱者權益註冊免費試用

本教學課程指示適用以下任何產品:

  • Visual Studio 2013
  • Visual Studio 2015
  • Visual Studio 2017
  • Visual Studio 2019

如果您尚未安裝任一個產品,安裝 Azure SDK 時,將為您自動安裝 Visual Studio。

應用程式架構

本應用程式會將廣告儲存在 SQL 資料庫中,使用 Entity Framework Code First 來建立表格和存取資料。 針對每個廣告,資料庫都會儲存兩個 URL:一個用於完整大小的影像,而另一個用於縮圖。

這是廣告資料表的影像

當使用者上傳影像時,在 Web 角色中執行的前端會將影像儲存在 Azure Blob 中,並將廣告資訊儲存在具有指向 Blob 的 URL 資料庫中。 同時會將訊息寫入 Azure 佇列。 在工作角色中執行的後端程式會定期輪詢佇列,以查看是否有新訊息。 當有新訊息出現時,工作者角色會為該影像建立縮圖,並更新該廣告的縮圖 URL 資料庫欄位。 下圖顯示應用程式的這些部分的互動情況。

顯示應用程式元件互動方式的圖表。

設定開發環境

首先,使用 Visual Studio 和 Azure SDK 設定您的開發環境。

  • Visual Studio 2019 包含 Azure SDK。 如果您使用 Visual Studio 2019,不需要額外設定開發環境。

  • 針對 Visual Studio 2015,按一下下列連結以安裝 Azure SDK for Visual Studio 2015

  • 針對 Visual Studio 2013,按一下下列連結以安裝 Azure SDK for Visual Studio 2013

  • 如果您沒有安裝 Visual Studio,請使用下列命令搭配 Azure SDK 安裝 Visual Studio 2019

備註

視您的電腦上已有的 SDK 相依性數目而定,安裝 SDK 可能需要很長的時間 (從數分鐘到半小時以上不等)。

下載並執行已完成的方案

  1. 下載並解壓縮 已完成的解決方案

  2. 啟動 Visual Studio。

  3. 從 [檔案] 功能表中,選擇 [開啟專案],導覽至方案的下載位置,然後開啟方案檔。

  4. 若要建置此方案,請按 CTRL+SHIFT+B。

    根據預設,Visual Studio 會自動還原未包含在 .zip 檔案中的 NuGet 封裝內容。 如果套件未還原,請移至 [管理方案的 NuGet 套件] 對話方塊,然後按一下右上方的 [還原] 按鈕來手動安裝。

  5. [方案總管] 中,確定 已選取 ContosoAdsCloudService 作為啟始專案。

  6. 如果您使用 Visual Studio 2015 或更新版本,變更 ContosoAdsWeb 專案中的 Web.config 檔案和 ContosoAdsCloudService 專案中的 ServiceConfiguration.Local.cscfg 檔案的應用程式中的 SQL Server 連接字串。 在每個案例中,將 "(localdb)\v11.0" 變更為 "(localdb)\MSSQLLocalDB"。

  7. 若要執行應用程式,請按 CTRL+F5。

    在本機執行雲端服務專案時,Visual Studio 會自動叫用 Azure「計算模擬器」和 Azure「儲存體模擬器」。 計算模擬器會利用您電腦的資源來模擬網頁角色和工人角色的環境。 記憶體模擬器會使用 SQL Server Express LocalDB 資料庫來模擬 Azure 雲端記憶體。

    第一次執行雲端服務專案時,需要約一分鐘的時間,才能啟動模擬器。 模擬器啟動完成時,預設的瀏覽器會開啟到應用程式首頁。

    Contoso Ads 架構 1

  8. 選取 [建立廣告]。

  9. 輸入部分測試資料,選取要上傳的 .jpg 影像,然後選取 [建立]

    顯示建立頁面的影像

    應用程式會進入 [索引] 頁面,但不會顯示新廣告的縮圖,因為系統尚未進行該處理。

  10. 稍等一下,然後重新整理索引頁面以查看縮圖。

    索引頁面

  11. 選取廣告的 [詳細資料] 以查看完整大小的影像。

    詳細數據頁面

您剛剛完全是在本機電腦上執行應用程式,並未連線至雲端。 儲存體模擬器會將佇列和 Blob 資料儲存在 SQL Server Express LocalDB 資料庫,而應用程式會將廣告資料儲存在另一個 LocalDB 資料庫。 Entity Framework Code First 會在 Web 應用程式第一次嘗試存取時自動建立廣告資料庫。

在下一節中,您會將方案設定為在雲端中執行時,將 Azure 雲端資源用於佇列、Blob 和應用程式資料庫。 如果您想繼續在本機執行,但使用雲端儲存和資料庫資源,也可以這樣做。 這只是設定連接字串的問題而已,您會看到作法。

將應用程式部署至 Azure

您會執行下列步驟,以在雲端中執行應用程式:

  • 建立 Azure 雲端服務。
  • 在 Azure SQL Database 中建立資料庫。
  • 建立 Azure 儲存體帳戶。
  • 將解決方案設定為在 Azure 中執行時使用您的資料庫。
  • 將解決方案設定為在 Azure 中執行時使用 Azure 儲存體帳戶。
  • 將專案部署至 Azure 雲端服務。

建立 Azure 雲端服務

Azure 雲端服務是應用程式執行所在的環境。

  1. 在您的瀏覽器中,開啟 Azure 入口網站

  2. 選取 建立資源 計算 雲端服務

  3. 在 [網域名稱系統 (DNS) 名稱] 輸入方塊中,輸入雲端服務的 URL 前置詞。

    URL 必須是唯一的。 如果您選擇的前置詞已在使用中,您會收到錯誤訊息。

  4. 為該服務指定新的資源群組。 選取 [新建],然後在 [資源群組] 輸入方塊中輸入名稱,例如 CS_contososadsRG。

  5. 選擇您要部署應用程式的區域。

    此欄位會指定您的雲端服務託管所在的資料中心。 針對生產應用程式,您應該選擇距離客戶最近的區域。 針對此教學課程,請選擇離您最近的區域。

  6. 選取 建立

    在下圖中,已建立一個 URL 為 CSvccontosoads.cloudapp.net 的雲端服務。

    影像顯示新的雲端服務

在 Azure SQL Database 中建立資料庫

應用程式在雲端中執行時會使用雲端式資料庫。

  1. Azure 入口網站中,選取 [建立資源 > 資料庫 > SQL Database]。

  2. 在 [ 資料庫名稱] 方塊中,輸入 contosoads

  3. 在 [資源群組] 中,選擇 [使用現有的] 並選取用於雲端服務的資源群組。

  4. 在下面的影像中,選取 [伺服器 - 進行必要設定] 和 [建立新伺服器]

    隧道連接至資料庫伺服器

    或者,如果您的訂用帳戶已有伺服器,您可以從下拉式清單選取該伺服器。

  5. 在 [伺服器名稱] 方塊中,輸入 csvccontosodbserver

  6. 輸入系統管理員的 [登入名稱] 和 [密碼]

    如果您選取了 [建立新伺服器],則不要在此輸入現有的名稱和密碼。 您正在輸入一個新的名稱和密碼,這是您現在設置的,以便在將來存取資料庫時使用。 如果選取先前建立的伺服器,入口網站會提示您提供先前建立之系統管理使用者帳戶的密碼。

  7. 選擇您為雲端服務選擇的相同 位置

    當雲端服務與資料庫位於不同的資料中心 (不同的區域) 時,延遲時間會增加,而且您將由於使用資料中心外的頻寬而產生費用。 資料中心內的頻寬則是免費的。

  8. 勾選 [允許 Azure 服務存取伺服器]

  9. 針對新伺服器選取 [選取]

    新伺服器

  10. 選擇 [建立] 。

建立 Azure 儲存體帳戶

Azure 儲存體帳戶可提供在雲端中儲存佇列和 Blob 資料的資源。

在真實世界應用程式中,您一般會為應用程式資料與記錄資料建立不同的帳戶,以及為測試資料與生產資料建立不同的帳戶。 在本教學課程中,您只會使用一個帳戶。

  1. Azure 入口網站中,選取 [建立資源 > 儲存體 > 儲存帳戶 - Blob、檔案、資料表、佇列]。

  2. 在 [名稱] 方塊中,輸入 URL 前置詞。

    此前置詞與您在方塊下面看到的文字組成儲存帳戶的唯一網址。 如果您輸入的前置詞已有人使用,請選擇不同的前置詞。

  3. 將 [部署模型] 設定為 [傳統]

  4. 將「複寫」下拉式清單設定為「本機備援儲存體」

    當為儲存體帳戶啟用地理複寫時,儲存的內容會複製到次要資料中心,以便在主要位置發生重大災害時能夠進行容錯移轉。 地理複寫會引發額外成本。 對於測試和開發帳戶,您通常不會想要付費使用地理區域複寫功能。 如需詳細資訊,請參閱 建立、管理或刪除記憶體帳戶

  5. 在 [資源群組] 中,選取 [使用現有的] 並選取用於雲端服務的資源群組。

  6. 將 [位置] 下拉式清單設為與您為雲端服務所選的相同區域。

    當雲端服務與儲存體帳戶位於不同的資料中心 (不同的區域) 時,延遲時間會增加,而且您將由於使用資料中心外的頻寬而產生費用。 資料中心內的頻寬則是免費的。

    Azure 同質群組提供一種機制,可將資料中心內的資源之間的距離縮至最短,因而可以減少延遲時間。 本教學課程不會使用同質群組。 如需詳細資訊,請參閱 如何在 Azure 中建立同質群組

  7. 選擇 [建立] 。

    新的記憶體帳戶

    在圖像中,已建立一個 URL 為csvccontosoads.core.windows.net的儲存體帳戶。

將方案配置為在 Azure 上執行時使用 Azure SQL Database 的資料庫

每個網站專案和背景工作角色專案都有自己獨立的資料庫連接字串,當應用程式在 Azure 上執行時,這些字串都必須指向 Azure SQL Database 中的資料庫。

您可以使用 web 角色 的Web.config 轉換 ,以及背景工作角色的雲端服務環境設定。

備註

在本節與下一節中,您將把認證儲存在專案檔中。 請勿將敏感數據儲存在公用原始程式碼存放庫中

  1. 在 ContosoAdsWeb 專案中,開啟應用程式 Web.config 檔案 Web.Release.config轉換檔、刪除包含 <connectionStrings> 元素的批注區塊,然後將下列程式代碼貼到其位置。

    <connectionStrings>
        <add name="ContosoAdsContext" connectionString="{connectionstring}"
        providerName="System.Data.SqlClient" xdt:Transform="SetAttributes" xdt:Locator="Match(name)"/>
    </connectionStrings>
    

    將檔案保持開啟以供編輯。

  2. Azure 入口網站中,選擇左窗格中的 [SQL Database ],選取您為此教學課程建立的資料庫,然後選取 [ 顯示連接字串]。

    顯示連接字串

    入口網站會顯示連接字串,並設有密碼占位符。

    連接字串

  3. Web.Release.config 轉換檔案中,刪除 {connectionstring} 並從 Azure 入口網站複製並貼上 ADO.NET 連接字串。

  4. 在您貼入 Web.Release.config 轉換檔案的連接字串中,將 {your_password_here} 取代為您為新 SQL 資料庫建立的密碼。

  5. 儲存檔案。

  6. 選取並複製連接字串(不包含其周圍的引號),以用於接下來的設定 worker role 專案的步驟。

  7. [方案總管]中 [角色]下的雲端服務專案,以滑鼠右鍵點擊 [ContosoAdsWorker],然後選取 [屬性]

    醒目提示 [屬性] 選單選項的螢幕快照。

  8. 選擇 [設定] 索引標籤。

  9. 將 [服務組態] 變更為 [雲端]

  10. 針對設定選取ContosoAdsDbConnectionString[值]欄位,然後將您從教學課程前一節複製的連接字串貼上。

    背景工作角色的資料庫連接字串

  11. 儲存您的變更。

在 Azure 中執行時,將解決方案設定為使用您的 Azure 儲存體帳戶

Web 角色專案和背景工作角色專案的 Azure 儲存體帳戶連接字串會儲存在雲端服務專案的環境設定中。 當應用程式在本機和在雲端執行時,每個專案都有要使用的一組個別設定。 您更新 Web 和工作角色專案的雲端環境設定。

  1. [ContosoAdsCloudService] 專案中 [角色] 下的 [ContosoAdsWeb] 上按滑鼠右鍵,然後選取 [屬性]

    影像顯示角色屬性

  2. 選擇 [設定] 索引標籤。在 [服務組態] 下拉式方塊中,選取 [雲端]

    雲端設定

  3. 選取 StorageConnectionString 專案,您會在行右端看到省略號 (...) 按鈕。 選擇省略符號按鈕,開啟 [建立儲存體連接字串] 對話方塊。

    開啟 [連接字串建立] 方塊

  4. 在 [建立儲存體帳戶連接字串] 對話方塊中,選取 [您的訂用帳戶]、選擇您稍早建立的儲存體帳戶,然後選取 [確定]。 如果您尚未登入,資源管理器會提示您輸入您的 Azure 帳戶認證。

    建立記憶體連接字串

  5. 儲存您的變更。

  6. 依照您針對 StorageConnectionString 連接字串執行的程序,設定 Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString 連接字串。

    此連接字串用於記錄。

  7. 請遵循您用於 ContosoAdsWeb 角色的相同程式,為 ContosoAdsWorker 角色設定這兩個連接字串。 請記得將 [服務組態] 設為 [雲端]

您使用 Visual Studio UI 所設定的角色環境設定會儲存在 ContosoAdsCloudService 專案的下列檔案中:

  • ServiceDefinition.csdef - 定義設定名稱。
  • ServiceConfiguration.Cloud.cscfg - 提供應用程式在雲端中執行時的值。
  • ServiceConfiguration.Local.cscfg - 提供應用程式在本機執行時的值。

例如,ServiceDefinition.csdef 包括下列定義:

<ConfigurationSettings>
    <Setting name="StorageConnectionString" />
    <Setting name="ContosoAdsDbConnectionString" />
</ConfigurationSettings>

ServiceConfiguration.Cloud.cscfg 檔案包含您在 Visual Studio 中針對這些設定輸入的值。

<Role name="ContosoAdsWorker">
    <Instances count="1" />
    <ConfigurationSettings>
        <Setting name="StorageConnectionString" value="{yourconnectionstring}" />
        <Setting name="ContosoAdsDbConnectionString" value="{yourconnectionstring}" />
        <!-- other settings not shown -->

    </ConfigurationSettings>
    <!-- other settings not shown -->

</Role>

<Instances> 設定會指定 Azure 會在其上執行背景工作角色程式碼的虛擬機器數目。 後續步驟一節包含有關擴展雲端服務的更多資訊連結。

將專案部署至 Azure

  1. [方案總管] 中,以滑鼠右鍵按兩下 ContosoAdsCloudService 雲端專案,然後選取 [ 發佈]。

    發佈選單

  2. 在 [發佈 Azure 應用程式] 精靈的 [登入] 步驟中,選取 [下一步]

    登入步驟

  3. 在精靈的 [設定] 步驟中,選取 [下一步]

    設定步驟

    [ 進階 ] 索引標籤中的預設設定適用於本教學課程。 如需進階索引標籤的相關信息,請參閱 發佈 Azure 應用程式精靈

  4. 在 [摘要] 步驟中,選取 [發佈]

    摘要步驟

    Azure 活動記錄視窗會在 Visual Studio 中開啟。

  5. 選擇向右箭頭圖示以展開部署詳細資料。

    完成部署最多可能需要大約 5 分鐘或更久的時間。

    Azure 活動記錄視窗

  6. 當部署狀態為完成時,選取 [Web 應用程式 URL] 來啟動應用程式。

  7. 您可以透過建立、檢視和編輯一些廣告來測試應用程式,正如同您在本機執行應用程式一般。

備註

完成測試後,請刪除或停止雲端服務。 即使您未使用雲端服務,因為已為其保留虛擬機器資源,因此仍會累積費用。 如果您讓它保持執行,找到您 URL 的任何人都可以建立和檢視廣告。 在 Azure 入口網站中,移至雲端服務的 [概 ] 索引標籤,然後按兩下頁面頂端的 [ 刪除] 按鈕。 如果您只想暫時避免他們存取網站,請改為按一下 [停止]。 在那種情況下,費用將持續累積。 當您不再需要 SQL 資料庫和儲存體帳戶時,可以遵循類似程序來加以刪除。

從頭開始建立應用程式

如果您仍然需要下載 已完成的應用程式,請立即執行。 將檔案從所下載的專案複製到新專案。

建立 Contoso Ads 應用程式包含下列步驟:

  • 建立雲端服務 Visual Studio 方案。
  • 更新和新增 NuGet 套件。
  • 設定專案參考。
  • 設定連接字串。
  • 加入程式碼檔案。

建立方案後,您會檢閱專屬於雲端服務專案和 Azure Blob 及佇列的程式碼。

建立雲端服務 Visual Studio 方案

  1. 在 Visual Studio 中,從 [檔案] 選單選擇 [新增專案]。

  2. 在 [新增專案] 對話方塊的左窗格中,展開 [Visual C#],選擇 [雲端] 範本,然後選擇 [Azure 雲端服務] 範本。

  3. 將專案和方案命名為 ContosoAdsCloudService,然後選取 [確定]

    新增專案

  4. 在 [新增 Azure 雲端服務] 對話方塊中,新增 Web 角色和背景工作角色。 將網頁角色命名為 ContosoAdsWeb,並將工作角色命名為 ContosoAdsWorker。 (使用右窗格中的鉛筆圖示來變更角色的預設名稱。)

    新增雲端服務專案

  5. 看見 Web 角色的 [新增 ASP.NET 專案] 對話方塊時,選取 MVC 範本,然後選取 [變更驗證]

    變更驗證

  6. 在 [變更驗證] 對話方塊中,選擇 [不需要驗證],然後選取 [確定]

    無驗證

  7. 在 [新增 ASP.NET 專案] 對話方塊中,選取 [確定]

  8. 在 [方案總管] 中,於方案 (不是其中一個專案) 上按一下滑鼠右鍵,並選擇 [新增 - 新專案]

  9. 在 [新增專案] 對話方塊中,於左窗格的 [Visual C#] 下選擇 [Windows],然後選取 [類別庫] 範本。

  10. 將專案命名為 ContosoAdsCommon,然後選取 [ 確定]。

    您需要從網頁和工作者角色專案中參考 Entity Framework 架構和資料模型。 作為替代方式,您可以在 Web 角色專案中定義與 EF 相關的類別,並從背景工作角色專案引用此專案。 但在替代方法中,您的工作角色專案會包含不需要的 Web 組件參考。

更新和新增 NuGet 套件

  1. 開啟方案的 [管理 NuGet 套件 ] 對話框。

  2. 在視窗頂端,選取 [更新]

  3. 尋找 WindowsAzure.Storage 套件,如果它位於清單中,請選取它,然後選取 Web 和背景工作專案以更新它,然後選取 [ 更新]。

    儲存體用戶端程式庫的更新頻率高於 Visual Studio 專案範本的更新頻率,因此,您可能會發現您需要更新新建專案中的版本。

  4. 在視窗頂端,選取 [瀏覽]

  5. 尋找 EntityFramework NuGet 套件,並將它安裝在這三個專案中。

  6. 尋找 Microsoft.WindowsAzure.ConfigurationManager NuGet 套件,並將其安裝在工作角色的專案中。

設定專案參考

  1. 在 ContosoAdsWeb 專案中,設定 ContosoAdsCommon 專案的參考。 以滑鼠右鍵按一下 ContosoAdsWeb 專案,然後選取 [參考] - [新增參考]。 在 [參考管理員] 對話方塊中,於左側窗格選取 [方案 - 專案],選取 [ContosoAdsCommon],然後選取 [確定]

  2. 在 ContosoAdsWorker 專案中,設定對 ContosoAdsCommon 專案的參考設定。

    ContosoAdsCommon 會包含前端與後端都會使用的 Entity Framework 資料模型和內容類別。

  3. 在 ContosoAdsWorker 專案中,設置 System.Drawing 的參照。

    此組件是由後端用來將影像轉換為縮圖。

設定連接字串

在本節中,您將針對本機測試用途來設定 Azure 儲存體和 SQL 連接字串。 本教學課程中稍早的部署指示,說明如何針對應用程式在雲端中執行而設定連接字串。

  1. 在 ContosoAdsWeb 專案中,開啟應用程式的 Web.config 檔案,在 connectionStrings 元素後方插入下列configSections 元素。

    <connectionStrings>
        <add name="ContosoAdsContext" connectionString="Data Source=(localdb)\v11.0; Initial Catalog=ContosoAds; Integrated Security=True; MultipleActiveResultSets=True;" providerName="System.Data.SqlClient" />
    </connectionStrings>
    

    如果您使用 Visual Studio 2015 或更新版本,將 "v11.0" 取代為 "MSSQLLocalDB"。

  2. 儲存您的變更。

  3. 在 ContosoAdsCloudService 專案中,於 [角色] 下的 ContosoAdsWeb 上按一下滑鼠右鍵,然後選取 [屬性]

    角色屬性影像

  4. [ContosoAdsWeb [角色] 屬性視窗中,選取 [ 設定 ] 索引卷標,然後選取 [ 新增設定]。

    將 [服務組態] 保持設為 [所有組態]

  5. 新增名為 StorageConnectionString 的設定。 將 [類型] 設定為 ConnectionString,並將 [值 ] 設定為 UseDevelopmentStorage=true

    新的連接字串

  6. 儲存您的變更。

  7. 遵循相同程序,在 ContosoAdsWorker 角色屬性中加入儲存體連接字串。

  8. 在仍停留於 ContosoAdsWorker [Role] 屬性視窗時,請再新增一個連接字串:

    • 名稱:ContosoAdsDbConnectionString

    • 類型:字串

    • 值:貼上用於 Web 角色專案的相同連接字串。 (下列範例適用於 Visual Studio 2013。如果您複製此範例且您是使用 Visual Studio 2015 或更新版本,請記得變更資料來源。)

      Data Source=(localdb)\v11.0; Initial Catalog=ContosoAds; Integrated Security=True; MultipleActiveResultSets=True;
      

新增程式碼檔案

在本節中,您會將檔案從所下載的方案複製到新方案。 下一節會示範和說明此程式碼的重要部分。

若要新增檔案到專案或資料夾,請以滑鼠右鍵按一下專案或資料夾,然後選取 [新增] - [現有項目]。 選取您想要的檔案,然後選取 [新增]。 如果詢問您是否要取代現有的檔案,請選取 [是]

  1. 在 ContosoAdsCommon 專案中,刪除 Class1.cs 檔案,然後從下載的專案新增 Ad.csContosoAdscontext.cs 檔案的位置。

  2. 在 ContosoAdsWeb 專案中,從所下載的專案加入下列檔案。

    • Global.asax.cs
    • 在 Views\Shared 資料夾中:_Layout.cshtml
    • 在 Views\Home 資料夾中:Index.cshtml
    • Controllers 資料夾中: AdController.cs
    • 在 Views\Ad 資料夾中 (請先建立此資料夾):五個 .cshtml 檔案。
  3. 在 ContosoAdsWorker 專案中,從下載的專案新增 WorkerRole.cs

您現在可以如本教學課程中稍早所指示般建置並執行應用程式,而應用程式會使用本機資料庫和儲存體模擬器資源。

以下小節說明與使用 Azure 環境、Blob 和佇列相關的程式碼。 本教學檔案未說明如何使用 Scaffolding 建立 MVC 控制器和檢視、如何編寫能與 SQL Server 資料庫搭配使用的 Entity Framework 程式碼,或 ASP.NET 4.5 中非同步程式設計的基本概念。 如需這些主題的相關資訊,請參閱下列資源:

ContosoAdsCommon - Ad.cs

Ad.cs 檔案可定義廣告類別列舉,以及廣告資訊的 POCO 實體類別。

public enum Category
{
    Cars,
    [Display(Name="Real Estate")]
    RealEstate,
    [Display(Name = "Free Stuff")]
    FreeStuff
}

public class Ad
{
    public int AdId { get; set; }

    [StringLength(100)]
    public string Title { get; set; }

    public int Price { get; set; }

    [StringLength(1000)]
    [DataType(DataType.MultilineText)]
    public string Description { get; set; }

    [StringLength(1000)]
    [DisplayName("Full-size Image")]
    public string ImageURL { get; set; }

    [StringLength(1000)]
    [DisplayName("Thumbnail")]
    public string ThumbnailURL { get; set; }

    [DataType(DataType.Date)]
    [DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
    public DateTime PostedDate { get; set; }

    public Category? Category { get; set; }
    [StringLength(12)]
    public string Phone { get; set; }
}

ContosoAdsCommon - ContosoAdsContext.cs

ContosoAdsContext 類別可指定廣告類別用於 DbSet 集合,Entity Framework 會儲存在 SQL 資料庫中。

public class ContosoAdsContext : DbContext
{
    public ContosoAdsContext() : base("name=ContosoAdsContext")
    {
    }
    public ContosoAdsContext(string connString)
        : base(connString)
    {
    }
    public System.Data.Entity.DbSet<Ad> Ads { get; set; }
}

這個類別有兩個建構函式。 第一個是由 Web 專案所使用,指定儲存在 Web.config 檔案的連接字串名稱。 第二個建構函式可讓您傳入背景工作角色專案使用的實際連接字串,因為它沒有 Web.config 檔案。 您稍早已看到此連接字串儲存所在的地方。 稍後,您會看到程式碼在具現化 DbContext 類別時,如何擷取此連接字串。

ContosoAdsWeb - Global.asax.cs

Application_Start 方法呼叫的程式碼會建立 images Blob 容器和 images 佇列 (如果尚不存在)。 此程式碼可確保每當您使用新的儲存體帳戶或在新電腦上使用儲存體模擬器時,其便會自動建立所需的 Blob 容器和佇列。

程序代碼會使用 .cscfg 檔案中的記憶體連接字串來存取記憶體帳戶。

var storageAccount = CloudStorageAccount.Parse
    (RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString"));

然後,它會取得 映像 Blob 容器的參考、如果容器不存在,則會建立容器,並在新的容器上設定訪問許可權。 依預設,新的容器只能允許具有儲存體帳戶認證的用戶端存取 Blob。 網站需要 Blob 處於公用狀態,以便能使用指向影像 Blob 的 URL 來顯示影像。

var blobClient = storageAccount.CreateCloudBlobClient();
var imagesBlobContainer = blobClient.GetContainerReference("images");
if (imagesBlobContainer.CreateIfNotExists())
{
    imagesBlobContainer.SetPermissions(
        new BlobContainerPermissions
        {
            PublicAccess =BlobContainerPublicAccessType.Blob
        });
}

類似的程式代碼會取得 圖像 佇列的參考,並建立新的佇列。 在此情況下,即不需要變更權限。

CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
var imagesQueue = queueClient.GetQueueReference("images");
imagesQueue.CreateIfNotExists();

ContosoAdsWeb - _Layout.cshtml

_Layout.cshtml 檔案會在頁首和頁尾中設定應用程式名稱,並建立 「廣告」功能表項。

ContosoAdsWeb - Views\Home\Index.cshtml

Views\Home\Index.cshtml 檔案在首頁上顯示類別連結。 連結會將查詢字串變數中 Category 列舉的整數值傳遞至 [廣告索引] 頁面。

<li>@Html.ActionLink("Cars", "Index", "Ad", new { category = (int)Category.Cars }, null)</li>
<li>@Html.ActionLink("Real estate", "Index", "Ad", new { category = (int)Category.RealEstate }, null)</li>
<li>@Html.ActionLink("Free stuff", "Index", "Ad", new { category = (int)Category.FreeStuff }, null)</li>
<li>@Html.ActionLink("All", "Index", "Ad", null, null)</li>

ContosoAdsWeb - AdController.cs

在 AdController.cs 檔案中,建構函式會呼叫 InitializeStorage 方法來建立 Azure 儲存體用戶端程式庫物件,該物件可提供用於處理 Blob 和佇列的 API。

然後程式碼會取得 圖像 Blob 容器的參考,如同您稍早在 Global.asax.cs 中所見。 這麼做會設定適用於 Web 應用程式的預設 重試原則 。 預設的指數退避重試原則,可能會因對暫時性錯誤進行反覆重試,而導致 Web 應用程式停止回應超過一分鐘。 此處指定的重試原則會在每次嘗試後等候 3 秒,最多嘗試 3 次。

var blobClient = storageAccount.CreateCloudBlobClient();
blobClient.DefaultRequestOptions.RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3);
imagesBlobContainer = blobClient.GetContainerReference("images");

類似的程式代碼會取得 影像 佇列的參考。

CloudQueueClient queueClient = storageAccount.CreateCloudQueueClient();
queueClient.DefaultRequestOptions.RetryPolicy = new LinearRetry(TimeSpan.FromSeconds(3), 3);
imagesQueue = queueClient.GetQueueReference("images");

多數的控制器程式碼通常用於使用 DbContext 類別來處理 Entity Framework 資料模型。 例外狀況為 HttpPost Create 方法,它會上傳檔案,並將檔案儲存在 Blob 儲存體。 模型系結器會將 HttpPostedFileBase 物件提供給 方法。

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<ActionResult> Create(
    [Bind(Include = "Title,Price,Description,Category,Phone")] Ad ad,
    HttpPostedFileBase imageFile)

如果使用者選取要上傳的檔案,程式碼會上傳檔案、將檔案儲存在 Blob,並以指向 Blob 的 URL 更新廣告資料庫記錄。

if (imageFile != null && imageFile.ContentLength != 0)
{
    blob = await UploadAndSaveBlobAsync(imageFile);
    ad.ImageURL = blob.Uri.ToString();
}

執行上傳的程式碼位於 UploadAndSaveBlobAsync 方法。 它會為 Blob 建立 GUID 名稱、上傳並儲存檔案,然後傳回參考至儲存的 Blob。

private async Task<CloudBlockBlob> UploadAndSaveBlobAsync(HttpPostedFileBase imageFile)
{
    string blobName = Guid.NewGuid().ToString() + Path.GetExtension(imageFile.FileName);
    CloudBlockBlob imageBlob = imagesBlobContainer.GetBlockBlobReference(blobName);
    using (var fileStream = imageFile.InputStream)
    {
        await imageBlob.UploadFromStreamAsync(fileStream);
    }
    return imageBlob;
}

HttpPost Create 方法上傳 Blob 並更新資料庫後,它會建立佇列訊息通知後端程序,有一個影像已準備好轉換成縮圖。

string queueMessageString = ad.AdId.ToString();
var queueMessage = new CloudQueueMessage(queueMessageString);
await queue.AddMessageAsync(queueMessage);

HttpPost Edit 方法的程式碼也是類似的,不同的是如果使用者選取新的影像檔案,就必須刪除現有的所有 Blob。

if (imageFile != null && imageFile.ContentLength != 0)
{
    await DeleteAdBlobsAsync(ad);
    imageBlob = await UploadAndSaveBlobAsync(imageFile);
    ad.ImageURL = imageBlob.Uri.ToString();
}

下一個範例顯示當您刪除廣告時會刪除 Blob 的程式碼:

private async Task DeleteAdBlobsAsync(Ad ad)
{
    if (!string.IsNullOrWhiteSpace(ad.ImageURL))
    {
        Uri blobUri = new Uri(ad.ImageURL);
        await DeleteAdBlobAsync(blobUri);
    }
    if (!string.IsNullOrWhiteSpace(ad.ThumbnailURL))
    {
        Uri blobUri = new Uri(ad.ThumbnailURL);
        await DeleteAdBlobAsync(blobUri);
    }
}
private static async Task DeleteAdBlobAsync(Uri blobUri)
{
    string blobName = blobUri.Segments[blobUri.Segments.Length - 1];
    CloudBlockBlob blobToDelete = imagesBlobContainer.GetBlockBlobReference(blobName);
    await blobToDelete.DeleteAsync();
}

ContosoAdsWeb - Views\Ad\Index.cshtml 和 Details.cshtml

Index.cshtml 檔案會顯示其他廣告數據的縮圖。

<img src="@Html.Raw(item.ThumbnailURL)" />

Details.cshtml 檔案會顯示完整大小的影像。

<img src="@Html.Raw(Model.ImageURL)" />

ContosoAdsWeb - Views\Ad\Create.cshtml 和 Edit.cshtml

Create.cshtml 和 Edit.cshtml 檔案可指定表單編碼,供控制器取得 HttpPostedFileBase 物件。

@using (Html.BeginForm("Create", "Ad", FormMethod.Post, new { enctype = "multipart/form-data" }))

<input> 元素告知瀏覽器提供檔案選取對話方塊。

<input type="file" name="imageFile" accept="image/*" class="form-control fileupload" />

ContosoAdsWorker - WorkerRole.cs - OnStart 方法

Azure 背景工作角色環境會在背景工作角色開始時呼叫 OnStart 類別中的 WorkerRole 方法,並且會在 Run 方法執行結束時呼叫 OnStart 方法。

方法 OnStart 會從 .cscfg 檔案取得資料庫連接字串,並將它傳遞給 Entity Framework DbContext 類別。 預設會使用 SQLClient 提供者,使得您不需指定提供者。

var dbConnString = CloudConfigurationManager.GetSetting("ContosoAdsDbConnectionString");
db = new ContosoAdsContext(dbConnString);

之後,方法會取得儲存體帳戶的參考,並建立 Blob 容器和佇列 (如果尚不存在)。 該動作的程式碼與 Web 角色 Application_Start 方法中的程式碼類似。

ContosoAdsWorker - WorkerRole.cs - Run 方法

Run 方法完成其初始化工作時,系統會呼叫OnStart 方法。 此方法會執行無限迴圈,監看是否有新的佇列訊息,並在訊息抵達時加以處理。

public override void Run()
{
    CloudQueueMessage msg = null;

    while (true)
    {
        try
        {
            msg = this.imagesQueue.GetMessage();
            if (msg != null)
            {
                ProcessQueueMessage(msg);
            }
            else
            {
                System.Threading.Thread.Sleep(1000);
            }
        }
        catch (StorageException e)
        {
            if (msg != null && msg.DequeueCount > 5)
            {
                this.imagesQueue.DeleteMessage(msg);
            }
            System.Threading.Thread.Sleep(5000);
        }
    }
}

在每次迴圈的反覆運算之後,如果沒有找到佇列訊息,程式會休息一秒。 暫停可避免工作角色過多地消耗 CPU 時間和產生儲存體交易成本。 Microsoft 客戶諮詢小組曾經遇過一個案例是,開發人員忘記納入此睡眠功能便部署到生產環境,之後便離開去度假。 當他們回到工作崗位時,因為疏忽所造成的代價比度假的開銷還高。

有時佇列訊息的內容會造成處理錯誤。 這種訊息稱為「有害訊息」。 如果您只是記錄錯誤並重新啟動迴圈,可能會不斷的嘗試處理該訊息。 因此,Catch 區塊中包含一個 if 陳述式,用來檢查應用程式嘗試處理當前訊息的次數。 如果此計數高過五次,則會從佇列中刪除訊息。

ProcessQueueMessage 在找到佇列訊息時被呼叫。

private void ProcessQueueMessage(CloudQueueMessage msg)
{
    var adId = int.Parse(msg.AsString);
    Ad ad = db.Ads.Find(adId);
    if (ad == null)
    {
        throw new Exception(String.Format("AdId {0} not found, can't create thumbnail", adId.ToString()));
    }

    CloudBlockBlob inputBlob = this.imagesBlobContainer.GetBlockBlobReference(ad.ImageURL);

    string thumbnailName = Path.GetFileNameWithoutExtension(inputBlob.Name) + "thumb.jpg";
    CloudBlockBlob outputBlob = this.imagesBlobContainer.GetBlockBlobReference(thumbnailName);

    using (Stream input = inputBlob.OpenRead())
    using (Stream output = outputBlob.OpenWrite())
    {
        ConvertImageToThumbnailJPG(input, output);
        outputBlob.Properties.ContentType = "image/jpeg";
    }

    ad.ThumbnailURL = outputBlob.Uri.ToString();
    db.SaveChanges();

    this.imagesQueue.DeleteMessage(msg);
}

此程式碼會讀取資料庫以取得影像 URL、將影像轉換為縮圖、將縮圖儲存在 Blob 中,以縮圖 Blob URL 更新資料庫,並刪除佇列訊息。

備註

為求簡化,ConvertImageToThumbnailJPG 方法中的程式碼會使用 SSystem.Drawing namespace 中的類別。 不過,此命名空間中類別的設計原意是要與 Windows Form 搭配使用。 不支援將它們用於 Windows 或 ASP.NET 服務。 如需影像處理選項的詳細資訊,請參閱 動態映像產生深入影像大小調整

故障排除

當您遵循本教學中的指示進行操作時,若有任何問題或故障,以下是一些常見的錯誤及其解決方法。

ServiceRuntime.RoleEnvironmentException

當您在 Azure 中執行應用程式,或使用 Azure 計算模擬器在本機執行應用程式時,Azure 會提供 RoleEnvironment 物件。 如果您在本機執行時遇到此錯誤,請確定您有將 ContosoAdsCloudService 專案設為啟動專案。 此設定會讓專案使用 Azure 計算模擬器來執行。

應用程式使用 Azure RoleEnvironment 的其中一件事是取得儲存在 .cscfg 檔案中的連接字串值,因此此例外狀況的另一個原因是缺少連接字元串。 請確定您在 ContosoAdsWeb 專案中同時為雲端和本機組態建立 StorageConnectionString 設定,也在 ContosoAdsWorker 專案中為這兩個組態建立連接字串。 如果您在整個解決方案中搜尋 StorageConnectionString,您應該會在六個檔案中看到它九次。

無法覆寫連接埠 xxx。 新的連接埠值低於通訊協定 http 允許的最小值 8080。

請嘗試變更 Web 專案使用的連接埠號碼。 以滑鼠右鍵按一下 ContosoAdsWeb 專案,然後選取 [屬性]。 選擇 [Web] 索引標籤,然後變更 [專案 URI] 設定中的連接埠號碼。

如需可能解決問題的另一個替代方法,請參閱下一節。

在本機執行時的其他錯誤

依預設,新的雲端服務專案會使用 Azure 計算模擬器精簡版來模擬 Azure 環境。 Azure 計算模擬器是完整計算模擬器的輕量版本,在某些情況下,完整版模擬器能夠正常運作,精簡版則不行。

若要將專案變更為使用完整版模擬器,請以滑鼠右鍵按一下 ContosoAdsCloudService 專案,然後選取 [屬性]。 在 [屬性] 視窗中,選取 [Web] 索引標籤,然後選取 [使用完整版模擬器] 選項按鈕。

為使用完整版模擬器執行應用程式,您必須使用管理員權限開啟 Visual Studio。

後續步驟

Contoso Ads 應用程式特意保持簡潔,以供入門教學課程使用。 例如,它不會實作 相依性插入工作模式的存放庫和單位。 它不會 使用介面進行記錄,也不會使用 EF Code First Migrations 來管理數據模型變更或 EF Connection Resiliency 來管理暫時性網路錯誤等等。

如需開發雲端的一般資訊,請參閱 使用 Azure 建置 Real-World Cloud Apps

如需詳細資訊,請參閱下列資源: