您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

Azure 云服务和 ASP.NET 入门Get started with Azure Cloud Services and ASP.NET

概述Overview

本教程演示如何使用 ASP.NET MVC 前端创建多层.NET 应用程序,并将其部署到 Azure 云服务This tutorial shows how to create a multi-tier .NET application with an ASP.NET MVC front-end, and deploy it to an Azure cloud service. 应用程序使用 Azure SQL 数据库Azure Blob 服务Azure 队列服务The application uses Azure SQL Database, the Azure Blob service, and the Azure Queue service. 可以从 MSDN 代码库 下载 Visual Studio 项目You can download the Visual Studio project from the MSDN Code Gallery.

本教程介绍如何在本地生成并运行应用程序、如何将其部署到 Azure 并在云中运行,以及如何从头构建。The tutorial shows you how to build and run the application locally, how to deploy it to Azure and run in the cloud, and how to build it from scratch. 可以从头构建并进行测试,之后根据喜好部署步骤。You can start by building from scratch and then do the test and deploy steps afterward if you prefer.

Contoso 广告应用程序Contoso Ads application

该应用程序是广告公告板。The application is an advertising bulletin board. 用户通过输入文本和上载图像创建一个广告。Users create an ad by entering text and uploading an image. 用户可以通过缩略图查看广告列表,并在选择一个广告以查看其详细信息时,查看完整尺寸的图像。They can see a list of ads with thumbnail images, and they can see the full-size image when they select an ad to see the details.

广告列表

应用程序使用 以队列为中心的工作模式 来减轻创建缩略图到后端进程的 CPU 密集型工作。The application uses the queue-centric work pattern to off-load the CPU-intensive work of creating thumbnails to a back-end process.

替代体系结构:应用服务和 WebJobsAlternative architecture: App Service and WebJobs

本教程演示如何在 Azure 云服务中运行前端和后端。This tutorial shows how to run both front-end and back-end in an Azure cloud service. 一种替代方法是在 Azure 应用服务中运行前端,并对后端使用 WebJobs 功能。An alternative is to run the front-end in Azure App Service and use the WebJobs feature for the back-end. 有关如何使用 WebJobs 的教程,请参阅 Azure WebJobs SDK 入门For a tutorial that uses WebJobs, see Get Started with the Azure WebJobs SDK. 有关如何选择最适合方案的服务的信息,请参阅 Azure 应用服务、云服务和虚拟机比较For information about how to choose the services that best fit your scenario, see Azure App Service, Cloud Services, and virtual machines comparison.

学习内容What you'll learn

  • 如何通过安装 Azure SDK 来让计算机可以进行 Azure 开发。How to enable your machine for Azure development by installing the Azure SDK.
  • 如何通过 ASP.NET MVC web 角色和辅助角色创建一个 Visual Studio 云服务项目。How to create a Visual Studio cloud service project with an ASP.NET MVC web role and a worker role.
  • 如何使用 Azure 存储仿真程序测试本地云服务项目。How to test the cloud service project locally, using the Azure storage emulator.
  • 如何将云项目发布到 Azure 云服务并使用 Azure 存储帐户测试。How to publish the cloud project to an Azure cloud service and test using an Azure storage account.
  • 如何上传文件并将其存储在 Azure Blob 服务中。How to upload files and store them in the Azure Blob service.
  • 如何将 Azure 队列服务用于各层之间的通信。How to use the Azure Queue service for communication between tiers.

先决条件Prerequisites

本教程假定用户了解有关 Azure 云服务的基本概念,例如 Web 角色辅助角色这样的术语。The tutorial assumes that you understand basic concepts about Azure cloud services such as web role and worker role terminology. 此外,还假定用户知道如何处理 Visual Studio 中的 ASP.NET MVCWeb 窗体项目。It also assumes that you know how to work with ASP.NET MVC or Web Forms projects in Visual Studio. 示例应用程序使用 MVC,但在本教程的大部分也适用于 Web 窗体。The sample application uses MVC, but most of the tutorial also applies to Web Forms.

在没有 Azure 订阅的情况下可以本地运行应用,但要将应用程序部署到云中,则需要一个 Azure 订阅。You can run the app locally without an Azure subscription, but you'll need one to deploy the application to the cloud. 如果没有帐户,则可以激活 MSDN 订户权益注册获取免费试用版If you don't have an account, you can activate your MSDN subscriber benefits or sign up for a free trial.

本教程说明使用以下产品之一:The tutorial instructions work with any of the following products:

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

上述产品中,只要缺少其中任意一个,安装 Azure SDK 时就会自动安装 Visual Studio。If you don't have one of these, Visual Studio may be installed automatically when you install the Azure SDK.

应用程序体系结构Application architecture

该应用程序将广告存储在 SQL 数据库中,通过使用实体框架 Code First 创建表和访问数据。The app stores ads in a SQL database, using Entity Framework Code First to create the tables and access the data. 对于每个广告,数据库存储两个 URL:一个用于全尺寸图像,另一个用于缩略图。For each ad, the database stores two URLs, one for the full-size image and one for the thumbnail.

广告表

当用户上传一个图像时,Web 角色中运行的前端在 Azure Blob 中存储图像,并将广告信息存储在带有指向 Blob 的 URL 的数据库中。When a user uploads an image, the front-end running in a web role stores the image in an Azure blob, and it stores the ad information in the database with a URL that points to the blob. 同时,它将一条消息写入 Azure 队列。At the same time, it writes a message to an Azure queue. 在辅助角色中定期运行的后端进程轮询队列是否有新消息。A back-end process running in a worker role periodically polls the queue for new messages. 显示新消息时,辅助角色将创建该图像的缩略图,并为该广告更新缩略图 URL 数据库字段。When a new message appears, the worker role creates a thumbnail for that image and updates the thumbnail URL database field for that ad. 下图演示了应用程序各部分之间如何交互:The following diagram shows how the parts of the application interact.

Contoso 广告体系结构

设置开发环境Set up the development environment

首先,请通过 Visual Studio 和 Azure SDK 来设置开发环境。To start, set up your development environment with Visual Studio and the Azure SDK.

备注

根据计算机上已有 SDK 依赖项的数量,安装 SDK 可能耗时较长,从几分钟到半小时或更长时间不等。Depending on the number of the SDK dependencies already on your machine, installing the SDK could take a long time, from several minutes to a half hour or more.

