﻿# ASP.NET 如何取得 Request URL 的各個部分

我們在開發網頁應用程式，時常需要去解析網址(Request.Url)的每個片段，進行一些判斷。例如說 "[http://localhost:1897/News/Press/Content.aspx/123?id=1#toc](http://localhost:1897/News/Press/Content.aspx/123?id=1#toc)"，我們想要取得網址裡第一層目錄的名字(News)用以判斷不同的頁面標題(Page Title)。

我看很多人都用字串的 IndexOf 方法與 Substring 方法：

```csharp
Request.Url.PathAndQuery.Substring(1, Request.Url.PathAndQuery.IndexOf("/", 1)-1)
```

這實在太埋沒 .NET 的強大設計了，事實上在 Request 物件就已經提供很多方便的屬性(Property)可供取得網址的片段。

底下這張表就是各種跟 Browser Request 的網址相關的屬性與用法：

|     |     |
| --- | --- |
| 網址：http://localhost:1897/News/Press/Content.aspx/123?id=1#toc |     |
| Request.ApplicationPath | **/** |
| Request.PhysicalPath | **D:\\Projects\\Solution\\web\\News\\Press\\Content.aspx** |
| System.IO.Path.GetDirectoryName(Request.PhysicalPath) | **D:\\Projects\\Solution\\web\\News\\Press** |
| Request.PhysicalApplicationPath | **D:\\Projects\\Solution\\web\\** |
| System.IO.Path.GetFileName(Request.PhysicalPath) | **Content.aspx** |
| Request.CurrentExecutionFilePath | **/News/Press/Content.aspx** |
| Request.FilePath | **/News/Press/Content.aspx** |
| Request.Path | **/News/Press/Content.aspx/123** |
| Request.RawUrl | **/News/Press/Content.aspx/123?id=1** |
| Request.Url.AbsolutePath | **/News/Press/Content.aspx/123** |
| Request.Url.AbsoluteUri | **http://localhost:1897/News/Press/Content.aspx/123?id=1** |
| Request.Url.Scheme | **http** |
| Request.Url.Host | **localhost** |
| Request.Url.Port | **1897** |
| Request.Url.Authority | **localhost:1897** |
| Request.Url.LocalPath | **/News/Press/Content.aspx/123** |
| Request.PathInfo | **/123** |
| Request.Url.PathAndQuery | **/News/Press/Content.aspx/123?id=1** |
| Request.Url.Query | **?id=1** |
| Request.Url.Fragment |     |
| Request.Url.Segments | **/**  <br>**News/**  <br>**Press/**  <br>**Content.aspx/**  <br>**123** |

所以當你看了這張表之後，你還會想用 Request.Url.PathAndQuery.Substring(1, Request.Url.PathAndQuery.IndexOf("/", 1)-1) 這種寫法嗎？

用這樣寫 Request.Url.Segments\[1\].Replace("/", "") 不是又短又直覺嗎？ ^\_^

以下是產生以上表格的程式碼：

```
protected void Page_Load(object sender, EventArgs e)
{ 

    StringBuilder sb = new StringBuilder(); 

    sb.Append("<table cellpadding=3 cellspacing=0 border=1>"); 

    sb.Append("<tr><td colspan=2>");
    sb.Append("網址：http://localhost:1897/News/Press/Content.aspx/123?id=1#toc");
    sb.Append("</td></tr>"); 

    // Request.ApplicationPath
    sb.Append("<tr><td>");
    sb.Append("Request.ApplicationPath");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.ApplicationPath + "</b>");
    sb.Append("</td></tr>"); 

    // Request.PhysicalPath
    sb.Append("<tr><td>");
    sb.Append("Request.PhysicalPath");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.PhysicalPath + "</b>");
    sb.Append("</td></tr>"); 

    // System.IO.Path.GetDirectoryName(Request.PhysicalPath)
    sb.Append("<tr><td>");
    sb.Append("System.IO.Path.GetDirectoryName(Request.PhysicalPath)");
    sb.Append("</td><td>");
    sb.Append("<b>" + System.IO.Path.GetDirectoryName(Request.PhysicalPath) + "</b>");
    sb.Append("</td></tr>"); 

    // Request.PhysicalApplicationPath
    sb.Append("<tr><td>");
    sb.Append("Request.PhysicalApplicationPath");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.PhysicalApplicationPath + "</b>");
    sb.Append("</td></tr>"); 

    // System.IO.Path.GetFileName(Request.PhysicalPath)
    sb.Append("<tr><td>");
    sb.Append("System.IO.Path.GetFileName(Request.PhysicalPath)");
    sb.Append("</td><td>");
    sb.Append("<b>" + System.IO.Path.GetFileName(Request.PhysicalPath) + "</b>");
    sb.Append("</td></tr>"); 

    // Request.CurrentExecutionFilePath
    sb.Append("<tr><td>");
    sb.Append("Request.CurrentExecutionFilePath");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.CurrentExecutionFilePath + "</b>");
    sb.Append("</td></tr>"); 

    // Request.FilePath
    sb.Append("<tr><td>");
    sb.Append("Request.FilePath");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.FilePath + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Path
    sb.Append("<tr><td>");
    sb.Append("Request.Path");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Path + "</b>");
    sb.Append("</td></tr>"); 

    // Request.RawUrl
    sb.Append("<tr><td>");
    sb.Append("Request.RawUrl");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.RawUrl + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.AbsolutePath
    sb.Append("<tr><td>");
    sb.Append("Request.Url.AbsolutePath");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.AbsolutePath + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.AbsoluteUri
    sb.Append("<tr><td>");
    sb.Append("Request.Url.AbsoluteUri");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.AbsoluteUri + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.Scheme
    sb.Append("<tr><td>");
    sb.Append("Request.Url.Scheme");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.Scheme + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.Host
    sb.Append("<tr><td>");
    sb.Append("Request.Url.Host");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.Host + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.Port
    sb.Append("<tr><td>");
    sb.Append("Request.Url.Port");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.Port + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.Authority
    sb.Append("<tr><td>");
    sb.Append("Request.Url.Authority");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.Authority + "</b>");
    sb.Append("</td></tr>"); 

    // local Request.Url.LocalPath
    sb.Append("<tr><td>");
    sb.Append("Request.Url.LocalPath");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.LocalPath + "</b>");
    sb.Append("</td></tr>"); 

    // Request.PathInfo
    sb.Append("<tr><td>");
    sb.Append("Request.PathInfo");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.PathInfo + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.PathAndQuery
    sb.Append("<tr><td>");
    sb.Append("Request.Url.PathAndQuery");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.PathAndQuery + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.Query
    sb.Append("<tr><td>");
    sb.Append("Request.Url.Query");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.Query + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.Fragment
    // 原則上你應該無法從 Request.Url.Fragment 取得任何資料，因為通常 Browser 不會送出 #toc 這個部分
    sb.Append("<tr><td>");
    sb.Append("Request.Url.Fragment");
    sb.Append("</td><td>");
    sb.Append("<b>" + Request.Url.Fragment + "</b>");
    sb.Append("</td></tr>"); 

    // Request.Url.Segments
    sb.Append("<tr>");
    sb.Append("<td>");
    sb.Append("Request.Url.Segments");
    sb.Append("</td>");
    sb.Append("<td>");
    string[] segments = Request.Url.Segments;
    foreach (string s in segments)
    {
        sb.Append("<b>" + s + "</b>");
        sb.Append("<br/>");
    }
    sb.Append("</td>");
    sb.Append("</tr>"); 

    sb.Append("</table>"); 

    ltlTable.Text = sb.ToString();
}
```

**注意事項**

-   當程式部署(Deploy)到 IIS 6 之後，假設你的網址是 [http://localhost:1897/News/Press/Content.aspx/123](http://localhost:1897/News/Press/Content.aspx/123)? ，IIS 不知為何會將問號 ( ? ) 給刪除掉，以致於 ASP.NET 使用 Request.Url.Query 是空字串！如果你的程式有判斷到這部分時就要特別注意，因為照理說應該會抓到才對！不知道是不是 IIS 6 的 Bug ？
