使用 Web Deploy 讓 Web 應用程式離線
演講者:Jason Lee
本主題說明如何使用 Internet 資訊服務 (IIS) Web 部署工具 (Web 部署) 在自動部署期間將 Web 應用程式離線。 瀏覽到 Web 應用程式的使用者將重新導向到 App_offline.htm 檔案,直到部署完成。
本主題圍繞著一家名為 Fabrikam, Inc. 的虛構公司展開,針對其企業部署需求而設計了一系列教學課程。本教學課程系列使用範例解決方案 (連絡人管理員解決方案) 來代表具有現實複雜性的 Web 應用程式,其中包括 ASP.NET MVC 3 應用程式、Windows Communication Foundation (WCF) 服務,和資料庫專案。
這些教學課程的核心部署方法是根據「了解專案檔案」中所述的分割專案檔案方法,其中建置程序由兩個專案檔案控制,一個包含適用於所有目標環境的建置指令,另一個則包含環境專屬的建置和部署設定。 在建置時,環境專屬的專案檔案被合併到與環境無關的專案檔案中,以形成完整的建置指令集。
任務概述
在許多情況下,您需要在變更相關元件 (例如資料庫或 Web 服務) 時將 Web 應用程式離線。 通常,在 IIS 和 ASP.NET 中,您可以透過將名為 App_offline.htm 的檔案放置在 IIS 網站或 web 應用程式的根資料夾中來實現這一點。 App_offline.htm 檔案是標準 HTML 文件,通常包含一則簡單訊息,通知使用者網站因維護而暫時無法使用。 雖然 App_offline.htm 檔案存在於網站的根資料夾中,但 IIS 會自動將任何請求重新導向到該檔案。 完成更新後,刪除 App_offline.htm 檔案,網站將恢復照常處理請求。
當您使用 Web Deploy 進行自動化或單一步驟部署到目標環境時,您可能希望將新增和移除 App_offline.htm 檔案的步驟納入您的部署過程中。 若要這樣做,您需要完成以下進階任務:
- 在用於控制部署過程的 Microsoft Build Engine (MSBuild) 專案檔案中,建立一個 MSBuild 目標,該目標在任何部署任務開始之前將 App_offline.htm 檔案複製到目標伺服器。
- 新增另一個 MSBuild 目標,該目標在所有部署任務完成後從目標伺服器中移除 App_offline.htm 檔案。
- 在 Web 應用程式專案中,建立一個 .wpp.targets 檔案,以確保在叫用 Web Deploy 時將 App_offline.htm 檔案新增至部署套件。
本主題將示範如何執行這些程序。 本主題中的任務和演練假定您已經建立了一個至少包含一個 Web 應用程式專案的解決方案,並且您使用自訂專案文件來控制部署流程,如「企業中的 Web 部署」中所述。 或者,您可以使用 Contact Manager 範例解決方案來跟著本主題中的範例執行。
將 App_Offline 檔案新增至 Web 應用程式專案
您需要完成的第一個任務是將 App_offline 檔案新增至您的 Web 應用程式專案:
- 為了防止該檔案干擾開發程序 (您不會希望應用程式永久離線),您應該將其命名為 App_offline.htm 以外的名稱。 例如,您可以將檔案命名為 App_offline-template.htm。
- 為了防止檔案按原樣部署,您應該將建置動作設為無。
將 App_offline 檔案新增至 Web 應用程式專案
在 Visual Studio 2010 中開啟您的解決方案。
在「方案總管」視窗中,以滑鼠以滑鼠右鍵按一下您的 Web 應用程式專案,指向「新增」,然後按一下「新項目」。
在「新增項目」對話方塊中,選擇「HTML 頁面」。
在「名稱」方塊中,鍵入 App_offline-template.htm,然後按一下「新增」。
新增一些簡單的 HTML 來通知使用者該應用程式不可用,然後儲存檔案。 請勿包含任何伺服器端標記 (例如,任何帶有「asp:」首碼的標記)。
在「方案總管」視窗中,以滑鼠以滑鼠右鍵按一下新檔案,然後按一下「屬性」。
在「屬性」視窗的「建置動作」行中,選擇「無」。
部署和刪除App_Offline文件
下一步是修改部署邏輯,以便在部署程序開始時將檔案複製到目標伺服器,並在結束時將其刪除。
注意
下一個程序假設您使用自訂 MSBuild 專案檔案來控制部署流程,如「了解專案檔案」中所述。 如果直接從 Visual Studio 進行部署,則需要使用不同的方法。 Sayed Ibrahim Hashimi 在「如何在發佈期間將您的網路應用程式設定為離線」中說明了這類方法。
若要將 App_offline 檔案部署到目標 IIS 網站,您需要使用 Web Deploy contentPath 提供者呼叫 MSDeploy.exe。 contentPath 提供者支援實體目錄路徑和 IIS 網站或應用程式路徑,這使其成為在 Visual Studio 專案資料夾和 IIS Web 應用程式之間同步檔案的理想選擇。 若要部署檔案,您的 MSDeploy 命令應該會像這樣:
msdeploy.exe –verb:sync
-source:contentPath="[Project folder]\App_offline.template.htm"
-dest:contentPath="[IIS application path]/App_offline.htm",
computerName="[Destination web server]"
要在部署程序結束時從目標網站刪除文件,您的 MSDeploy 命令應該會像這樣:
msdeploy.exe –verb:delete
-dest:contentPath="[IIS application path]/App_offline.htm",
computerName="[Destination web server]"
要在產生和部署程序中自動執行這些命令,您需要將它們整合到自訂 MSBuild 專案文件中。 下一個程序描述如何執行此操作。
若要部署和刪除 App_offline 檔案
在 Visual Studio 2010 中,開啟控制部署程序的 MSBuild 專案檔。 在「連絡人管理員」範例解決方案中,這是 Publish.proj 檔案。
在根 Project 元素中,建立一個新的 PropertyGroup 元素來儲存 App_offline 部署的變數:
<PropertyGroup> <AppOfflineTemplateFilename Condition=" '$(AppOfflineTemplateFilename)'=='' "> app_offline-template.htm </AppOfflineTemplateFilename> <AppOfflineSourcePath Condition=" '$(AppOfflineSourcePath)'==''"> $(SourceRoot)ContactManager.Mvc\$(AppOfflineTemplateFilename) </AppOfflineSourcePath> </PropertyGroup>
SourceRoot 屬性在 Publish.proj 檔案中的其他位置定義。 它指示來源內容的根資料夾相對於目前路徑的位置,換句話說,相對於 Publish.proj 檔案的位置。
contentPath 提供者不接受相對檔案路徑,因此您需要先取得來源檔案的絕對路徑,然後才能部署它。 您可以使用 ConvertToAbsolutePath 任務來執行此操作。
新增一個名為 GetAppOfflineAbsolutePath 的新 Target 元素。 在此目標中,使用 ConvertToAbsolutePath 任務來取得專案資料夾中 App_offline-template 檔案的絕對路徑。
<Target Name="GetAppOfflineAbsolutePath" BeforeTargets="DeployAppOffline"> <ConvertToAbsolutePath Paths="$(AppOfflineSourcePath)"> <Output TaskParameter="AbsolutePaths" PropertyName="AppOfflineAbsoluteSourcePath" /> </ConvertToAbsolutePath> </Target>
此目標採用專案資料夾中 App_offline-template 檔案的相對路徑,並將其儲存為絕對檔案路徑至新屬性。 BeforeTargets 屬性指定您希望此目標在您將在下一個步驟中建立的 DeployAppOffline 目標之前執行。
新增名為 DeployAppOffline 的新目標。 在此目標中,呼叫 MSDeploy.exe 指令將 App_offline 檔案部署到目標 Web 伺服器。
<Target Name="DeployAppOffline" Condition=" '$(EnableAppOffline'!='false' "> <PropertyGroup> <_Cmd>"$(MSDeployPath)\msdeploy.exe" -verb:sync -source:contentPath="$(AppOfflineAbsoluteSourcePath)" -dest:contentPath="$(ContactManagerIisPath)/App_offline.htm", computerName="$(MSDeployComputerName)" </_Cmd> </PropertyGroup> <Exec Command="$(_Cmd)"/> </Target>
在此範例中,ContactManagerIisPath 屬性在專案檔案的其他位置定義。 這只是一個 IIS 應用程式路徑,格式為 [IIS 網站名稱]/[應用程式名稱]。 透過在目標中包含條件,使用者可以透過更改屬性值或提供命令列參數來開啟或關閉 App_offline 部署。
新增一個名為 DeleteAppOffline 的新目標。 在此目標中,呼叫 MSDeploy.exe 命令從目標 Web 伺服器中移除 App_offline 檔案。
<Target Name="DeleteAppOffline" Condition=" '$(EnableAppOffline'!='false' "> <PropertyGroup> <_Cmd>"$(MSDeployPath)\msdeploy.exe" -verb:delete -dest:contentPath="$(ContactManagerIisPath)/App_offline.htm", computerName="$(MSDeployComputerName)" </_Cmd> </PropertyGroup> <Exec Command="$(_Cmd)"/> </Target>
最後的任務是在專案文件執行期間的適當時刻呼叫這些新目標。 您可以透過多種方式做到這一點。 例如,在 Publish.proj 檔案中,FullPublishDependsOn 屬性指定在叫用 FullPublish 預設目標時必須依序執行的目標清單。
修改 MSBuild 專案檔案以在發佈程序中的適當時刻叫用 DeployAppOffline 和 DeleteAppOffline 目標。
<PropertyGroup> <FullPublishDependsOn> Clean; BuildProjects; DeployAppOffline; GatherPackagesForPublishing; PublishDbPackages; DeployTestDBPermissions; PublishWebPackages; DeleteAppOffline; </FullPublishDependsOn> </PropertyGroup> <Target Name="FullPublish" DependsOnTargets="$(FullPublishDependsOn)" />
當您執行自訂 MSBuild 專案檔案時,App_offline 檔案將在成功產生後立即部署到伺服器。 所有部署任務完成後,它將從伺服器中刪除。
將 App_Offline 檔案新增至部署包
根據您設定部署的方式,當您將 Web 套件部署到目標時,目標 IIS Web 應用程式中的任何現有內容 (例如 App_offline.htm 檔案) 可能會自動刪除。 為了確保 App_offline.htm 檔案在部署期間保持不變,除了在部署過程開始時直接部署該檔案之外,您還需要將該檔案包含在 Web 部署套件本身中。
- 如果您已按照本主題中的前面的任務進行操作,您將已將 App_offline.htm 檔案以不同的檔案名稱新增至您的 Web 應用程式專案 (我們用的是 App_offline-template.htm),並且您將建置動作設定為「無」。 這些變更是必要的,以防止檔案干擾開發和偵錯。 因此,您需要自訂封裝流程,以確保 Web 部署套件中包含 App_offline.htm 檔案。
Web 發佈管線 (WPP) 使用名為 FilesForPackagingFromProject 的專案清單來建立應包含在 Web 部署套件中的檔案清單。 您可以透過將自己的項目新增至此清單來自訂 Web 套件的內容。 為此,您需要完成以下進階步驟:
在與專案檔案相同的資料夾中建立一個名為 [專案名稱].wpp.targets 的自訂專案檔案。
注意
.wpp.targets 檔案需要與您的Web 應用程式專案檔案位於相同資料夾中 (例如,ContactManager.Mvc.csproj),而不是與您用於控制建置和部署流程的任何自訂專案檔案位於相同資料夾中。
在 .wpp.targets 檔案中,建立一個新的 MSBuild 目標,該目標在 CopyAllFilesToSingleFolderForPackage 目標之前執行。 這是 WPP 目標,它建立要包含在套件中的內容清單。
在新目標中,建立一個 ItemGroup 元素。
在 ItemGroup 元素中,新增 FilesForPackagingFromProject 項目,並指定 App_offline.htm 檔案。
.wpp.targets 檔案應該會像這樣:
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="AddAppOfflineToPackage"
BeforeTargets="CopyAllFilesToSingleFolderForPackage">
<ItemGroup>
<FilesForPackagingFromProject Include="App_offline-template.htm">
<DestinationRelativePath>App_offline.htm</DestinationRelativePath>
</FilesForPackagingFromProject>
</ItemGroup>
</Target>
</Project>
以下是本例中需要注意的要點:
- BeforeTargets 屬性透過指定應在 CopyAllFilesToSingleFolderForPackage 目標之前立即執行來將此目標插入 WPP 中。
- 當檔案加入清單時,FilesForPackagingFromProject 項目使用 DestinationRelativePath 中繼資料值將檔案從 App_offline-template.htm 重新命名為 App_offline.htm。
下一個程序將示範如何將此 .wpp.targets 檔案新增至 Web 應用程式專案中。
要將 .wpp.targets 檔案新增至 Web 部署套件
在 Visual Studio 2010 中開啟您的解決方案。
在「方案總管」視窗中,以滑鼠以滑鼠右鍵按一下 Web 應用程式專案節點 (例如,ContactManager.Mvc),指向「新增」,然後按一下「新項目」。
在「新增項目」對話方塊中,選擇「XML 檔案」範本。
在「名稱」方塊中,鍵入 [項目名稱].wpp.targets (例如,ContactManager.Mvc.wpp.targets),然後按一下「新增」。
注意
如果將新專案新增至專案的根節點,則會在與專案檔案相同的資料夾中建立該檔案。 您可以透過在 Windows 資源管理器中開啟該資料夾來驗證這一點。
在該檔案中,新增前面所述的 MSBuild 標記。
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Target Name="AddAppOfflineToPackage" BeforeTargets="CopyAllFilesToSingleFolderForPackage"> <ItemGroup> <FilesForPackagingFromProject Include="App_offline-template.htm"> <DestinationRelativePath>App_offline.htm</DestinationRelativePath> </FilesForPackagingFromProject> </ItemGroup> </Target> </Project>
儲存並關閉 [專案名稱].wpp.targets 檔案。
下次建置並封裝 Web 應用程式專案時,WPP 將自動偵測 .wpp.targets 檔案。 App_offline-template.htm 檔案將作為 App_offline.htm 包含在產生的 Web 部署套件中。
注意
如果您的部署失敗,App_offline.htm 檔案將保留在原處,並且您的應用程式將保持離線狀態。 這通常是所需的行為。 若要讓您的應用程式重新連線,您可以從 Web 伺服器中刪除 App_offline.htm 檔案。 或者,如果您修正任何錯誤並成功執行部署,則將移除 App_offline.htm 檔案。
結論
本主題介紹如何在部署期間使 Web 應用程式離線,方法是在部署過程開始時將 App_offline.htm 檔案發佈到目標伺服器並在結束時將其刪除。 它也介紹如何將 App_offline.htm 檔案包含在 Web 部署套件中。
深入閱讀
有關封裝和部署程序的更多資訊,請參閱「建置和封裝 Web 應用程式專案」、「設定 Web 套件部署參數」和「部署 Web 套件」。
如果直接從 Visual Studio 發佈 Web 應用程式,而不是使用這些教學課程中描述的自訂 MSBuild 專案文件方法,則需要使用稍微不同的方法在發佈程序中使應用程式離線。