下载并运行已完成的解决方案Download and run the completed solution

  1. 下载并解压缩 已完成的解决方案Download and unzip the completed solution.

  2. 启动 Visual Studio。Start Visual Studio.

  3. 从“文件”菜单中,选择“打开项目”,导航到下载解决方案的位置,并打开解决方案文件。From the File menu choose Open Project, navigate to where you downloaded the solution, and then open the solution file.

  4. 按 CTRL+SHIFT+B 生成解决方案。Press CTRL+SHIFT+B to build the solution.

    默认情况下,Visual Studio 会自动还原 NuGet 包的内容,它未包括在 .zip 文件中。By default, Visual Studio automatically restores the NuGet package content, which was not included in the .zip file. 如果包未还原,请通过转到“管理解决方案的 NuGet 包”对话框并单击右上角的“还原”按钮手动安装。If the packages don't restore, install them manually by going to the Manage NuGet Packages for Solution dialog box and clicking the Restore button at the top right.

  5. 在“解决方案资源管理器”中,确保 ContosoAdsCloudService 被选为启动项目。In Solution Explorer, make sure that ContosoAdsCloudService is selected as the startup project.

  6. 如果使用 Visual Studio 2015 或更高版本,请在 ContosoAdsWeb 项目的应用程序 Web.config 文件以及 ContosoAdsCloudService 项目的 ServiceConfiguration.Local.cscfg 文件中,更改 SQL Server 连接字符串。If you're using Visual Studio 2015 or higher, change the SQL Server connection string in the application Web.config file of the ContosoAdsWeb project and in the ServiceConfiguration.Local.cscfg file of the ContosoAdsCloudService project. 对于每种情况,请将“(localdb)\v11.0”更改为“(localdb)\MSSQLLocalDB”。In each case, change "(localdb)\v11.0" to "(localdb)\MSSQLLocalDB".

  7. 按 Ctrl+F5 运行应用程序。Press CTRL+F5 to run the application.

    在本地运行云服务项目时,Visual Studio 会自动调用 Azure 计算模拟器和 Azure 存储模拟器When you run a cloud service project locally, Visual Studio automatically invokes the Azure compute emulator and Azure storage emulator. 计算仿真程序使用计算机资源,以模拟 web 角色和辅助角色环境。The compute emulator uses your computer's resources to simulate the web role and worker role environments. 存储模拟器使用 SQL Server Express LocalDB 数据库模拟 Azure 云存储。The storage emulator uses a SQL Server Express LocalDB database to simulate Azure cloud storage.

    首次运行云服务项目时,模拟器会花费大约一分钟来启动。The first time you run a cloud service project, it takes a minute or so for the emulators to start up. 模拟器完成启动后,默认浏览器中会打开应用程序的主页。When emulator startup is finished, the default browser opens to the application home page.

    Contoso 广告体系结构

  8. 单击“创建广告”。Click Create an Ad.

  9. 输入一些测试数据并选择一个要上载的 .jpg 图像,并单击“创建”。Enter some test data and select a .jpg image to upload, and then click Create.

    创建页面

    该应用程序转到索引页,但它不显示新广告的缩略图,因为该处理尚未发生。The app goes to the Index page, but it doesn't show a thumbnail for the new ad because that processing hasn't happened yet.

  10. 稍等片刻,并刷新该索引页查看缩略图。Wait a moment and then refresh the Index page to see the thumbnail.

    索引页面

  11. 单击广告的“详细信息”查看实际尺寸的图像 。Click Details for your ad to see the full-size image.

    详细信息页

已在本地计算机上完全运行应用程序,但未连接到云。You've been running the application entirely on your local computer, with no connection to the cloud. 存储模拟器将队列和 Blob 数据存储在 SQL Server Express LocalDB 数据库中,应用程序将广告数据存储在另一个 LocalDB 数据库中。The storage emulator stores the queue and blob data in a SQL Server Express LocalDB database, and the application stores the ad data in another LocalDB database. 在 Web 应用首次尝试访问它时,实体框架 Code First 自动创建广告数据库。Entity Framework Code First automatically created the ad database the first time the web app tried to access it.

下一部分中,要将解决方案配置为在云中运行时对队列、Blob 和应用程序数据库使用 Azure 云资源。In the following section you'll configure the solution to use Azure cloud resources for queues, blobs, and the application database when it runs in the cloud. 如果需要继续在本地运行,但同时又要使用云存储和数据库资源,则可以这样做。If you wanted to continue to run locally but use cloud storage and database resources, you could do that. 只需设置连接字符串即可,这一点会随后介绍。It's just a matter of setting connection strings, which you'll see how to do.

将应用程序部署到 AzureDeploy the application to Azure

将执行以下步骤,以便在云中运行应用程序:You'll do the following steps to run the application in the cloud:

  • 创建 Azure 云服务。Create an Azure cloud service.
  • 创建 Azure SQL 数据库。Create an Azure SQL database.
  • 创建 Azure 存储帐户。Create an Azure storage account.
  • 配置解决方案,以便在 Azure 中运行时使用 Azure SQL 数据库。Configure the solution to use your Azure SQL database when it runs in Azure.
  • 配置解决方案以便在 Azure 中运行时使用 Azure 存储帐户。Configure the solution to use your Azure storage account when it runs in Azure.
  • 将项目部署到 Azure 云服务。Deploy the project to your Azure cloud service.

创建 Azure 云服务Create an Azure cloud service

Azure 云服务是该应用程序将运行的环境。An Azure cloud service is the environment the application will run in.

  1. 在浏览器中,打开 Azure 门户In your browser, open the Azure portal.

  2. 单击“创建资源”>“计算”>“云服务”。Click Create a resource > Compute > Cloud Service.

  3. 在 DNS 名称输入框中,输入云服务的 URL 前缀。In the DNS name input box, enter a URL prefix for the cloud service.

    此 URL 必须是唯一的。This URL has to be unique. 如果所选前缀已被使用,则会获得一条错误消息。You'll get an error message if the prefix you choose is already in use.

  4. 为服务指定新的资源组。Specify a new Resource group for the service. 单击“新建”,然后在资源组输入框中键入一个名称,例如 CS_contososadsRG。Click Create new and then type a name in the Resource group input box, such as CS_contososadsRG.

  5. 选择要在其中部署该应用程序的区域。Choose the region where you want to deploy the application.

    此字段指定云服务将托管在哪个数据中心。This field specifies which datacenter your cloud service will be hosted in. 对于生产应用程序,可以选择离客户最近的区域。For a production application, you'd choose the region closest to your customers. 对于本教程,选择最近的区域。For this tutorial, choose the region closest to you.

  6. 单击“创建”。Click Create.

    在下图中,使用 URL CSvccontosoads.cloudapp.net 创建了一个云服务。In the following image, a cloud service is created with the URL CSvccontosoads.cloudapp.net.

    新的云服务

创建 Azure SQL 数据库Create an Azure SQL database

