2011-07-17 46 views
0

我真的很喜歡ASP.NET MVC 3框架。或者至少,它確實比試圖用ASP.NET 3.5或4.0來愚弄更好。但是,我只是對某些事情感到困惑。他們爲什麼選擇用字符串指定路線?指定ASP.NET MVC 3路線符號

IOW,我告訴我的指定的路線是這樣的(例如):

... new { controller = "Products", action = "List", id = UrlParameter.Optional } 

這條路線相匹配的ProductsController.List()方法。假設我處於重構心態,並且想要將我的ProductsController重命名爲InventoryController。在使用我選擇的重命名工具後,我打開Global.aspx並遍歷所有路線並將所有這些愚蠢的字符串更改爲「Inventory」。你可能會迴應,我可以做一個查找和替換......但來吧!我覺得這是最後一代的答案。

我喜歡重構我的代碼,因爲我更好地理解了我的域。我不想使用愚蠢的(我說愚蠢,因爲它們對編譯器沒有意義)字符串來引用符號/語義代碼結構,這些結構完全對應於最終存儲在符號表中的類型和方法名稱。有什麼意義?爲什麼要打擾類型呢?讓我們回過頭來使用關聯數組和字典來編寫腳本來表示我們的領域模型......在我看來,當我們將它與字符串引用混合時,強類型的好處會大大減少。

儘管如此,一個選項將是反思。會有這樣的性能打擊嗎?我想MVC框架必須在該產品字符串上使用反射來獲得我的產品控制器,所以......但是,您也必須刪除類型名稱中的「控制器」部分,如下所示:

= typeof(ProductsController).Name.Replace("Controller", string.Empty) 

我可以使用下面的輔助函數,使之成爲小機:

public string GetControllerName(Type controller) 
{ 
    return controller.Name.Replace("Controller", string.Empty); 
} 

標杆是爲了,如果這是爲了避免這些字符串的唯一途徑......不過,這是愚蠢的。我在一個類型上使用反射來獲得一個MVC將與反射結合使用的字符串,以獲得我原來首先使用的類型。

是否有某些原因不採取下一步(邏輯?)步驟並讓控制器和操作屬性直接指望類型和委託?這難道不是簡單清晰嗎?就我所知,MVC的一個基本方面是約定優於配置,但使用這些字符串進行路由似乎只是對我的配置形式。

是否有其他解決方法?我還是MVC的新手。我讀過我們可以替換這些路由組件。有誰知道是否有可能做我正在談論的事情?如果這是不可能的,那麼......我一個人在這裏嗎?我錯過了什麼嗎?一些壓倒一切的原因是爲什麼這些路線必須由啞線設置?如果沒有,這可能是爲了遊說嗎?

當我用這種方式使用字符串的時候,我是否還在憎恨它?我仍然認爲C#需要類似於Ruby的符號和Lisp的關鍵字,以便我們的重構工具可以利用。有點像枚舉值名稱同時是值的「字符串枚舉」。

我明白這個問題的一部分是主觀的,但我也在尋找關於是否可以直接使用類型和委託來指定這些路由配置的客觀答案。

謝謝 Jeromeyers

回答

1

個人而言,我從未有過的方式路線問題的定義,因爲我總是unit test them。所以,如果我處於重構的心情,我的單元測試總是保證我的路線將按照我的意願行事。

當然,如果您仍然不滿意ASP.NET MVC團隊設計框架的方式(不要猶豫打開票並投票改進未來版本),您可以隨時編寫自定義路線:

public class IHateMagicStringsRoute<T> : Route where T : Controller 
{ 
    public IHateMagicStringsRoute(
     string url, 
     Expression<Func<T, ActionResult>> expression 
    ) : base(url, Parse(expression), new MvcRouteHandler()) 
    { } 

    private static RouteValueDictionary Parse(Expression<Func<T, ActionResult>> expression) 
    { 
     var mce = expression.Body as MethodCallExpression; 
     if (mce != null) 
     { 
      return new RouteValueDictionary(new 
      { 
       controller = typeof(T).Name.Replace("Controller", ""), 
       action = mce.Method.Name 
      }); 
     } 
     return null; 
    } 
} 

然後,而不是和:

routes.MapRoute(
    "Default", 
    "{controller}/{action}", 
    new { controller = "Home", action = "Index" } 
); 

你可以:

routes.Add(
    new IHateMagicStringsRoute<HomeController>(
     "{controller}/{action}", 
     x => x.Index() 
    ) 
); 

現在,您可以根據自己的喜好重新命名控制器和操作。

+0

太棒了,就是我在找的東西。然而,當你說你因爲單元測試而沒有任何問題時,我仍然認爲由於不得不用這些字符串來中斷開發流程。如果單元測試失敗(因爲它會),那麼你將不得不和你的路線一起去,而不是讓你的重命名自動處理它。我儘可能地避免這些無關的步驟,這些步驟有助於在我開發的過程中破壞我在工作中與我一起工作的不斷變化的卡片屋。 – jeromeyers

+0

快速提問:爲什麼我們最初使用MapRoute並將「Default」的值作爲第一個參數,然後在自定義路徑中使用Add方法並忽略提供「Default」參數? – jeromeyers

+0

@ jeromeyers,這是路線的名稱。如果你想:'routes.Add(「Default」,new IHateMagicStringsRoute (...));' –