本文章是由機器翻譯。

Visual Studio

使用多個 Visual Studio 專案類型成功創建雲服務

Patrick Foley

下載代碼示例

您可能已經注意到,如今的 Visual Studio 中包含很多不同的專案類型。您選擇哪一種呢?所有類型都能在適當的情況下説明解決問題。即使是在一個業務問題中,也經常會出現多個用例,可以用不同的 Visual Studio 專案類型完美解決。

最近,在為我領導的一個雲計算專案構建基礎設施時,我就遇到了這樣的問題。這個專案的主題是介紹成功案例:Microsoft Solutions Advocates (microsoftsolutionsadvocates.com)。我使用了幾種不同的 Visual Studio 專案類型來構建我的解決方案,本文將簡要介紹我的這個專案“客戶成功案例”(CSS)。

CSS 有三個截然不同的用例:

  1. 匿名使用者在公共網站上閱讀成功案例。
  2. 參與這個計畫的使用者登錄專用的網站,創建和編輯他們自己的成功案例。
  3. 管理員(例如我)登錄管理網站,管理和編輯所有資料,包括查詢表等細節資訊。

我的解決方法綜合運用了三種 Microsoft .NET Framework 技術:

  1. ASP.NET MVC,用於公共網站
  2. WCF RIA 服務,用於專用的客戶可編輯網站
  3. ASP.NET 動態資料,用於管理網站

所有這些技術都可以單獨用來創建整個解決方案,但我更願意各取所長。首先,ASP.NET MVC 是創建隨處可用的公共網站的理想技術,因為它提供標準 HTML。公共網站有行銷作用,因此我最終將聘請一位設計師來改進外觀。與設計師合作增加了難度,但 ASP.NET MVC 具有直觀的視圖實現方式,因此很容易被設計師理解和運用。將網站指定為唯讀並與其他用例相分離,有助於清楚劃定設計師的參與範圍。

儘管 ASP.NET MVC 也可用來實現使用者編輯功能,但 WCF RIA 服務是更好的選擇。(相反,WCF RIA 服務可用來構建華麗的公共網站,但 Silverlight 在某些設備上不受支援,例如 iPhone 和 iPad,而我希望盡可能擴大公共用例的適用範圍。)Silverlight 仍然會用到,它非常適合創建豐富的編輯體驗,而且只需很少的程式設計,只要使用者擁有或安裝 Silverlight,就可以實現一個客戶協作網站的成功案例。

利用 ASP.NET 動態資料,無需大量工作即可方便地構建管理解決方案。管理網站不需要花哨的外表,它只需提供途徑去管理解決方案中的所有資料,而不必求助於 SQL Server Management Studio。隨著解決方案不斷深入,ASP.NET 動態資料網站無疑會包含在 WCF RIA 服務網站中。但是,它在以資料為中心的開發專案(例如我們的這個專案)的初始階段是很有用的,無需花費什麼精力即可構建。

面向 Windows Azure

再次說明,本示例基於實際的問題,而且因為解決方案需要公共網站,所以我打算利用 Windows Azure 和 SQL Azure。Windows Server 和 SQL Server 可能更為熟悉,但我需要利用在雲中運行的優勢(無需維護作業系統、應用修補程式等)。我僅僅是有時間構建 解決方案,肯定沒有時間來運營 它,因此必須使用 Windows Azure。

若要瞭解此示例並在 Windows Azure 上試用,您需要擁有帳戶。microsoft.com/windowsazure/offers 提供了多種選項和套裝程式。MSDN 訂閱者和 Microsoft 合作夥伴(包括 BizSpark 創業公司,詳情請訪問 bizspark.com)可以在幾個月內免費訪問資源。對於原型製作和學習(例如練習本示例),您可以使用“入門特惠”,其中包括使用三個月的 1GB SQL Azure 資料庫和 25 小時的 Windows Azure 小型計算實例,這些應該足夠您熟悉該平臺。我使用“入門特惠”構建了此示例,沒有花其他費用。

“客戶成功案例”概述

本示例以教程形式提供。實際實施中的幾個重要方面不在本文的討論範圍內,包括使用者級的安全、測試、與設計師合作以及超越極其簡化的模型。我將嘗試在以後的文章或我的博客 pfoley.com 上進行介紹。

各個步驟高度概括,並假定讀者熟悉 Visual Studio 和其中涉及的技術。整個解決方案的代碼可以從 code.msdn.microsoft.com/mag201101VSCloud 下載,每個步驟的詳細說明可以從 pfoley.com/mm2011jan 獲得。

步驟 1:為實體框架資料模型創建專案