在云中运行应用程序时,它将使用基于云的数据库。When the app runs in the cloud, it will use a cloud-based database.

  1. Azure 门户中,单击“创建资源”>“数据库”>“SQL 数据库”。In the Azure portal, click Create a resource > Databases > SQL Database.

  2. 在“数据库名称”框中 ,输入 contosoadsIn the Database Name box, enter contosoads.

  3. 在“资源组”中,单击“使用现有资源组”,并选择用于云服务的资源组。In the Resource group, click Use existing and select the resource group used for the cloud service.

  4. 在下图中,单击“服务器 - 配置所需设置”和“新建服务器”。In the following image, click Server - Configure required settings and Create a new server.

    到数据库服务器的隧道

    或者,如果订阅已有一台服务器,可从下拉列表中选择该服务器。Alternatively, if your subscription already has a server, you can select that server from the drop-down list.

  5. 在“服务器名称”框中,输入 csvccontosodbserver。In the Server name box, enter csvccontosodbserver.

  6. 输入管理员“登录名”和“密码”。Enter an administrator Login Name and Password.

    如果选择了“新建服务器”,则不在此处输入现有名称和密码。If you selected Create a new server, you aren't entering an existing name and password here. 需要输入新的名称和密码,这些名称和密码需要现在定义,供以后访问数据库时使用。You're entering a new name and password that you're defining now to use later when you access the database. 如果选择之前创建的服务器,系统会提示已创建的管理用户帐户的密码。If you selected a server that you created previously, you'll be prompted for the password to the administrative user account you already created.

  7. 选择的“区域”与为云服务选择的相同。Choose the same Location that you chose for the cloud service.

    当云服务和数据库位于不同的数据中心(不同区域)时,延迟将增加,并且要支付带宽数据中心之外的费用。When the cloud service and database are in different datacenters (different regions), latency will increase and you will be charged for bandwidth outside the data center. 数据中心内的带宽是免费的。Bandwidth within a data center is free.

  8. 选中“允许 Azure 服务访问服务器”。Check Allow azure services to access server.

  9. 针对新服务器单击“选择”。Click Select for the new server.

    新建 SQL 数据库服务器

  10. 单击“创建”。Click Create.

创建 Azure 存储帐户Create an Azure storage account

Azure 存储帐户提供在云中存储队列和 Blob 数据的资源。An Azure storage account provides resources for storing queue and blob data in the cloud.

在实际应用程序中,通常会为记录数据的应用程序数据创建单独的帐户,并且为生产数据的测试数据创建单独帐户。In a real-world application, you would typically create separate accounts for application data versus logging data, and separate accounts for test data versus production data. 对于本教程,将只使用一个帐户。For this tutorial, you'll use just one account.

  1. Azure 门户中,单击“创建资源”>“存储”>“存储帐户 - Blob、文件、表、队列”。In the Azure portal, click Create a resource > Storage > Storage account - blob, file, table, queue.

  2. 在“名称”框中,输入 URL 前缀。In the Name box, enter a URL prefix.

    此前缀加上在框下看到的文本将是存储帐户的唯一 URL。This prefix plus the text you see under the box will be the unique URL to your storage account. 如果其他人已使用输入的前缀,必须选择不同的前缀。If the prefix you enter has already been used by someone else, you'll have to choose a different prefix.

  3. 将“部署模型”设置为“经典”。Set the Deployment model to Classic.

  4. 将“复制”下拉列表设置为“本地冗余存储”。Set the Replication drop-down list to Locally redundant storage.

    为存储帐户启用异地复制时,会将存储内容复制到辅助数据中心,这样就能够在主要位置发生重大灾难时进行故障转移。When geo-replication is enabled for a storage account, the stored content is replicated to a secondary datacenter to enable failover if a major disaster occurs in the primary location. 异地复制可能会产生额外的成本。Geo-replication can incur additional costs. 对于测试和开发帐户,你通常不希望因为异地复制而付款。For test and development accounts, you generally don't want to pay for geo-replication. 有关详细信息,请参阅创建、管理或删除存储帐户For more information, see Create, manage, or delete a storage account.

  5. 在“资源组”中,单击“使用现有资源组”,然后选择用于云服务的资源组。In the Resource group, click Use existing and select the resource group used for the cloud service.

  6. 将“位置”下拉列表设置为为云服务选择的同一区域。Set the Location drop-down list to the same region you chose for the cloud service.

    当云服务和存储帐户位于不同的数据中心(不同区域)时,延迟将增加,并且需要为数据中心外的带宽付费。When the cloud service and storage account are in different datacenters (different regions), latency will increase and you will be charged for bandwidth outside the data center. 数据中心内的带宽是免费的。Bandwidth within a data center is free.

    Azure 地缘组实际上是一种机制,目的是最小化数据中心内不同资源之间的距离,这样可以降低延迟。Azure affinity groups provide a mechanism to minimize the distance between resources in a data center, which can reduce latency. 本教程不使用地缘组。This tutorial does not use affinity groups. 有关详细信息,请参阅 如何在 Azure 中创建地缘组For more information, see How to Create an Affinity Group in Azure.

  7. 单击“创建”。Click Create.

    新的存储帐户

    在图中,使用 URL“ csvccontosoads.core.windows.net”创建一个存储帐户。In the image, a storage account is created with the URL csvccontosoads.core.windows.net.

配置解决方案,以便在 Azure 中运行时使用 Azure SQL 数据库Configure the solution to use your Azure SQL database when it runs in Azure

Web 项目和辅助角色项目自身具有数据库连接字符串,并且当应用程序在 Azure 运行时指向 Azure SQL 数据库。The web project and the worker role project each has its own database connection string, and each needs to point to the Azure SQL database when the app runs in Azure.

将为 Web 角色使用 Web.config 转换,为辅助角色使用云服务环境设置。You'll use a Web.config transform for the web role and a cloud service environment setting for the worker role.

备注

在本部分和下一部分,会在项目文件中存储凭据。In this section and the next section, you store credentials in project files. 不要将敏感数据存储在公共源代码存储库中Don't store sensitive data in public source code repositories.

  1. 在 ContosoAdsWeb 项目中,为应用程序 Web.config 文件打开 Web.Release.config 转换文件,删除包含 <connectionStrings> 元素的注释块,并在其原位置粘贴下面的代码。In the ContosoAdsWeb project, open the Web.Release.config transform file for the application Web.config file, delete the comment block that contains a <connectionStrings> element, and paste the following code in its place.

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

    保持文件打开进行编辑。Leave the file open for editing.

  2. Azure 门户中,依次单击左窗格中的“SQL 数据库”、为本教程创建的数据库、“显示连接字符串”。In the Azure portal, click SQL Databases in the left pane, click the database you created for this tutorial, and then click Show connection strings.

    显示连接字符串

    门户会显示连接字符串,其占位符用于输入密码。The portal displays connection strings, with a placeholder for the password.

    连接字符串

  3. Web.Release.config 转换文件中,删除 {connectionstring} 并在其位置粘贴 Azure 门户中的 ADO.NET 连接字符串。In the Web.Release.config transform file, delete {connectionstring} and paste in its place the ADO.NET connection string from the Azure portal.

  4. 在粘贴到 Web.Release.config 转换文件的连接字符串中,请用为新的 SQL 数据库创建的密码替换 {your_password_here}In the connection string that you pasted into the Web.Release.config transform file, replace {your_password_here} with the password you created for the new SQL database.

  5. 保存该文件。Save the file.

  6. 选择并复制连接字符串,供在以下步骤中配置辅助角色项目的使用(不带周围的引号)。Select and copy the connection string (without the surrounding quotation marks) for use in the following steps for configuring the worker role project.

  7. 在云服务项目的“角色”下的“解决方案资源管理器”中,右键单击“ContosoAdsWorker”并单击“属性”。In Solution Explorer, under Roles in the cloud service project, right-click ContosoAdsWorker and then click Properties.

    角色属性

  8. 单击“设置”选项卡。Click the Settings tab.

  9. 将“服务配置”更改为“云”。Change Service Configuration to Cloud.

  10. 选择 ContosoAdsDbConnectionString 设置的“值”字段,并粘贴从本教程上一部分复制的连接字符串。Select the Value field for the ContosoAdsDbConnectionString setting, and then paste the connection string that you copied from the previous section of the tutorial.

    辅助角色的数据库连接字符串

  11. 保存所做更改。Save your changes.

