2009-08-23 145 views
1

我想了解如何在cakephp中爲管理路由設置前綴路由。不幸的是,我還沒有想出如何在ASP.NET MVC中做到這一點。ASP.Net MVC中的前綴路由like cakephp

例如,

如果/行政/管理,我想控制器Management.admin_index用戶類型被調用,而不改變URL。我嘗試了我認爲是正確的,但最終改變了我的所有網站。

所以問題是:如果可能的話,我如何在ASP.NET MVC中做前綴路由?

更新:這正是我一直在尋找的。 http://devlicio.us/blogs/billy_mccafferty/archive/2009/01/22/mvc-quot-areas-quot-as-hierarchical-subfolders-under-views.aspx該代碼允許您有一個默認網站,然後是一個管理區域。

回答

2

也許你應該嘗試寫一個自定義路線。看看System.Web.Routing.RouteBase。

*編輯*

好吧,我再看看,我錯了。什麼最初是我的第一個念頭竟然是簡單的解決方案:你應該實現自定義IRouteHandler這樣的:

using System.Web; 
using System.Web.Mvc; 
using System.Web.Routing; 

namespace PrefixRoutingTest.Util 
{ 
    public class PrefixRouteHandler : IRouteHandler 
    { 
     public IHttpHandler GetHttpHandler(RequestContext requestContext) 
     { 
      //only apply this behavior to a part of the site 
      if (requestContext.HttpContext.Request.Path.ToLower().StartsWith("/prefixed/") && 
       requestContext.HttpContext.User.Identity.IsAuthenticated) 
      { 
       //prefix the action name with Admin 
       var action = requestContext.RouteData.Values["action"].ToString(); 
       requestContext.RouteData.Values["action"] = "Admin" + action; 
      } 

      return new MvcHandler(requestContext); 
     } 
    } 
} 

然後,做一個控制器,兩個動作,前綴他們中的一個與「管理」,並標記它與AuthorizeAttribute。它應該是這個樣子:

using System.Web.Mvc; 

namespace PrefixRoutingTest.Controllers 
{ 
    public class PrefixedController : Controller 
    { 
     public ActionResult Test() 
     { 
      return View(); 
     } 

     [Authorize] 
     public ActionResult AdminTest() 
     { 
      return View(); 
     } 

    } 
} 

請在瀏覽文件夾中的「前綴」文件夾,並在其中加入兩種觀點,一個Test.aspx的和AdminTest.aspx。然後你只需要使用此代碼替換默認路由(在Global.asax中):

public static void RegisterRoutes(RouteCollection routes) 
{ 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); 

    routes.Add("Default", new Route("{controller}/{action}/{id}", new PrefixRouteHandler()) 
    { 
     Defaults = new RouteValueDictionary(new { controller = "Home", action = "Index", id = "" }) 
    }); 
} 

就是這樣,當你現在瀏覽到網站/前綴/測試作爲匿名用戶,你應該得到的標準測試查看,但如果您是管理員,您將獲得AdminTest視圖。但是,如果匿名用戶直接嘗試訪問AdminTest url,他將被髮送到登錄頁面。

PS:我可以證實這一點的作品,SOU如果你有問題,實現它只是給我打電話;)

+0

沒有足夠的信息知道這是否是一個很好的答案。我特別要求如何在ASP.NET MVC中做前綴路由。如何看待基類幫助我? – 2009-08-24 20:07:43

+0

啊,好吧,這看起來像我之後。我會在今天晚些時候嘗試並回復你。 – 2009-08-26 21:02:40

+0

來處理區域只需設置DataTokens [「區域」]。 requestContext.RouteData.DataTokens [ 「區域」] = requestContext.RouteData.Values [ 「yourCustomAreaToken」] – kite 2013-04-11 10:17:45

0

我想也許爲它設置路線?

在這個例子中,您需要創建一個每個(管理員)控制器的路由。

routes.MapRoute(null, 
    "Admin/{controller}/{action}/", 
    new { controller = "Management", action = "Index" }); 
+0

我仍然很新也,但我認爲可以這樣做整潔。 – jeef3 2009-08-23 21:38:52

+0

感謝您的回答。如果在管理\管理\目錄的用戶類型我的請求被路由到管理什麼,我想我要的是:admin_index(),這是前綴的路由是什麼...但我不知道它是如何可能的ASP.NET MVC 。 – 2009-08-24 20:10:41

+0

