﻿# ASP.NET MVC 開發心得分享 (7)：HandleUnknownAction

使用 ASP.NET MVC 開發網站的過程中，在 Controller 中的 Action 名稱有可能因為某些理由而想要更名(Rename)，但在 View 中的連結若忘記改或因為連結在資料庫裡沒改到的話，就會導致 Request 到一個不存在 Action 進而得到 **HTTP 404 找不到資源** 的結果 (如下圖示)，今天我就來分享處理這種情況的方式。

!['/' 應用程式中發生伺服器錯誤。找不到資源。 描述: HTTP 404. 您要尋找的資源 (或其相依性的其中之一) 可能已經移除、名稱已經變更或是暫時無法使用。請檢閱下列 URL，並且確定它的拼寫無誤。](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/bbae225cf6712e4b8d9f-image_3.png "'/' 應用程式中發生伺服器錯誤。
找不到資源。
描述: HTTP 404. 您要尋找的資源 (或其相依性的其中之一) 可能已經移除、名稱已經變更或是暫時無法使用。請檢閱下列 URL，並且確定它的拼寫無誤。")

我們都知道 ASP.NET MVC 中所有的 Controller 都是繼承 [Controller](http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.aspx) 這個抽象類別 (如下圖示)

![ ASP.NET MVC 中所有的 Controller 都是繼承 Controller 這個抽象類別](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/123cb1d9c15a25ef98e9-image_6.png " ASP.NET MVC 中所有的 Controller 都是繼承 Controller 這個抽象類別")

而在 [Controller](http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.aspx) 抽象類別中有定義一個 [HandleUnknownAction](http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.handleunknownaction.aspx) 方法，預設的行為就是回應 HTTP 404，如下圖所示 0x194 就等於十進位的 404

![在 Controller 抽象類別中有定義一個 HandleUnknownAction 方法，預設的行為就是回應 HTTP 404，如圖示 0x194 就等於十進位的 404](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/d9e6ed0bfc7cf67e1c7b-image_15.png "在 Controller 抽象類別中有定義一個 HandleUnknownAction 方法，預設的行為就是回應 HTTP 404，如圖示 0x194 就等於十進位的 404")

若你要自訂回應方式，就可以在每一個 Controller 中覆寫這個方法，或是在自己定義的 BaseController 中覆寫這個方法，如下程式範例：

```
protected override void HandleUnknownAction(string actionName)
{
    Response.Redirect("/", true);
}
```

程式碼圖示如下：

![在 Controller 抽象類別中有定義一個 HandleUnknownAction 方法，預設的行為就是回應 HTTP 404，若你要自訂回應方式，就可以在每一個 Controller 中覆寫這個方法，或是在自己定義的 BaseController 中覆寫這個方法](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/a190be2f4c105658ea50-image_9.png "在 Controller 抽象類別中有定義一個 HandleUnknownAction 方法，預設的行為就是回應 HTTP 404，若你要自訂回應方式，就可以在每一個 Controller 中覆寫這個方法，或是在自己定義的 BaseController 中覆寫這個方法")

如上範例是我習慣的寫法，直接將無效的 Request 直接 Redirect 回首頁，但建議不要在「開發時期」就這樣寫，這樣子你就很難抓錯誤了。如果網站已經部署至正式機，建議可以將這些 UnknownAction 都記錄下來備查。

如果你直接參照 MSDN 上的範例程式的話，會有一個潛在的風險，初學者要特別注意。

MSDN 上的範例程式如下：

```
protected override void HandleUnknownAction(string actionName) {
    try {
        this.View(actionName).ExecuteResult(this.ControllerContext);
    } catch (InvalidOperationException ieox ) {
        ViewData["error"] = "Unknown Action: \"" + 
            Server.HtmlEncode(actionName) + "\"";
        ViewData["exMessage"] = ieox.Message;
        this.View("Error").ExecuteResult(this.ControllerContext);
    }
}
```

如果你的 Controller 中有個如下圖的 Action 並套用了 \[AcceptVerbs(HttpVerbs.Post)\] 屬性(Attribute)

![image](https://stwillblogassets.blob.core.windows.net/files/images/external/stwillblogassets.blob.core.windows.net/3960d35519d0212efa67-image_12.png "image")

而且也沒有另一個 Login Action 存在的情況下，當使用者直接點擊 Login 這個網址 ( 以 HTTP GET )，就會觸發 [HandleUnknownAction](http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.handleunknownaction.aspx) 方法，原本你可能預期這個 Login View 在 HTTP GET 情況下不應該被顯示，但因為利用以下這行 Code 的方式直接執行名為 actionName 的 View，原本因為在 HTTP POST 才顯示的 View 就會被顯示出來！

```
this.View(actionName).ExecuteResult(this.ControllerContext);
```

所以在使用 [HandleUnknownAction](http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.handleunknownaction.aspx) 方法的時候務必要小心使用。

**相關連結**

-   [Controller.HandleUnknownAction Method](http://msdn.microsoft.com/en-us/library/system.web.mvc.controller.handleunknownaction.aspx)