配置解决方案以便在 Azure 中运行时使用 Azure 存储帐户Configure the solution to use your Azure storage account when it runs in Azure

Web 角色项目和辅助角色项目的 azure 存储帐户连接字符串存储在云服务项目中的环境设置。Azure storage account connection strings for both the web role project and the worker role project are stored in environment settings in the cloud service project. 对于每个项目来说,应用程序在本地运行和在云中运行所要使用的设置集是不同的。For each project, there is a separate set of settings to be used when the application runs locally and when it runs in the cloud. 将更新用于 web 和辅助角色项目的云环境设置。You'll update the cloud environment settings for both web and worker role projects.

  1. 在“解决方案资源管理器”中,右键单击“ContosoAdsCloudService”项目中“角色”下的“ContosoAdsWeb”,并单击“属性”。In Solution Explorer, right-click ContosoAdsWeb under Roles in the ContosoAdsCloudService project, and then click Properties.

    角色属性

  2. 单击“设置”选项卡。在“服务配置”下拉列表框中,选择“云”。Click the Settings tab. In the Service Configuration drop-down box, choose Cloud.

    云配置

  3. 选择“StorageConnectionString”条目,此时会看到一个省略号 ( ... ) 按钮,位于行的右端。Select the StorageConnectionString entry, and you'll see an ellipsis (...) button at the right end of the line. 单击省略号按钮打开“创建存储帐户连接字符串”对话框 。Click the ellipsis button to open the Create Storage Account Connection String dialog box.

    打开连接字符串创建框

  4. 在“创建存储连接字符串”对话框中,单击“订阅”,选择以前创建的存储帐户,然后单击“确定”。In the Create Storage Connection String dialog box, click Your subscription, choose the storage account that you created earlier, and then click OK. 如果尚未登录,会提示输入 Azure 帐户凭据。If you're not already logged in, you'll be prompted for your Azure account credentials.

    创建存储连接字符串

  5. 保存所做更改。Save your changes.

  6. 按用于 StorageConnectionString 连接字符串的同一过程设置 Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString 连接字符串。Follow the same procedure that you used for the StorageConnectionString connection string to set the Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString connection string.

    此连接字符串用于日志记录。This connection string is used for logging.

  7. 请按照用于 ContosoAdsWeb 角色的相同过程为 ContosoAdsWorker 角色设置两个连接字符串。Follow the same procedure that you used for the ContosoAdsWeb role to set both connection strings for the ContosoAdsWorker role. 不要忘记将“服务配置”设置为“云”。Don't forget to set Service Configuration to Cloud.

已使用 Visual Studio 用户界面进行配置的角色环境设置存储在 ContosoAdsCloudService 项目的以下文件中:The role environment settings that you have configured using the Visual Studio UI are stored in the following files in the ContosoAdsCloudService project:

  • ServiceDefinition.csdef - 定义设置名称。ServiceDefinition.csdef - Defines the setting names.
  • ServiceConfiguration.Cloud.cscfg - 为云中运行的应用提供值。ServiceConfiguration.Cloud.cscfg - Provides values for when the app runs in the cloud.
  • ServiceConfiguration.Local.cscfg - 为本地运行的应用提供值。ServiceConfiguration.Local.cscfg - Provides values for when the app runs locally.

例如,ServiceDefinition.csdef 包括以下定义:For example, the ServiceDefinition.csdef includes the following definitions:

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

ServiceConfiguration.Cloud.cscfg 文件包括你在 Visual Studio 中为这些设置输入的值。And the ServiceConfiguration.Cloud.cscfg file includes the values you entered for those settings in 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 要在其上运行辅助角色代码的虚拟机的数量。The <Instances> setting specifies the number of virtual machines that Azure will run the worker role code on. 后续步骤 部分包括有关向外缩放云服务的详细信息的链接。The Next steps section includes links to more information about scaling out a cloud service,

将项目部署到 AzureDeploy the project to Azure

  1. 在“解决方案资源管理器”中,右键单击“ContosoAdsCloudService”云项目并选择“发布”。In Solution Explorer, right-click the ContosoAdsCloudService cloud project and then select Publish.

    发布菜单

  2. 在“发布 Azure 应用程序”向导的“登录”步骤中,单击“下一步”。In the Sign in step of the Publish Azure Application wizard, click Next.

    登录步骤

  3. 在向导的“设置”步骤中,单击“下一步”。In the Settings step of the wizard, click Next.

    设置步骤

    本教程可以使用“高级”选项卡中的默认设置 。The default settings in the Advanced tab are fine for this tutorial. 有关高级选项卡的信息,请参阅 发布 Azure 应用程序向导For information about the advanced tab, see Publish Azure Application Wizard.

  4. 在“摘要”步骤中,单击“发布”。In the Summary step, click Publish.

    摘要步骤

    “Azure 活动日志”窗口会在 Visual Studio 中打开 。The Azure Activity Log window opens in Visual Studio.

  5. 单击右箭头图标以展开部署详细信息。Click the right arrow icon to expand the deployment details.

    部署可能需要 5 分钟或更长时间。The deployment can take up to 5 minutes or more to complete.

    Azure 活动日志窗口

  6. 当部署状态为完成时,单击“Web 应用 URL” 启动应用程序。When the deployment status is complete, click the Web app URL to start the application.

  7. 就像在本地运行应用程序一样,现在可以通过创建、查看和编辑一些广告测试应用程序。You can now test the app by creating, viewing, and editing some ads, as you did when you ran the application locally.

备注