本示例中使用的 Web 技術實際上都使用了實體框架,因此我選擇讓三個用例共用通用的實體框架模型,從而將這些用例集成在一起。使用現有的資料庫時,您必須從資料庫生成模型。只要有可能,我都傾向于先創建模型,再從模型生成資料庫,因為我更希望從模型的角度而不是資料庫的角度考慮我的設計。為簡化起見,本示例只使用了兩個實體:Company 和 Story。

實體框架模型將在其自己的專案中創建,並在多個專案間共用(我是從 Julie Lerman 那裡學到如何做的;詳情請參見 pfoley.com/mm2011jan01)。我將這樣的最佳做法稱為“秘密握手”,即第一次這麼做並不容易,而一旦掌握了訣竅,就簡單了:

  1. 在“類庫”專案中創建實體框架模型。
  2. 將連接字串複製到所有共用模型的專案中。
  3. 在所有共用模型的專案中添加對實體框架專案和 System.Data.Entity 的引用。

首先在 Visual Studio 2010 中創建一個名為“Customer Success Stories”的空白解決方案,然後添加名為“CSSModel”的類庫。刪除類檔,添加空的 ADO.NET 實體資料模型專案,名為“CSSModel”。添加 Company 和 Story 實體以及兩個實體間的關聯,如 圖 1 所示(當您按右鍵 Company 以添加關聯時,請確保在隨後的對話方塊中選中“為‘Person’實體添加外鍵屬性”,因為後面的步驟中要求使用外鍵屬性)。

圖 1 向 Visual Studio 專案中添加 Company 和 Story 實體

模型現在可以生成資料庫表了,但需要一個 SQL Azure 資料庫來放置這些表。原型製作完成並且專案推進時,可以添加一個本地 SQL Server 資料庫用於測試,但在這個時候,直接操作 SQL Azure 資料庫也不復雜。

從您的 SQL Azure 帳戶門戶,創建新的資料庫“CSSDB”並在“防火牆設置”選項卡上添加針對當前 IP 位址的規則以及“允許 Microsoft 服務訪問此伺服器”。您的 SQL Azure 帳戶門戶應該就像圖 2 所示。

圖 2 在 SQL Azure 門戶中配置設置

在 Visual Studio 中,按右鍵設計圖面並選擇“從模型生成資料庫”。添加指向新 SQL Azure 資料庫的連接,並完成嚮導。該嚮導將生成一些資料定義語言 (DDL) 並以 .sql 檔打開,如 圖 3 所示。.

图 3 生成数据库模型

在您可以執行 SQL 之前,您必須連接到 SQL Azure 資料庫(按一下 Transact-SQL 編輯器工具列上的“連接”按鈕)。SQL Azure 不支援“USE”語句,因此您必須從工具列上的“資料庫”下拉清單中選擇新的資料庫,然後執行 SQL。現在您有一個 SQL Azure 資料庫,可以在 Visual Studio 伺服器資源管理器、SQL Server Management Studio 或新的管理工具(Microsoft 專案代碼“Houston”)(sqlazurelabs.com/houston.aspx) 中查看它。一旦您構建解決方案,您就有一個實體框架專案,可以用來通過程式設計訪問該資料庫。

步驟 2:創建 ASP.NET 動態資料項目目

ASP.NET 動態資料網站提供了一種簡單方法用於處理資料庫中所有資料,並且建立了基線功能以確保整個環境均運行正常,所有這些只需一行代碼就能完成。

向解決方案中添加新的 ASP.NET 動態資料實體 Web 應用程式專案,並命名為“CSSAdmin”。若要使用第一步中記錄的資料模型,請從 CSSModel 中的 App.Config 將 connectionStrings 元素複製到 CSSAdmin 中的 web.config。將 CSSAdmin 設置為啟動專案,並添加對 CSSModel 專案和 System.Data.Entity 的引用。

使用 ASP.NET 動態資料項目目能實現很多有意思的功能,但只需取消注釋 Global.asax.cs 中的 RegisterContext 行並將其改為以下內容,就能實現預設行為:

DefaultModel.RegisterContext(typeof(CSSModel.CSSModelContainer), new ContextConfiguration() { ScaffoldAllTables = true });

生成並運行專案,現在您就擁有了一個基本網站,可以用來管理資料。添加一些測試資料,以確保所有功能均運行正常。

步驟 3:創建 Windows Azure 服務專案

執行上一步後得到一個本地網站,可以通過它訪問 SQL Azure 上的資料庫。下一步是讓這個網站在 Windows Azure 上運行。

