主版頁面中的 URL (VB)

作者 :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 屬性值會告知瀏覽器在 Images 子資料夾中尋找名為 PoweredByASPNET.gif的檔案。

瀏覽內容頁面時,會將上述標記直接傳送至瀏覽器。 請花點時間流覽 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。 將一些文字新增至參考 MainContent ContentPlaceHolder 的內容控件,然後透過瀏覽器瀏覽頁面。 如圖 2 所示,瀏覽器找不到 PoweredByASPNET.gif 影像檔。 這其中發生了什麼狀況?

內容 ~/Admin/Default.aspx 頁面會傳送 footerContent 與頁面相同的 HTML 區域 About.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,也就是開頭為正斜線 () / 或通訊協定的 URL,例如 http://。 因為絕對 URL 會從已知的固定點指定資源的位置,所以不論網站資料夾結構中的網頁位置為何,相同的絕對 URL 在任何網頁中都有效。

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

  • /ASPNET_MasterPages_Tutorial_04_VB/Images/PoweredByASPNET.gif
  • http://localhost:3908/ASPNET_MasterPages_Tutorial_04_VB/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_VB/... 中的絕對 URL 也會受到相同的嚴重性影響,因為此應用程式路徑通常會在開發與生產伺服器之間有所不同。

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

使用~ResolveClientUrl

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

類別 ControlResolveClientUrl 方法 會採用 URL,並將它修改為適用於控件所在網頁的相對 URL。 例如,從 About.aspx 呼叫 ResolveClientUrl("~/Images/PoweredByASPNET.gif") 會傳Images/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 控件的 設定為 IDPoweredByImage、其 屬性設定為 ~/Images/PoweredByASPNET.gif,並將其 ImageUrlAlternateText 屬性設定為 “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) 。 轉譯 Image Web 控制件時,它會使用 ResolveClientUrl 方法來解析其 ImageUrl 屬性值。 在 中~/Admin/Default.aspxImageUrl會轉換成適當的相對 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 的 設定為 IDlnkHome、其 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。 您可以在 或 透過在 的http://ScottOnWriting.NET部落格連線mitchell@4GuysFromRolla.com到 Scott。

特別感謝

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