完成测试后,删除或停止云服务。When you're finished testing, delete or stop the cloud service. 即使不使用云服务,也会产生费用,因为需为其保留虚拟机资源。Even if you're not using the cloud service, it's accruing charges because virtual machine resources are reserved for it. 如果保持运行云服务,找到 URL 的任何人都可以创建和查看广告。And if you leave it running, anyone who finds your URL can create and view ads. Azure 门户中,转到云服务的“概览”选项卡,然后单击页面顶部的“删除”按钮。In the Azure portal, go to the Overview tab for your cloud service, and then click the Delete button at the top of the page. If you just want to temporarily prevent others from accessing the site, click Stop instead. 在这种情况下,会继续产生费用。In that case, charges will continue to accrue. 不再需要 SQL 数据库和存储帐户时,可以遵循类似的过程将其删除。You can follow a similar procedure to delete the SQL database and storage account when you no longer need them.

从头开始创建应用程序Create the application from scratch

如果尚未下载 已完成的应用程序,现在请下载。If you haven't already downloaded the completed application, do that now. 要将文件从下载的项目复制到新的项目。You'll copy files from the downloaded project into the new project.

创建 Contoso 广告应用程序涉及以下步骤:Creating the Contoso Ads application involves the following steps:

  • 创建云服务 Visual Studio 解决方案。Create a cloud service Visual Studio solution.
  • 更新和添加 NuGet 包。Update and add NuGet packages.
  • 设置项目引用。Set project references.
  • 配置连接字符串。Configure connection strings.
  • 添加代码文件。Add code files.

创建该解决方案后,将审核对于云服务项目和 Azure blob 和队列唯一的代码。After the solution is created, you'll review the code that is unique to cloud service projects and Azure blobs and queues.

创建云服务 Visual Studio 解决方案Create a cloud service Visual Studio solution

  1. 在 Visual Studio 中,从“文件”菜单中选择“新建项目” 新建项目 from the 。In Visual Studio, choose New Project from the File menu.

  2. 在“新建项目”对话框的左窗格中,展开“Visual C#”,选择“云”模板,并选择“Microsoft Azure 云服务”模板。In the left pane of the New Project dialog box, expand Visual C# and choose Cloud templates, and then choose the Azure Cloud Service template.

  3. 将项目和解决方案命名为 ContosoAdsCloudService,然后单击“确定”。Name the project and solution ContosoAdsCloudService, and then click OK.

    新建项目

  4. 在“新建 Azure 云服务”对话框中,添加一个 Web 角色和辅助角色。In the New Azure Cloud Service dialog box, add a web role and a worker role. 将 web 角色命名为 ContosoAdsWeb,并将辅助角色命名为 ContosoAdsWorker。Name the web role ContosoAdsWeb, and name the worker role ContosoAdsWorker. (使用右侧窗格中的铅笔图标更改这些角色的默认名称。)(Use the pencil icon in the right-hand pane to change the default names of the roles.)

    新建云服务项目

  5. 看到 Web 角色的“新建 ASP.NET 项目”对话框时,选择 MVC 模板中,并单击“更改身份验证”。When you see the New ASP.NET Project dialog box for the web role, choose the MVC template, and then click Change Authentication.

    更改身份验证

  6. 在“更改身份验证”对话框中,选择“无身份验证”,并单击“确定”。In the Change Authentication dialog box, choose No Authentication, and then click OK.

    无身份验证

  7. 在“新建 ASP.NET 项目”对话框中,单击“确定”。In the New ASP.NET Project dialog, click OK.

  8. 在“解决方案资源管理器”中,右键单击该解决方案(而不是其中某个项目),并选择“添加 - 新建项目”。In Solution Explorer, right-click the solution (not one of the projects), and choose Add - New Project.

  9. 在“添加新项目”对话框中,选择左窗格中“Visual C#”下面的“Windows”,并单击“类库”模板。In the Add New Project dialog box, choose Windows under Visual C# in the left pane, and then click the Class Library template.

  10. 将项目命名为 ContosoAdsCommon,然后单击“确定”。Name the project ContosoAdsCommon, and then click OK.

    需要从 Web 和辅助角色项目引用实体框架上下文和数据模型。You need to reference the Entity Framework context and the data model from both web and worker role projects. 替代方法是,在 Web 角色项目中定义与 EF 相关的类,并从辅助角色项目中引用该项目。As an alternative, you could define the EF-related classes in the web role project and reference that project from the worker role project. 但在替代方法中,辅助角色项目会引用不需要的 Web 程序集。But in the alternative approach, your worker role project would have a reference to web assemblies that it doesn't need.

更新和添加 NuGet 包Update and add NuGet packages

  1. 打开解决方案的“管理 NuGet 包”对话框 。Open the Manage NuGet Packages dialog box for the solution.

  2. 在窗口顶部,选择“更新”。At the top of the window, select Updates.

  3. 查找 WindowsAzure.Storage 包,如果它在列表中,请选择它并选择要在其中更新它的 Web 项目和辅助角色项目,并单击“更新”。Look for the WindowsAzure.Storage package, and if it's in the list, select it and select the web and worker projects to update it in, and then click Update.

    存储客户端库更新频率高于 Visual Studio 项目模板,因此经常会发现新创建项目中的版本需要更新。The storage client library is updated more frequently than Visual Studio project templates, so you'll often find that the version in a newly-created project needs to be updated.

  4. 在窗口顶部,选择“浏览”。At the top of the window, select Browse.

  5. 找到 EntityFramework NuGet 包,并将其安装在所有三个项目中。Find the EntityFramework NuGet package, and install it in all three projects.

  6. 查找 Microsoft.WindowsAzure.ConfigurationManager NuGet 包,并将它安装在辅助角色项目中。Find the Microsoft.WindowsAzure.ConfigurationManager NuGet package, and install it in the worker role project.

设置项目引用Set project references

  1. 在 ContosoAdsWeb 项目中,设置对 ContosoAdsCommon 项目的引用。In the ContosoAdsWeb project, set a reference to the ContosoAdsCommon project. 右键单击 ContosoAdsWeb 项目,并单击“引用” - “添加引用”。Right-click the ContosoAdsWeb project, and then click References - Add References. 在“引用管理器”对话框中,选择左窗格中的“解决方案 - 项目”,选择 ContosoAdsCommon,并单击“确定”。In the Reference Manager dialog box, select Solution – Projects in the left pane, select ContosoAdsCommon, and then click OK.

  2. 在 ContosoAdsWorker 项目中,设置对 ContosoAdsCommon 项目的引用。In the ContosoAdsWorker project, set a reference to the ContosoAdsCommon project.

    ContosoAdsCommon 将包含实体框架数据模型和上下文类,会在前端和后端使用。ContosoAdsCommon will contain the Entity Framework data model and context class, which will be used by both the front-end and back-end.

  3. 在 ContosoAdsWorker 项目中,设置对 System.Drawing的引用。In the ContosoAdsWorker project, set a reference to System.Drawing.

    后端使用此程序集将图像转换为缩略图。This assembly is used by the back-end to convert images to thumbnails.

