如何在 MVC 的 Route 中的URL {controller}/{action}/{ID} 中傳遞包含 "." 句號

前言
最近做 ASP.NET MVC 內部教育訓練時,因為同仁問的一個看似很蠢的問題,但是卻讓我發現一個我從來壓根子就不會想過,要在 {ID} 裡面傳遞的 primaryKey 的內容居然包含句號 ".”,因為眾所皆知,句號在 Url 裡面,應該是保留字元,且 RFC 3986 規範中定義了在 Url 裡面那些是保留字,如果URL中使用到了這些保留字,這時候就需要使用 UriEncoding 將其編碼為「%HEXHEX」的形式。

MVC 的 Route 中 {id} 中包含句號的問題
事情是這樣的,課堂中,實作一個 MVC 基本表單,包含清單與 (CRUD) 等 View 畫面,於是撰寫的假資料來測試從 List 到 Details 的畫面。
由於為求簡單,所以 ViewModel 只有兩個欄位:EmpName、Title,於是我將 EmpName 充當 ID 使用,傳入到 Details 畫面,因此我們直接修改 MVC 的範本如下:

但是,當程式執行後,並在這個畫面點選了這個 ActionLink 後,卻出現如下 404.0 Not Found

我發現,學員傳入的 id 為 gelis.wu,也就是說,當中有一個句號 “.”,但是我們不是有將 id 的內容用 UrlEncoding 包起來嗎?後來爬文了一下,才想起來,就是以 HTTP 所使用的 application/x-www-form-urlencoded 的編碼規則來說,字符"a"-"z","A"-"Z","0"-"9",".","-","*",和"_" 都不會被編碼,也就是說 gelis.wu 會照實丟出去,這些東西真的太久沒用就會忘,因為長久以來心中總是會有一種根深蒂固的觀念就是,從開始接觸 HTTP 到現在,應該都沒改過這些東西,應該都一樣,但有時就因為這種想法,導致類似問題都認為,這理所當然地而未加以細心思考,但是,事實上,除了 EmpName=test2 與 test2 可以導向到 Details 畫面之外,如果 EmpName 包含句號,就是不能執行,為什麼 IIS 會傳回 404 呢?
繼續爬文後發現,並不是 IIS 傳回 404 ,而是 MVC Route 規範問題,在 Stackoverflow 中也有一篇問答中也有提到

如果你希望 {id} 將尾端的句號視為 id 的一部分,你必須將 web.config 中的 httpRunrime 的 relaxedUrlToFileSystemMapping 設為 true

但是,仔細想了一下,relaxedUrlToFileSystemMapping 是指 Url 是否符合 Windows 的檔案系統路經規範,與目前這件事情根本無關。
後來繼續爬文,又在 Stackoverflow 上爬到一篇關於 ASP.NET MVC Route 的問答,標題是:

ASP.NET MVC: How to Route Search Term with . (Period) at the end


圖片網址來源:https://stackoverflow.com/questions/332757/asp-net-mvc-how-to-route-search-term-with-period-at-the-end

這一篇 Timothy Khouri 遇到一個問題,他是在 Route 的結尾 {id} 的部分若包含 “.” 句號即會得到跟我相同的 404 Not Found 的錯誤訊息,看來是跟我一樣的問題。
根據 Kosau 的說明,看來這一個問題純粹是 ASP.NET MVC Route 處裡分隔符號 “/” 無法處裡 “.” 的問題。

如果真的需要 ASP.NET MVC 的 Route 結構中使用 “.” 句號的話,Kosau 提供了一種解決方式,就是在 web.config 中的 system.webServer/handlers 的 section 裡加入如下:

修改 web.config 後再測試,果然!可以通過了!!!


後記:
我想,很顯然的是,這樣的解法會讓 Home 這個 controller 的 Route 後面的敘述任何字元都被接受,因為在 Stackoverflow 中提供的範例是將 controllers/* 後面的內容都接受,但我們實際上只有 {id} 是會有包含句號 “.” 的,所以我們也可以將 web.config 再修改得更精確一點,如下:


參考資料:
混亂的 URLEncode
http://blog.ericsk.org/archives/1423
URL 編解碼問題
http://www.huanlintalk.com/2014/02/url-encoding-solved.html
java中的url編碼與解碼
http://www.cnblogs.com/shishm/articles/1614407.html
Don’t use .NET System.Uri.UnescapeDataString in URL Decoding
https://blogs.msdn.microsoft.com/yangxind/2006/11/08/dont-use-net-system-uri-unescapedatastring-in-url-decoding/

留言

  1. syste,.web/handlers 指的是system.webServer/handlers 嗎?

    回覆刪除
  2. 是的!是我手誤,敲到鍵盤 "m" 旁邊的 "," 的逗號了,以及 system.web 後面少了一個 "Server"
    所以是 system.webServer/handlers 才對。

    回覆刪除
  3. Action有.是否相同?

    回覆刪除

張貼留言

這個網誌中的熱門文章

軟體工程師 - 成長的 10 個階段

常見的程式碼壞味道(Code Smell or Bad Smell)

什麼是 gRPC ?