從您的 Windows Azure 帳戶門戶,創建名為“CSS Storage”的存儲服務以及名為“CSS Service”的託管服務。您的 Windows Azure 帳戶門戶應該與 圖 4 類似。

圖 4 在 Windows Azure 門戶中創建服務

在 Visual Studio 中,向解決方案中添加新的 Windows Azure 雲服務專案,命名為“CSSAdminService”(您必須安裝 Windows Azure Tools for Visual Studio),但不要從嚮導中添加其他“雲服務解決方案”。雲服務專案提供了必要的基礎結構,方便您在用於開發和調試的本地版“雲構造”中運行應用程式。它還可以簡化以對話模式發佈到 Windows Azure 的過程。這對原型製作和簡單的 Windows Azure 解決方案都非常有利,但是一旦您要正式在 Windows Azure 上進行開發工作,您可能需要使用 Windows PowerShell 來進行腳本開發(連續的集成解決方案可能需要這項工作)。

按右鍵 CSSAdminService 中的 Roles 資料夾,然後選擇“添加”|“解決方案中的 Web 角色專案”以關聯 CSSAdmin 專案和雲服務專案。現在您可以編譯並運行解決方案,它將在開發結構中運行。此時,解決方案與在 IIS 或 Cassini 上運行並沒有什麼區別,但在開發結構上運行很重要,因為這樣可以找出錯誤,例如在開發 Windows Azure 解決方案時使用了不受支援的 Windows API。

按右鍵 CSSAdminService 專案並選擇“發佈”,以便部署到您的 Windows Azure 帳戶。第一次部署時,您需要添加憑據(按照說明將憑據複製到您的 Windows Azure 帳戶)。然後選擇“託管服務位置”和“存儲帳戶”來部署您的解決方案。託管服務位置有兩個選項:生產和分段測試。更新生產中的實際解決方案時,先進行分段測試部署可以確保一切正常,然後再將分段測試環境提升為生產環境。製作原型時,我傾向于直接部署到生產環境,因為我不打算讓解決方案運行。按一下“確定”部署到 Windows Azure,這要花費幾分鐘時間。完成之後,使用服務頁面上顯示的網站 URL 運行 Windows Azure 應用程式,如圖 5 所示。

圖 5 Windows Azure 部署的服務

驗證服務能夠運行之後,暫停並刪除 部署以避免收費(部署服務套裝程式後即按照使用情況計費,無論是否真正運行)。不要刪除服務本身,因為這樣會導致網站 URL 返回到可用 URL 清單中。很明顯,如果您準備啟動實際的生產解決方案,您必須制定預算以不間斷運行 Windows Azure 服務。

如果服務部署失敗,您不會得知具體 的錯誤之處。通常您甚至都不知道 出錯了。服務狀態呈現“正在初始化...忙碌...正在停止...正在初始化...”的迴圈。如果您遇到這種情況(肯定會遇到),請查找問題,例如正在嘗試訪問本地資源(可能是本地 SQL Server 資料庫)或引用 Windows Azure 上不存在的程式集。部署套裝程式時啟用 IntelliTrace(請參見圖 6)可以説明您通過查看引發的具體異常來找出問題。

圖 6 發佈到 Windows Azure 時啟用 IntelliTrace

步驟 4:創建 ASP.NET MVC 專案

到目前為止,解決方案中包含了在 Windows Azure 上運行的管理網站(雖然沒有使用者級的安全設置)以及對 SQL Azure 資料庫的訪問,所有功能都是通過一行代碼實現的。下一步是創建公共網站。

向解決方案中添加新的 ASP.NET MVC 2 Web 應用程式專案,命名為“CSSPublic”(練習本示例時不要創建單元測試專案)。如果您很熟悉 ASP.NET MVC,您可能希望從 ASP.NET MVC 2 空 Web 應用程式開始,但我更願意從可以直接使用的網站結構開始,然後逐步修改它,使之符合我的需要。

按右鍵 CSSPublic 將其設置為啟動專案,然後運行它以瞭解您的初始內容。CSS 的公共網站是唯讀和匿名的,因此按照以下步驟刪除所有登錄和帳戶功能:

  1. 從 Site.Master 中刪除“logindisplay”div。
  2. 從主 Web.config 中刪除 ApplicationServices 連接字串和身份驗證元素。
  3. 刪除 AccountController.cs、AccountModels.cs、LogOnUserControl.ascx 和“視圖”下的整個 Account 資料夾。
  4. 再次運行,確保一切正常。
  5. 將連接字串從 CSSModel App.Config 複製到 CSSPublic Web.config,然後像之前一樣添加對 CSSModel 和 System.Data.Entity 的引用。
  6. 選擇 CSSPublic 的所有引用,並將“複製本地”屬性設置為 True。