配置连接字符串Configure connection strings

在本部分,你将为本地测试配置 Azure 存储和 SQL 连接字符串。In this section, you configure Azure Storage and SQL connection strings for testing locally. 本教程前面的部署说明解释如何当应用程序在云中运行时设置连接字符串。The deployment instructions earlier in the tutorial explain how to set up the connection strings for when the app runs in the cloud.

  1. 在 ContosoAdsWeb 项目中,打开应用程序 Web.config 文件,并在 configSections 元素后面插入以下 connectionStrings 元素。In the ContosoAdsWeb project, open the application Web.config file, and insert the following connectionStrings element after the configSections element.

    <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”。If you're using Visual Studio 2015 or higher, replace "v11.0" with "MSSQLLocalDB".

  2. 保存所做更改。Save your changes.

  3. 在 ContosoAdsCloudService 项目中,右键单击“角色”下的 ContosoAdsWeb,并单击“属性”。In the ContosoAdsCloudService project, right-click ContosoAdsWeb under Roles, and then click Properties.

    角色属性

  4. 在“ContosoAdsWeb [角色]”属性窗口中,单击“设置”选项卡,并单击“添加设置”。In the ContosoAdsWeb [Role] properties window, click the Settings tab, and then click Add Setting.

    将“服务配置”保留设置为“所有配置”。Leave Service Configuration set to All Configurations.

  5. 添加名为 StorageConnectionString 的设置。Add a setting named StorageConnectionString. 将“类型”设置为 ConnectionString,并将“值”设置为 UseDevelopmentStorage=trueSet Type to ConnectionString, and set Value to UseDevelopmentStorage=true.

    新连接字符串

  6. 保存所做更改。Save your changes.

  7. 按照相同的过程在 ContosoAdsWorker 角色属性中添加存储连接字符串。Follow the same procedure to add a storage connection string in the ContosoAdsWorker role properties.

  8. 还是在“ContosoAdsWorker [角色]”属性窗口中,添加另一个连接字符串 :Still in the ContosoAdsWorker [Role] properties window, add another connection string:

    • 名称:ContosoAdsDbConnectionStringName: ContosoAdsDbConnectionString

    • 键入:StringType: String

    • 值:粘贴用于 Web 角色项目的相同连接字符串。Value: Paste the same connection string you used for the web role project. (以下示例适用于 Visual Studio 2013。(The following example is for Visual Studio 2013. 如果你使用 Visual Studio 2015 或更高版本并想要复制此示例,请记得更改数据源。)Don't forget to change the Data Source if you copy this example and you're using Visual Studio 2015 or higher.)

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

添加代码文件Add code files

在本部分,你要将代码文件从已下载的解决方案复制到新的解决方案。In this section, you copy code files from the downloaded solution into the new solution. 以下各节会显示并解释此代码的关键部分。The following sections will show and explain key parts of this code.

要将文件添加到某个项目或文件夹,请右键单击该项目或文件夹,并单击“添加” - “现有项”。To add files to a project or a folder, right-click the project or folder and click Add - Existing Item. 选择所需的文件,并单击“添加”。Select the files you want and then click Add. 如果询问你是否想要替换现有文件,请单击“是”。If asked whether you want to replace existing files, click Yes.

  1. 在 ContosoAdsCommon 项目中,删除 Class1.cs 文件,并在其原位置添加来自下载项目的 Ad.csContosoAdscontext.cs 文件。In the ContosoAdsCommon project, delete the Class1.cs file and add in its place the Ad.cs and ContosoAdscontext.cs files from the downloaded project.

  2. 在 ContosoAdsWeb 项目中,从下载的项目添加以下文件。In the ContosoAdsWeb project, add the following files from the downloaded project.

    • Global.asax.csGlobal.asax.cs.
    • 在“Views\Shared”文件夹中:_Layout.cshtml。In the Views\Shared folder: _Layout.cshtml.
    • 在“Views\Home”文件夹中:Index.cshtml。In the Views\Home folder: Index.cshtml.
    • 在“Controllers”文件夹中:AdController.cs。In the Controllers folder: AdController.cs.
    • Views\Ad 文件夹(首先创建该文件夹)中:五个 .cshtml 文件。In the Views\Ad folder (create the folder first): five .cshtml files.
  3. 在 ContosoAdsWorker 项目中,从下载的项目添加 WorkerRole.csIn the ContosoAdsWorker project, add WorkerRole.cs from the downloaded project.

现在,可以按照前面教程中的说明生成并运行该应用程序,并且该应用程序将使用本地数据库和存储仿真程序资源。You can now build and run the application as instructed earlier in the tutorial, and the app will use local database and storage emulator resources.

以下部分介绍与使用 Azure 环境、Blob 和队列相关的代码。The following sections explain the code related to working with the Azure environment, blobs, and queues. 本教程未说明如何使用基架创建 MVC 控制器和视图,如何编写适用于 SQL Server 数据库的实体框架代码,或者在 ASP.NET 4.5 中的异步编程基础知识。This tutorial does not explain how to create MVC controllers and views using scaffolding, how to write Entity Framework code that works with SQL Server databases, or the basics of asynchronous programming in ASP.NET 4.5. 有关这些主题的信息,请参阅以下资源:For information about these topics, see the following resources:

ContosoAdsCommon - Ad.csContosoAdsCommon - Ad.cs

Ad.cs 文件为 ad 类别定义一个枚举,为 ad 信息定义一个 POCO 实体类。The Ad.cs file defines an enum for ad categories and a POCO entity class for ad information.

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.csContosoAdsCommon - ContosoAdsContext.cs

ContosoAdsContext 类指定 DbSet 集合中使用的 Ad 类,实体框架将存储在 SQL 数据库中。The ContosoAdsContext class specifies that the Ad class is used in a DbSet collection, which Entity Framework will store in a SQL database.

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

类具有两个构造函数。The class has two constructors. 其中第一个由 web 项目使用,并指定存储在 Web.config 文件中的连接字符串的名称。The first of them is used by the web project, and specifies the name of a connection string that is stored in the Web.config file. 第二个构造函数用于传入辅助角色项目所使用的实际连接字符串,因为没有 Web.config 文件。The second constructor enables you to pass in the actual connection string used by the worker role project, since it doesn't have a Web.config file. 之前看到存储此连接字符串的位置,稍后会看到在实例化 DbContext 类时代码如何检索连接字符串。You saw earlier where this connection string was stored, and you'll see later how the code retrieves the connection string when it instantiates the DbContext class.

ContosoAdsWeb - Global.asax.csContosoAdsWeb - Global.asax.cs

