共用方式為


主版頁面中的 URL (C#)

作者:Scott Mitchell

下載 PDF

說明主版頁面中的 URL 如何因主版頁面檔案位於與內容頁面不同的相對目錄中而中斷。 在宣告式語法中查看透過 ~ 重新處理URL,並以程序設計方式使用 ResolveUrl 和 ResolveClientUrl。 (也查看

簡介

到目前為止,我們在所有範例中,主版和內容頁面都位於網站根資料夾 () 相同的資料夾中。 但是,主版和內容頁面必須位於相同的資料夾中,並無任何原因。 您當然可以在子資料夾中建立內容頁面。 同樣地,您可能會建立放置 ~/MasterPages/ 網站主版頁面的資料夾。

將主圖形和內容頁面放在不同資料夾中的其中一個潛在問題,包括中斷的URL。 如果主版頁面包含超連結、影像或其他元素中的相對 URL,則位於不同資料夾中的內容頁面連結將會無效。 在本教學課程中,我們會檢查此問題的來源以及因應措施。

相對 URL 的問題

如果指向的資源位置相對於網站資料夾結構中的網頁位置,則網頁上的 URL稱為相對URL 。 任何開頭為前置正斜線的 URL () / 或通訊協定 (,例如 http://) 相對,因為瀏覽器會根據包含 URL 的網頁位置加以解析。

例如,我們的網站有一個資料夾,其中包含單一 ~/Images/ 圖像檔案 PoweredByASPNET.gif。 主版頁面檔案Site.master在區域中具有<img>footerContent下列標記的專案:

<div id="footerContent">
 <img src="Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
</div>

專案中 src<img> 屬性值是相對 URL,因為它不是以 /http://開頭。 簡單地說src,屬性值會告訴瀏覽器查看名為 PoweredByASPNET.gifImages檔案子資料夾。

瀏覽內容頁面時,上述標記會直接傳送至瀏覽器。 請花點時間流覽 About.aspx 並檢視傳送至瀏覽器的 HTML 來源。 您會發現主版頁面中完全相同的標記已傳送至瀏覽器。

<div id="footerContent">
 <img src="Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
</div>

如果內容頁面位於根資料夾中 () About.aspx 所有專案如預期般運作,因為根 Images 資料夾有相對於根資料夾的子資料夾。 不過,如果內容頁面位於與主版頁面不同的資料夾中,則會細分專案。 為了說明這點,請建立名為 的 Admin子資料夾。 接下來,將名為 Default.aspx 的內容頁面新增至 Admin 資料夾,請務必將新頁面系結至 Site.master 主版頁面。

注意

在 [ 指定主版頁面] 中的 [標題]、[中繼卷標] 和其他 HTML 標頭教學課程中 ,我們建立了名為 BasePage 的自定義基頁類別,該類別會在未明確指派內容頁面時自動設定內容頁面的標題 () 。 別忘了讓新建立的頁面程序代碼後置類別衍生自 BasePage ,以便利用這項功能。

建立此內容頁面之後,您的 方案總管 看起來應該類似圖 1。

已將新資料夾和 ASP.NET 頁面新增至專案

圖 01:已將新資料夾和 ASP.NET 頁面新增至專案

接下來,更新 檔案 Web.sitemap 以包含本課程的新 <siteMapNode> 專案。 下列 XML 顯示完整的 Web.sitemap 標記,現在包含第三 <siteMapNode> 個專案的新增。

<?xml version="1.0" encoding="utf-8" ?>
<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >
 <siteMapNode url="~/Default.aspx" title="Home">
 <siteMapNode url="~/About.aspx" title="About the Author" />
 <siteMapNode url="~/MultipleContentPlaceHolders.aspx" title="Using Multiple ContentPlaceHolder Controls" />
 <siteMapNode url="~/Admin/Default.aspx" title="Rebasing URLs" />
 </siteMapNode>
</siteMap>

新建立 Default.aspx 的頁面應該有四個對應至 中 Site.master四個 ContentPlaceHolders 的內容控件。 將一些文字新增至參考 ContentPlaceHolder 的內容控件, MainContent 然後瀏覽網頁瀏覽瀏覽器。 如圖 2 所示,瀏覽器找不到 PoweredByASPNET.gif 影像檔。 這其中發生了什麼狀況?

內容 ~/Admin/Default.aspx 頁面會傳送與頁面相同的 HTML footerContentAbout.aspx

<div id="footerContent">
 <img src="Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
</div>

因為元素 <img> 的屬性 src 是相對 URL,所以瀏覽器會嘗試尋找 Images 相對於網頁資料夾位置的資料夾。 換句話說,瀏覽器正在尋找影像檔 Admin/Images/PoweredByASPNET.gif

找不到 PoweredByASPNET.gif 影像檔

圖 02PoweredByASPNET.gif 按下即可 檢視大小完整的影像 () 找不到影像檔

以絕對 URL 取代相對 URL

相對 URL 的相反是 絕對 URL,其開頭為正斜線 () / 或通訊協定,例如 http://。 因為絕對 URL 會從已知的固定點指定資源的位置,所以不論網站資料夾結構中的網頁位置為何,相同的絕對 URL 在任何網頁中都有效。

若要補救圖 2 所示的中斷影像,我們需要更新 <img> 元素的 src 屬性,使其使用絕對 URL 而不是相對 URL。 若要判斷正確的絕對 URL,請瀏覽網站中的其中一個網頁,並檢查網址列。 如圖 2 所示的網址列,Web 應用程式的完整路徑為 http://localhost:3908/ASPNET_MasterPages_Tutorial_04_CS/。 因此,我們可以將元素的 src 屬性更新<img>為下列兩個絕對 URL 的其中一個:

  • /ASPNET_MasterPages_Tutorial_04_CS/Images/PoweredByASPNET.gif
  • http://localhost:3908/ASPNET_MasterPages_Tutorial_04_CS/Images/PoweredByASPNET.gif

請花點時間使用上述其中一個窗體,將元素的 src 屬性更新<img>為絕對 URL,然後透過瀏覽器瀏覽~/Admin/Default.aspx頁面。 這次瀏覽器會正確尋找並顯示 PoweredByASPNET.gif 圖像檔, (請參閱圖 3) 。

現在會顯示 PoweredByASPNET.gif 影像

圖 03:影像 PoweredByASPNET.gif 現在會顯示 (按鍵即可檢視大小完整的影像)

雖然絕對 URL 中的硬式編碼運作正常,但會將 HTML 緊密結合至網站的伺服器和資料夾位置,這可能會變更。 因為每次啟動 Visual Studio 的內建 ASP.NET 開發網頁伺服器時,都會自動選取先前localhost的埠號碼,所以使用表單http://localhost:3908/...的絕對 URL 會很弱點。 同樣地,只有在本機測試時,元件 http://localhost 才有效。 將程式代碼部署至生產伺服器之後,URL 基底會變更為其他專案,例如 http://www.yourserver.com。 表單 /ASPNET_MasterPages_Tutorial_04_CS/... 中的絕對 URL 也會受到相同的嚴重性影響,因為此應用程式路徑在開發和生產伺服器之間通常會有所不同。

好消息是,ASP.NET 提供在運行時間產生有效相對 URL 的方法。

使用~ResolveClientUrl

ASP.NET 可讓頁面開發人員使用波浪 () ~ 來表示 Web 應用程式的根目錄,而不是硬式編碼絕對 URL。 例如,稍早在本教學課程中,我使用了文字中的表示法 ~/Admin/Default.aspx 來參考 Default.aspx 資料夾中的頁面 Admin~表示Admin資料夾是 Web 應用程式根目錄的子資料夾。

類別Control的 方法會採用 URL,並將它修改為適用於控件所在網頁的相對 ResolveClientUrl URL。 例如,從呼叫 ResolveClientUrl("~/Images/PoweredByASPNET.gif") 會傳About.aspxImages/PoweredByASPNET.gif回 。 不過,從 ~/Admin/Default.aspx呼叫它會傳 ../Images/PoweredByASPNET.gif回 。

注意

因為所有 ASP.NET 伺服器控制件都衍生自 Control 類別,所以所有伺服器控制項都可以存取 ResolveClientUrl 方法。 Page即使類別衍生自 Control 類別,這表示您可以直接從 ASP.NET 頁面的程式代碼後置類別使用此方法。

~宣告式標記中使用

有數個 ASP.NET Web 控制項包括 URL 相關屬性:HyperLink 控制件具有 NavigateUrl 屬性、影像控制件具有 ImageUrl 屬性等等。 轉譯時,這些控制項會將其 URL 相關屬性值傳遞至 ResolveClientUrl。 因此,如果這些屬性包含 ~ 來指出 Web 應用程式的根目錄,URL 將會修改為有效的相對 URL。

請記住,只有 ASP.NET 伺服器控制件在其網址相關屬性中轉換 ~~如果 出現在靜態 HTML 標記中,例如 <img src="~/Images/PoweredByASPNET.gif" />,ASP.NET 引擎會將 傳送~至瀏覽器,以及其餘的 HTML 內容。 瀏覽器假設 ~ 是 URL 的一部分。 例如,如果瀏覽器收到標記 <img src="~/Images/PoweredByASPNET.gif" /> ,則其假設有名為 ~ 的子資料夾,其子資料夾 Images 包含影像檔 PoweredByASPNET.gif

若要修正 中的 Site.master影像標記,請將現有 <img> 元素取代為 ASP.NET Image Web 控件。 將 Image Web 控件的 ID 設定為 PoweredByImage、其 ImageUrl 屬性設定為 ~/Images/PoweredByASPNET.gif,並將其 AlternateText 屬性設定為 “Powered by ASP.NET!”

<div id="footerContent">
 <asp:Image ID="PoweredByImage" runat="server" ImageUrl="~/Images/PoweredByASPNET.gif" 
    AlternateText="Powered by ASP.NET!" />
</div>

對主版頁面進行這項變更之後,請再次重新流覽 ~/Admin/Default.aspx 頁面。 這次 PoweredByASPNET.gif 影像檔會出現在頁面中, (請參閱圖 3) 。 當影像 Web 控件轉譯時,它會使用 ResolveClientUrl 方法來解析其 ImageUrl 屬性值。 ImageUrl在 中~/Admin/Default.aspx會轉換成適當的相對 URL,如下列 HTML 來源代碼段所示:

<div id="footerContent">
 <img id="ctl00_PoweredByImage" src="../Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
</div>

注意

除了用於 URL 型 Web 控制項屬性之外, ~ 也可以在呼叫 Response.RedirectServer.MapPath 方法時使用 。 此外, ResolveClientUrl 也可以直接從 ASP.NET 或主版頁面的宣告式標記叫用 方法。

修正主版頁面的剩餘相對 URL

除了我們剛才修正的 <img>footerContent 元素之外,主版頁面還包含一個需要注意的相對URL。 區域 topContent 包含指向的連結「主版頁面教學課程」 Default.aspx

<div id="topContent">
 <a href="Default.aspx">Master Pages Tutorials</a>
</div>

由於此 URL 是相對的,因此會將用戶傳送至 Default.aspx 他們瀏覽之內容頁面資料夾中的頁面。 若要讓此連結一律指向 Default.aspx 根資料夾中,我們需要將 元素取代 <a> 為 HyperLink Web 控制件,以便我們可以使用 ~ 表示法。

拿掉項目標記, <a> 並在其位置新增 HyperLink 控制件。 將 HyperLink 的 ID 設定為 lnkHome、其 NavigateUrl 屬性設定為 ~/Default.aspx,並將 屬性 Text 設定為 「主版頁面教學課程」。

<div id="topContent">
 <asp:HyperLink ID="lnkHome" runat="server" NavigateUrl="~/Default.aspx"
    Text="Master Pages Tutorials" />
</div>

就這麼簡單! 此時,不論主版頁面和內容頁面所在的資料夾為何,內容頁面轉譯時,主版頁面中的所有URL都會正確根據。

區段中的<head>自動 URL 解析

使用主版頁面建立 Site-Wide 版 面配置教學課程中,我們已將 新增 <link>Styles.css 區域中的 <head> 檔案:

<head runat="server">
 <title>Untitled Page</title>
 <asp:ContentPlaceHolder id="head" runat="server">
 </asp:ContentPlaceHolder>
 <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>

<link>雖然元素的 屬性是相對的href,但它會在運行時間自動轉換成適當的路徑。 如同我們在主版頁面教學課程中 指定標題、中繼標籤和其他 HTML 標頭 中所討論, <head> 區域實際上是伺服器端控件,可讓它在轉譯時修改其內部控件的內容。

若要確認這一點,請重新瀏覽 ~/Admin/Default.aspx 頁面,並檢視傳送至瀏覽器的 HTML 來源。 如下列代碼段所示,<link>元素的 href 屬性已自動修改為適當的相對 URL。 ../Styles.css

<head>
 <title>
 Default
 </title>
 <link href="../Styles.css" rel="stylesheet" type="text/css" />
</head>

摘要

主版頁面通常包含必須透過URL指定的連結、影像和其他外部資源。 因為主版頁面和內容頁面可能不存在於相同的資料夾中,所以請務必避免使用相對 URL。 雖然可以使用硬式編碼的絕對 URL,但這麼做會緊密結合 Web 應用程式的絕對 URL。 如果絕對 URL 變更 ,就像移動或部署 Web 應用程式時一樣,您必須記得返回並更新絕對 URL。

理想的方法是使用磚 (~) 來表示應用程式根目錄。 ASP.NET 包含 URL 相關屬性的 Web 控制件會在 ~ 執行時間對應至應用程式根目錄。 在內部,Web 控制項會使用 Control 類別的 ResolveClientUrl 方法來產生有效的相對 URL。 此方法是公用的,而且可從每個伺服器控制項取得, (包括 Page 類別) ,因此您可以視需要以程式設計方式從程式代碼後置類別使用它。

快樂的程序設計!

深入閱讀

如需本教學課程中所討論之主題的詳細資訊,請參閱下列資源:

關於作者

Scott Mitchell 是多個 ASP/ASP.NET 書籍的作者,以及 4GuysFromRolla.com 的建立者,自 1998 年起就與 Microsoft Web 技術合作。 Scott 是獨立的顧問、訓練者和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 3.5。 Scott 可以透過 mitchell@4GuysFromRolla.com 在 上的部落格或透過 http://ScottOnWriting.NET其部落格來連線。

特別感謝

想要檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行放在 mitchell@4GuysFromRolla.com