對於這一點,你可以創建一個名爲'admin_index'的操作方法(它返回一個ActionResult公共法)和preppend屬性'[ActionName(「指數」)]' 這是相當前綴的路由不能不應該得到期望的結果呢? – jeef3 2009-08-24 20:43:23

0

我也一直在尋找如何做到這一點,只是理解了它。

這裏是VB代碼(它不應該是很難翻譯成C#)


創建一個類實現IRouteHandler:

Imports System.Web 
Imports System.Web.Mvc 
Imports System.Web.Routing 

Namespace Util.Routing 
    ''' <summary> 
    ''' This Route Handler looks for a 'prefix' part in the url. If found, it appends the prefix to the action name. 
    ''' Example: /prefix/controller/action 
    ''' Turns into: /controller/prefix_action 
    ''' </summary> 
    ''' <remarks></remarks> 
    Public Class PrefixRouteHandler 
     Implements IRouteHandler 

     Public Function GetHttpHandler(ByVal requestContext As System.Web.Routing.RequestContext) As System.Web.IHttpHandler Implements System.Web.Routing.IRouteHandler.GetHttpHandler 
      Dim prefix = requestContext.RouteData.Values("prefix") 
      If (prefix IsNot Nothing) Then 
       ' If prefix actually exists in the beginning of the URL 
       If (requestContext.HttpContext.Request.Path.ToLower().StartsWith("/" & prefix.ToString.ToLower() & "/")) Then 
        Dim action = requestContext.RouteData.Values("action") 
        If action Is Nothing Then 
         action = "index" 
        End If 
        requestContext.RouteData.Values("action") = prefix & "_" & action 
       End If 
      End If 
      Return New MvcHandler(requestContext) 
     End Function 
    End Class 
End Namespace 

接下來,這增加你的global.asax。VB:

Shared Sub RegisterRoutes(ByVal routes As RouteCollection) 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}") 
    routes.IgnoreRoute("{*favicon}", New With {.favicon = "(.*/)?favicon.ico(/.*)?"}) 
    routes.IgnoreRoute("{resource}.aspx/{*pathInfo}") 
    ' MapRoute takes the following parameters, in order: 
    ' (1) Route name 
    ' (2) URL with parameters 
    ' (3) Parameter defaults 
    routes.Add(New Route("admin/{controller}/{action}/{id}", _ 
        New RouteValueDictionary(New With {.prefix = "Admin", .controller = "Home", .action = "Index", .id = ""}), _ 
        New PrefixRouteHandler() _ 
       ) _ 
    ) 
    routes.Add(New Route("manager/{controller}/{action}/{id}", _ 
        New RouteValueDictionary(New With {.prefix = "Manager", .controller = "Home", .action = "Index", .id = ""}), _ 
        New PrefixRouteHandler() _ 
       ) _ 
    ) 
    routes.MapRoute("Default", _ 
     "{controller}/{action}/{id}", _ 
     New With {.controller = "Home", .action = "Index", .id = ""} _ 
    ) 

End Sub 

你會發現,有兩個前綴的路由:管理/控制/動作,以及管理器/控制器/動作。你可以添加儘可能多的,你想要的。

- 編輯 - 最初似乎工作,直到我嘗試使用Html.Actionlink創建鏈接。這會導致ActionLink將admin /添加到每個生成的url。所以,我糾正了它。這應該會導致前綴路由的工作方式與CakePHP的管理路由類似。

這裏是編輯:

Shared Sub RegisterRoutes(ByVal routes As RouteCollection) 
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}") 
    routes.IgnoreRoute("{*favicon}", New With {.favicon = "(.*/)?favicon.ico(/.*)?"}) 
    routes.IgnoreRoute("{resource}.aspx/{*pathInfo}") 

    routes.Add("AdminPrefix", _ 
        New Route("{prefix}/{controller}/{action}/{id}", _ 
        New RouteValueDictionary(New With {.controller = "Home", .action = "Index", .id = "", .prefix = ""}), _ 
        New RouteValueDictionary(New With {.prefix = "admin"}), _ 
        New PrefixRouteHandler())) 
    routes.Add("ManagerPrefix", _ 
        New Route("{prefix}/{controller}/{action}/{id}", _ 
        New RouteValueDictionary(New With {.controller = "Home", .action = "Index", .id = "", .prefix = ""}), _ 
        New RouteValueDictionary(New With {.prefix = "manager"}), _ 
        New PrefixRouteHandler())) 
    routes.MapRoute("Default", _ 
     "{controller}/{action}/{id}", _ 
     New With {.controller = "Home", .action = "Index", .id = ""} _ 
    ) 

End Sub