Application_Start 方法调用的代码创建图像 Blob 容器和图像队列(如果它们尚不存在)。Code that is called from the Application_Start method creates an images blob container and an images queue if they don't already exist. 这确保只要开始使用新的存储帐户,或在新的计算机上开始使用存储模拟器,就自动创建所需的 Blob 容器和队列。This ensures that whenever you start using a new storage account, or start using the storage emulator on a new computer, the required blob container and queue will be created automatically.

此代码通过使用来自 .cscfg 文件的存储连接字符串获取存储帐户的访问权限。The code gets access to the storage account by using the storage connection string from the .cscfg file.

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

然后,它获取对图像 Blob 容器的引用,创建尚不存在的容器,并在新容器上设置访问权限。Then it gets a reference to the images blob container, creates the container if it doesn't already exist, and sets access permissions on the new container. 默认情况下,新容器只允许带存储帐户凭据的客户端访问 Blob。By default, new containers only allow clients with storage account credentials to access blobs. 网站需要 Blob 是公共的,以便它可以使用指向图像 Blob 的 Url 显示图像。The website needs the blobs to be public so that it can display images using URLs that point to the image blobs.

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

类似代码获取对 图像 队列的引用并创建一个新队列。Similar code gets a reference to the images queue and creates a new queue. 这种情况不需要权限更改。In this case, no permissions change is needed.

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

ContosoAdsWeb - _Layout.cshtmlContosoAdsWeb - _Layout.cshtml

_Layout.cshtml 文件设置页眉和页脚中的应用程序,并创建“广告”菜单项。The _Layout.cshtml file sets the app name in the header and footer, and creates an "Ads" menu entry.

ContosoAdsWeb - Views\Home\Index.cshtmlContosoAdsWeb - Views\Home\Index.cshtml

Views\Home\Index.cshtml 文件在主页上显示类别链接。The Views\Home\Index.cshtml file displays category links on the home page. 链接将查询字符串变量中的 Category 枚举的整数值传递到“广告索引”页面。The links pass the integer value of the Category enum in a querystring variable to the Ads Index page.

<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.csContosoAdsWeb - AdController.cs

AdController.cs 文件中,构造函数调用 InitializeStorage 方法来创建 Azure 存储客户端库对象,此类对象提供一个用于处理 Blob 和队列的 API。In the AdController.cs file, the constructor calls the InitializeStorage method to create Azure Storage Client Library objects that provide an API for working with blobs and queues.

然后,代码获取对图像 Blob 容器的引用,正如之前在 Global.asax.cs 中所见。Then the code gets a reference to the images blob container as you saw earlier in Global.asax.cs. 在执行该操作时,它设置适用于 Web 应用程序的默认 重试策略While doing that it sets a default retry policy appropriate for a web app. 对于超过暂时性故障反复重试超过一分钟的 Web 应用程序,默认指数回退重试策略将其可能挂起。The default exponential backoff retry policy could hang the web app for longer than a minute on repeated retries for a transient fault. 此处指定的重试策略将在每次尝试后等待三秒,最多可尝试三次。The retry policy specified here waits three seconds after each try for up to three tries.

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

类似代码获取对 图像 队列的引用。Similar code gets a reference to the images queue.

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

大部分控制器代码通常用于使用 DbContext 类的实体框架数据模型。Most of the controller code is typical for working with an Entity Framework data model using a DbContext class. 例外情况是 HttpPost Create 方法,它上传文件并将其保存在 Blob 存储中。An exception is the HttpPost Create method, which uploads a file and saves it in blob storage. 模型联编程序为该方法提供一个 HttpPostedFileBase 对象。The model binder provides an HttpPostedFileBase object to the method.

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

如果用户选择要上传的文件,则代码上传该文件,将其保存在 Blob 中,并使用指向 Blob 的 URL 更新广告数据库记录。If the user selected a file to upload, the code uploads the file, saves it in a blob, and updates the Ad database record with a URL that points to the blob.

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

执行上载的代码位于 UploadAndSaveBlobAsync 方法中。The code that does the upload is in the UploadAndSaveBlobAsync method. 它将创建 Blob 的 GUID 名称,上传和保存该文件,并将引用返回已保存的 Blob。It creates a GUID name for the blob, uploads and saves the file, and returns a reference to the saved 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 并更新数据库,它会创建队列消息,以通知后端进程图像已准备好转换为一个缩略图。After the HttpPost Create method uploads a blob and updates the database, it creates a queue message to inform that back-end process that an image is ready for conversion to a thumbnail.

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

HttpPost Edit 方法的代码和它类似,不同之处在于如果用户选择新图像文件,则必须删除已存在的任何 blob。The code for the HttpPost Edit method is similar except that if the user selects a new image file any blobs that already exist must be deleted.

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

以下示例演示了删除广告时删除 Blob 的代码:The next example shows the code that deletes blobs when you delete an ad.

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.cshtmlContosoAdsWeb - Views\Ad\Index.cshtml and Details.cshtml

Index.cshtml 文件显示带有其他广告数据的缩略图。The Index.cshtml file displays thumbnails with the other ad data.

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

Details.cshtml 文件显示完全尺寸的图像。The Details.cshtml file displays the full-size image.

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

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

Create.cshtmlEdit.cshtml 文件指定窗体编码,允许控制器获取 HttpPostedFileBase 对象。The Create.cshtml and Edit.cshtml files specify form encoding that enables the controller to get the HttpPostedFileBase object.

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

<input> 元素通知浏览器提供文件选择对话框。An <input> element tells the browser to provide a file selection dialog.

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

ContosoAdsWorker - WorkerRole.cs - OnStart 方法ContosoAdsWorker - WorkerRole.cs - OnStart method

Azure 辅助角色环境在辅助角色启动时调用 WorkerRole 类中的 OnStart 方法,并且它在 OnStart 方法结束时调用 Run 方法。The Azure worker role environment calls the OnStart method in the WorkerRole class when the worker role is getting started, and it calls the Run method when the OnStart method finishes.

OnStart 方法从 .cscfg 文件获取数据库连接字符串,并将其传递给实体框架 DbContext 类。The OnStart method gets the database connection string from the .cscfg file and passes it to the Entity Framework DbContext class. 在默认情况下使用 SQLClient 提供程序,因此不需要指定提供程序。The SQLClient provider is used by default, so the provider does not have to be specified.

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

之后,该方法获取对存储帐户的引用,并创建 Blob 容器和队列(如果它们不存在)。After that, the method gets a reference to the storage account and creates the blob container and queue if they don't exist. 此代码类似于已在 web 角色 Application_Start 方法中看到的内容。The code for that is similar to what you already saw in the web role Application_Start method.

ContosoAdsWorker - WorkerRole.cs - Run methodContosoAdsWorker - WorkerRole.cs - Run method

Run 方法完成其初始化工作时调用 OnStart 方法。The Run method is called when the OnStart method finishes its initialization work. 该方法执行监视新队列消息的一个无限循环,并在它们到达时进行处理。The method executes an infinite loop that watches for new queue messages and processes them when they arrive.

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);
        }
    }
}

