2009-08-23 127 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