我認為有必要為 Companies 和 Stories 添加單獨的控制器(和相關的視圖),同時保持 Home 控制器作為登錄頁面。這些是很重要的決策。設計師可以美化網站,但資訊架構(網站的結構)必須首先正確無誤。

命名方式在模型視圖控制器 (MVC) 專案中很重要。使用複數形式的控制器名稱(Companies 而不是 Company)並匹配視圖資料夾。為控制器方法和視圖名稱使用 Index、Details 等標準約定。如果您確實需要,可以更改這些約定,但這會增加複雜性。

按右鍵 Controllers 資料夾以添加新的控制器“CompaniesController”。此網站不會實現任何行為(它是唯讀的),因此無需使用顯式模型類。將實體框架模型容器自身視為模型。在 CompaniesController.cs 中,添加“using CSSModel”並更改 Index 方法,以返回如下所示的公司清單:

CSSModelContainer db = new CSSModelContainer();
return View(db.Companies.ToList());

若要創建視圖,請在“視圖”下創建空的 Companies 資料夾,然後按右鍵該資料夾,以添加名為“Index”的視圖。將其嚴格設置為與 CSSModel.Company 的 View 資料類和 List 的視圖內容相同的類型。

在 Site.Master 中,在功能表中添加一個清單項以引用新的 Controller:

  <li><%: Html.ActionLink("Companies", "Index", "Companies")%></li>

運行應用程式,按一下功能表以查看 Companies 清單。 預設視圖是很好的起點,但要刪除不必要的“Id”欄位。 因為此網站要設置為唯讀的,所以刪除“Edit”、“Delete”和“Create”的 ActionLink 項。最後將公司名稱本身設置為指向 Details 視圖的連結:

  <%: Html.ActionLink(item.Name, "Details", new { id=item.Id })%>

您的 Companies 清單應該類似于圖 7 所示。

圖 7 ASP.NET MVC 網站中的 Companies 清單

若要實現 Details,請向 CompaniesController 中添加一個方法:

public ActionResult Details(int id)
{
  CSSModelContainer db = new CSSModelContainer();
  return View(db.Companies.Single(c => c.Id.Equals(id)));
}

Id 參數代表 URL 中 Companies\Details\ 後面的整數。該整數用於使用簡單的 LINQ 運算式查找相應的公司。

像之前一樣在 Companies 資料夾下添加 Details 視圖,但這次選擇“Details”作為視圖內容,並將視圖命名為“Details”。

運行專案,流覽到 Companies,然後按一下其中一個公司名稱,查看預設的 Details 視圖。

為 Stories 添加控制器和視圖與此類似。視圖在設計師接手之前還需要很多微調,但這是個好的開始,很容易向前推進。

若要驗證此專案能夠在 Windows Azure 上運行,請創建一個名為“CSSPublicService”的雲服務專案,並為其添加 CSSPublic 角色。在開發結構中本地運行該服務,然後將網站發佈到 Windows Azure,並從公共 URL 運行它。完成時不要忘了暫停和刪除部署,以避免計費。

步驟 5:創建 WCF RIA 服務專案

現在的解決方案中包含 ASP.NET MVC 和 ASP.NET 動態資料網站,運行在(或至少可以運行)在 Windows Azure 上,它們使用共用的實體框架模型訪問 SQL Azure 資料庫。只需非常少的探測代碼即可獲得相當數量的功能。添加 WCF RIA 服務網站又添加了另一個維度:豐富的編輯體驗。

添加一個名為“CSSCustomerEdit”(不含空格)的 Silverlight 業務應用程式專案,Visual Studio 將為您的解決方案添加兩個專案:一個 Silverlight 用戶端 (CSSCustomerEdit) 和一個 Web 服務 (CSSCustomerEdit.Web)。運行解決方案來看看您的初始內容。打開 CSSCustomerEdit 專案中的 ApplicationStrings.resx,將 ApplicationName 的值改為“Customer Success Stories”以便更醒目。

在 CSSCustomerEdit.Web 中,將 connectionStrings 從 CSSModel 複製到 Web.config 中,添加對 CSSModel 和 System.Data.Entity 的引用,並將所有引用的“複製本地”屬性設置為 True。然後按右鍵 Services 資料夾,添加新的域服務類項,命名為“CSSDomainService”。確保該類的名稱以 Service(沒有數位)結尾,這樣可以充分利用兩個專案之間的工具優勢(另一次“秘密握手”)。按一下“確定”以打開“添加新的域服務類”對話方塊,然後選中所有實體,並為每個實體選中“啟用編輯”(圖 8)。

图 8 添加域服务类

請注意“為中繼資料生成關聯的類”呈灰顯。這表示對我在這裡推薦的方法的一種折中。在 Silverlight 業務應用程式中,中繼資料類可用來添加更多驗證邏輯,例如範圍和顯示預設值。但是,當實體框架模型與 CSSCustomerEdit.Web 不在一個專案中時,工具包將不允許您添加這些中繼資料類。如果此功能對您很重要,或者您打算在解決方案的 Silverlight 業務應用程式部分投入大部分精力,您可能需要直接在“.Web”專案中創建實體框架模型,而不是在獨立的專案中創建。您應該引用 CSSCustomerEdit.Web 以共用另一個專案中的實體框架模型。

正如前文所述,身份驗證和授權不在本文的討論範圍內,但還是可以稍作講解。在 CSSDomainService 類中,添加一個名為“myCompany”的預留位置屬性,代表使用者獲得授權可以編輯的公司。從現在開始,將其硬編碼為 1,但最終登錄過程會將其設置為已通過身份驗證的使用者的正確公司。

編輯 CSSDomainService 類以反映專案的具體用例:使用者可以更新公司,但不能插入或刪除公司(管理員在 ASP.NET 動態資料網站中進行插入或刪除),因此刪除這些服務方法。另外,使用者只能編輯他們所在的公司,而不是公司清單,因此將 GetCompanies 改為 GetMyCompany。同樣,將 GetStories 更改為 GetMyStories,並確保創建案例的使用者的 CompanyId 等於 myCompany:

private int myCompany = 1; // TODO: set myCompany during authentication
public Company GetMyCompany()
{
  return this.ObjectContext.Companies.Single(c=>c.Id.Equals(myCompany));
}
...
public IQueryable<Story> GetMyStories()
{
  return this.ObjectContext.Stories.Where(s=>s.CompanyId.Equals(myCompany));
}

public void InsertStory(Story story)
{
  story.CompanyId = myCompany;
  story.Id = -1; // database will replace with next auto-increment value
  ...
}

WCF RIA 服務在創建可編輯的欄位式介面時很有用,但應該從最簡單的做起,逐步增加功能。DataGrid 和 DataForm 控制項很強大,但每次我的速度過快或嘗試一次性添加太多功能時,最終都會亂成一團,只得回溯。因此最好循序漸進地工作,一次進行一項 UI 改進。

若要實現此示例的基線 UI,請在 CSSCustomerEdit 中添加對 System.Windows.Controls.Data 和 System.Windows.Controls.DomainServices 的引用。為 Company(單數)和 Stories 創建新的視圖(Silverlight 頁面項),然後類比來自現有的 Home 和 About 視圖的 XAML。編輯 MainPage.xaml 以添加新的分隔符號和連結按鈕(或者只是指派現有的 Home 和 About 視圖用於 Company 和 Stories)。

在 Silverlight 開發中,很多有意思的地方都涉及編輯 XAML。在 CSSCustomerEdit 中,為 Company 視圖添加命名空間條目 DomainDataSource 和 DataForm。此外,為 Stories 視圖添加 DataGrid。在兩個 DataForm 中,處理 EditEnded 事件以調用 MyData.SubmitChanges.Stories.xaml,如圖 9 所示。

圖 9 Stories 視圖的 XAML

生成...運行...大功告成!豐富的編輯體驗已經有了,可以繼續發展充實(請參見圖 10)。

圖 10 運行中的 Stories 視圖

和以前一樣,創建一個新的雲服務專案,在 Windows Azure 上發佈並測試。將 CSSCustomerEditTestPage.aspx 複製到 Default.aspx 以實現更清晰的體驗,任務就完成了。

條條大路通羅馬

Visual Studio 和 .NET Framework 提供了無數的選擇,可以用來創建在 Windows Azure 上運行的解決方案。儘管探索“唯一”的方式來創建未來雲計算的殺手級應用程式很吸引人,其實利用多種技術的功能可以解決更為複雜的問題,收穫也更多。這樣做更容易編寫代碼,更容易深入開發,而且借助 Windows Azure 也更容易運營。

Patrick Foley 是 Microsoft 的 ISV 架構推廣人員,他的職責是説明軟體公司成功應用 Microsoft 平臺。可以在 pfoley.com 閱讀他的博客文章。

衷心感謝以下技術專家對本文的審閱: Hanu Kommalapati