循环每次迭代后,如果不找到任何队列消息,该程序休眠一秒钟。After each iteration of the loop, if no queue message was found, the program sleeps for a second. 此举防止辅助角色导致过多的 CPU 时间和存储事务成本。This prevents the worker role from incurring excessive CPU time and storage transaction costs. Microsoft 客户顾问团队讲过一个故事,一位开发人员忘记此操作,部署到生产环境,并去度假了。The Microsoft Customer Advisory Team tells a story about a developer who forgot to include this, deployed to production, and left for vacation. 当他们回来时, 其监管成本将大于休假。When they got back, their oversight cost more than the vacation.

有时队列消息的内容会在处理过程中导致错误。Sometimes the content of a queue message causes an error in processing. 这称为 有害消息,并且如果只记录了一个错误并重启循环,则可能无休止地尝试处理该消息。This is called a poison message, and if you just logged an error and restarted the loop, you could endlessly try to process that message. 因此,捕获块包括 if 语句检查应用程序尝试处理当前消息的次数,如果已超过 5 次,将从队列中删除该消息。Therefore the catch block includes an if statement that checks to see how many times the app has tried to process the current message, and if it has been more than 5 times, the message is deleted from the queue.

ProcessQueueMessageProcessQueueMessage is called when a queue message is found.

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 更新数据库并删除队列消息。This code reads the database to get the image URL, converts the image to a thumbnail, saves the thumbnail in a blob, updates the database with the thumbnail blob URL, and deletes the queue message.

备注

为简单起见,ConvertImageToThumbnailJPG 方法中的代码使用 System.Drawing 命名空间中的类。The code in the ConvertImageToThumbnailJPG method uses classes in the System.Drawing namespace for simplicity. 但是,此命名空间中的类已设计用于 Windows 窗体。However, the classes in this namespace were designed for use with Windows Forms. 不支持在 Windows 或 ASP.NET 服务中使用。They are not supported for use in a Windows or ASP.NET service. 有关图像处理选项的详细信息,请参阅动态图像生成深入学习图像大小调整For more information about image-processing options, see Dynamic Image Generation and Deep Inside Image Resizing.

疑难解答Troubleshooting

按本教程中的说明操作时,如果出现异常现象,请参考如下常见错误信息和解决方法。In case something doesn't work while you're following the instructions in this tutorial, here are some common errors and how to resolve them.

ServiceRuntime.RoleEnvironmentExceptionServiceRuntime.RoleEnvironmentException

在 Azure 中运行应用程序或使用 Azure 计算模拟器本地运行时, RoleEnvironment 对象由 Azure 提供。The RoleEnvironment object is provided by Azure when you run an application in Azure or when you run locally using the Azure compute emulator. 如果在本地运行时收到此错误,请确保已将 ContosoAdsCloudService 项目设为启动项目。If you get this error when you're running locally, make sure that you have set the ContosoAdsCloudService project as the startup project. 这会项目设置为使用 Azure 计算仿真程序运行。This sets up the project to run using the Azure compute emulator.

应用程序使用 Azure RoleEnvironment 的内容之一是获取 .cscfg 文件中存储的连接字符串值,所以此异常的另一个原因是丢失连接字符串。One of the things the application uses the Azure RoleEnvironment for is to get the connection string values that are stored in the .cscfg files, so another cause of this exception is a missing connection string. 确保在 ContosoAdsWeb 项目中为云和本地配置创建 StorageConnectionString 设置,并且可在 ContosoAdsWorker 项目中为两个配置创建两个连接字符串。Make sure that you created the StorageConnectionString setting for both Cloud and Local configurations in the ContosoAdsWeb project, and that you created both connection strings for both configurations in the ContosoAdsWorker project. 如果为整个解决方案中的 StorageConnectionString 进行 查找全部 搜索,应在 6 个文件中看到它 9 次。If you do a Find All search for StorageConnectionString in the entire solution, you should see it 9 times in 6 files.

无法重写到端口 xxx。Cannot override to port xxx. 低于最小允许值 8080 的新端口用于 http 协议New port below minimum allowed value 8080 for protocol http

请尝试更改 web 项目使用的端口号。Try changing the port number used by the web project. 右键单击 ContosoAdsWeb 项目,并单击“属性”。Right-click the ContosoAdsWeb project, and then click Properties. 单击“Web”选项卡,并更改“项目 Url”设置中的端口号。Click the Web tab, and then change the port number in the Project Url setting.

有关可能解决该问题的另一种方法,请参阅下一节。For another alternative that might resolve the problem, see the following section.

在本地运行时出现其他错误Other errors when running locally

默认情况下新的云服务项目使用 Azure 计算模拟器 express 版来模拟 Azure 环境。By default new cloud service projects use the Azure compute emulator express to simulate the Azure environment. 这是完整计算仿真程序的轻型版本,在某些情况下完整仿真程序会在没有 express 版时工作。This is a lightweight version of the full compute emulator, and under some conditions the full emulator will work when the express version does not.

要更改项目以使用完整模拟器,请右键单击 ContosoAdsCloudService 项目中,并单击“属性”。To change the project to use the full emulator, right-click the ContosoAdsCloudService project, and then click Properties. 在“属性”窗口中,单击“Web”选项卡,并单击“使用完整模拟器”单选按钮。In the Properties window click the Web tab, and then click the Use Full Emulator radio button.

要使用完整仿真程序运行该应用程序,必须使用管理员权限打开 Visual Studio。In order to run the application with the full emulator, you have to open Visual Studio with administrator privileges.

后续步骤Next steps

Contoso 广告应用程序有意保持入门教程的简单性。The Contoso Ads application has intentionally been kept simple for a getting-started tutorial. 例如,它没有实施依赖关系注入存储库和单元的工作模式,它不使用日志记录接口,它不使用 EF Code First 迁移来管理数据模型更改,或使用 EF 连接复原管理暂时性的网络错误等。For example, it doesn't implement dependency injection or the repository and unit of work patterns, it doesn't use an interface for logging, it doesn't use EF Code First Migrations to manage data model changes or EF Connection Resiliency to manage transient network errors, and so forth.

下面是演示更实际编码方法的一些云服务示例应用程序,从不太复杂到更复杂排列:Here are some cloud service sample applications that demonstrate more real-world coding practices, listed from less complex to more complex:

有关云开发的常规信息,请参阅 使用 Azure 生成实际的云应用For general information about developing for the cloud, see Building Real-World Cloud Apps with Azure.

有关 Azure 存储最佳实践和模式的视频介绍,请参阅 Microsoft Azure 存储 – 新增功能、最佳实践和模式For a video introduction to Azure Storage best practices and patterns, see Microsoft Azure Storage – What's New, Best Practices and Patterns.

有关详细信息,请参阅以下资源:For more information, see the following resources: