2012-12-11 39 views
7

我想用默認controller = Home和default action = Index來維護ASP.NET MVC 4的現有控制器/操作/ ID路由,但也要啓用controller/id只要第二個項目不是已知的操作,就轉到控制器的索引方法。在ASP.NET MVC 4中使用id路由到索引4

例如,給定一個控制器家庭用行動指標及發送:

/Home/Send -> controller's Send method 
/Home -> controller's Index method 
/Home/Send/xyz -> controller's Send method with id = xyz 
/Home/abc -> controller's Index method with id = abc 

但是,如果我先定義兩種路線,它隱藏了另外一個。我將如何做到這一點?

+0

你是如何在RouteTable上定義你的路線的? –

+0

@FelipeOriani我沒有 - 如果我創建一個,它會隱藏另一個,據我所知。 –

回答

2

在情況下,你的行爲(如發送)的列表中是衆所周知的,而他們(行動)名稱不能是一樣的,有些ID值,我們可以用我們的自定義ConstraintImplementation:

public class MyRouteConstraint : IRouteConstraint 
{ 
    public readonly IList<string> KnownActions = new List<string> 
     { "Send", "Find", ... }; // explicit action names 

    public bool Match(System.Web.HttpContextBase httpContext, Route route 
        , string parameterName, RouteValueDictionary values 
        , RouteDirection routeDirection) 
    { 
    // for now skip the Url generation 
    if (routeDirection.Equals(RouteDirection.UrlGeneration)) 
    { 
     return false; // leave it on default 
    } 

    // try to find out our parameters 
    string action = values["action"].ToString(); 
    string id = values["id"].ToString(); 

    // id and action were provided? 
    var bothProvided = !(string.IsNullOrEmpty(action) || string.IsNullOrEmpty(id)); 
    if (bothProvided) 
    { 
     return false; // leave it on default 
    } 

    var isKnownAction = KnownActions.Contains(action 
          , StringComparer.InvariantCultureIgnoreCase); 

    // action is known 
    if (isKnownAction) 
    { 
     return false; // leave it on default 
    } 

    // action is not known, id was found 
    values["action"] = "Index"; // change action 
    values["id"] = action; // use the id 

    return true; 
    } 

與路線圖(默認的前 - 這兩個必須提供),應該是這樣的:

routes.MapRoute(
    name: "DefaultMap", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = string.Empty, action = "Index", id = string.Empty }, 
    constraints: new { lang = new MyRouteConstraint() } 
); 

總和mary:在這種情況下,我們正在評估「action」參數的值。

  • 如果同時提供1)action和2)id,我們將不會在這裏處理它。
  • 如果這是已知的行爲(在列表中,或反映...)。
  • 只有當動作名稱未知時,讓我們更改路由值:將動作設置爲「索引」並將動作值設置爲ID。

注:action名稱和id值必須是唯一的......那麼這將工作

+0

是否可以從中識別實際控制器類的類型,並查看動作是否匹配?我不想手動構建操作名稱列表。 –

+0

有兩個類似的問題(我被invovled;)解決方案可能可以找到:http://stackoverflow.com/questions/13602238,http://stackoverflow.com/questions/13423545。因爲控制器名稱是路線的一部分,所以有些反思......但大多數情況下,它必須通過自定義方法來完成;( –

5

在默認通用之前先執行特定的一個。訂單很重要。

routes.MapRoute(name: "single", url: "{controller}/{id}", 
    defaults: new { controller = "Home", action = "Index" }, 
    constraints: new { id = @"^[0-9]+$" }); 

routes.MapRoute(
    name: "Default", 
    url: "{controller}/{action}/{id}", 
    defaults: new { controller = "Home", 
    action = "Index", 
    id = UrlParameter.Optional } 
); 
+0

不幸的是,我的身份證不一定是數字。它是一個字符串,而且什麼都行。 –

+1

然後你可以擺脫路由約束 – Shyju

+0

如果我消除了約束,那麼任何針對控制器/操作(無ID)的請求都將與控制器/ ID匹配,而不是相應的操作。 –

0

我不認爲有您的要求的解決方案,因爲你有兩個競爭的路線。也許你可以定義一些特定的東西(如果你沒有任何其他控制器)。

routes.MapRoute(
     name: "Send", 
     url: "{controller}/Send/{id}", 
     defaults: new { controller = "Home", id = UrlParameter.Optional } 
    ); 
routes.MapRoute(
     name: "Home", 
     url: "Home", 
     defaults: new { controller = "Home", action = "Index" } 

routes.MapRoute(
     name: "Index", 
     url: "{controller}/{id}", 
     defaults: new { controller = "Home", action= "Index", 
          id = UrlParameter.Optional } 
    ); 

routes.MapRoute(
     name: "Default", 
     url: "{controller}/{action}/{id}", 
     defaults: new { controller = "Home", action = "Index", 
               id = UrlParameter.Optional } 
    ); 
0

這是什麼工作對我來說:

1)在RouteConfig,我就把這是的第一行:

routes.MapRoute(name: "single", url: "{controller}/{lastName}", 
      defaults: new { controller = "LeaveRequests", action = "Index" }); 

2)在我的控制器:

public ViewResult Index(string lastName) 
{ 
    if (lastName == null) 
    { 
     return //return somthing 
    } 
    else 
    { 
     return //return something 
    } 
} 

3)當你調用控制器

http://localhost:34333/leaveRequests/Simpsons 

它會給你辛普森的所有請求。

如果你調用http://localhost:34333/leaveRequests/ 它會給所有請求

0

這對我的作品

routes.IgnoreRoute( 「{}資源個.axd/{*} PATHINFO」);

 routes.MapRoute(
      name: "Default1", 
      url: "{id}", 
      defaults: new { controller = "Home", action = "Index" } 
     ); 

     routes.MapRoute(
      name: "Default", 
      url: "{controller}/{action}/{id}", 
      defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } 
     ); 
+0

訂單在這裏很重要。 –

1

最簡單的方法是在Controller中簡單創建兩個Action方法。一個用於索引,另一個用於發送並將您的字符串ID參數放在兩者上。既然你不能有重複或重載的操作方法,那就解決了這個問題。您的索引方法現在將處理索引或空白路徑,其中id是否存在(null)並以這種方式處理您的視圖。您的發送方法將與索引完全相同。然後,您可以路由,處理或重定向您喜歡的方式,具體取決於id是否爲空。這應該沒有變化RouteConfig.cs工作:

public ActionResult Index(string id) {if (id == null) Do A else Do B} 

public ActionResult Send(string id) {if (id == null) Do A else Do B} 

我有這個鬥爭了很長時間,這是最簡單的解決方案。