主版頁面中的 URL (VB)
解決主版頁面中的 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。
圖 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
。
圖 02: PoweredByASPNET.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) 。
圖 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 應用程式根目錄的子資料夾。
類別 Control
的 ResolveClientUrl
方法 會採用 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 控件的 設定為 ID
PoweredByImage
、其 屬性設定為 ~/Images/PoweredByASPNET.gif
,並將其 ImageUrl
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) 。 轉譯 Image Web 控制件時,它會使用 ResolveClientUrl
方法來解析其 ImageUrl
屬性值。 在 中~/Admin/Default.aspx
ImageUrl
會轉換成適當的相對 URL,如下列 HTML 來源代碼段所示:
<div id="footerContent">
<img id="ctl00_PoweredByImage" src="../Images/PoweredByASPNET.gif" alt="Powered by ASP.NET!" />
</div>
注意
除了用於 URL 型 Web 控制項屬性之外, ~
也可以在呼叫 Response.Redirect
和 Server.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。 您可以在 或 透過在 的http://ScottOnWriting.NET部落格連線mitchell@4GuysFromRolla.com到 Scott。
特別感謝
有興趣檢閱即將推出的 MSDN 文章嗎? 如果是,請將一行 mitchell@4GuysFromRolla.com放在 。