【问题标题】:Prefix routing in ASP.Net MVC like cakephpASP.Net MVC 中的前缀路由,如 cakephp
【发布时间】:2009-08-23 21:19:19
【问题描述】:

我想了解如何在 cakephp 中设置前缀路由来进行管理员路由。不幸的是,我还没有弄清楚如何在 ASP.NET MVC 中做到这一点。

例如,

如果用户键入 /Admin/Management,我希望调用控制器 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此代码允许您拥有一个默认网站,然后是一个管理区域。

【问题讨论】:

    标签: asp.net-mvc


    【解决方案1】:

    也许您应该尝试编写自定义路线。查看 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);
            }
        }
    }
    

    然后,用两个动作制作一个控制器,在其中一个前面加上“Admin”,并用 AuthorizeAttribute 标记它。它应该看起来像这样:

    using System.Web.Mvc;
    
    namespace PrefixRoutingTest.Controllers
    {
        public class PrefixedController : Controller
        {
            public ActionResult Test()
            {
                return View();
            }
    
            [Authorize]
            public ActionResult AdminTest()
            {
                return View();
            }
    
        }
    }
    

    在 Views 文件夹中创建一个“Prefixed”文件夹,并在其中添加两个 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 = "" })
        });
    }
    

    就是这样,当您现在以匿名用户身份导航到 site/Prefixed/Test 时,您应该获得标准的 Test 视图,但如果您是管理员,您将获得 AdminTest 视图。但是,如果匿名用户尝试直接访问 AdminTest url,他将被发送到登录页面。

    PS:我可以确认这是可行的,如果您在实施时遇到问题,请给我打个电话;)

    【讨论】:

    • 没有足够的信息来判断这是否是一个好的答案。我特别询问如何在 ASP.NET MVC 中进行前缀路由。查看基类对我有什么帮助?
    • 啊,好吧,这看起来像我所追求的。我会在今天晚些时候试一试,然后回复你。
    • 处理区域只需设置DataTokens["area"]。 requestContext.RouteData.DataTokens["area"] = requestContext.RouteData.Values["yourCustomAreaToken"]
    【解决方案2】:

    我想也许可以为它设置一条路线?

    在此示例中,您需要为每个(管理员)控制器创建一个路由。

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

    【讨论】:

    • 我还是很新,但我认为这可以做得更整洁。
    • 感谢您的回答。我想我想要的是如果用户在 Admin\Management\Index 中键入我的请求被路由到 Management:admin_index() 这是前缀路由是什么......但我不知道它在 ASP.NET MVC 中是如何实现的.
    • 为此,您可以创建一个名为admin_index 的Action Method(返回ActionResult 的公共方法)并预先添加属性[ActionName("Index")] 这不是完全前缀路由,但应该给出所需的结果?跨度>
    • 好的,我试试,然后告诉你结果。
    【解决方案3】:

    我也一直在寻找如何做到这一点,只是想通了。

    这是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
    

    您会注意到有两个前缀路由:admin/controller/action 和 manager/controller/action。您可以根据需要添加任意数量。

    --编辑-- 最初这似乎有效,直到我尝试使用 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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-09
      • 2013-10-09
      • 2016-06-19
      • 2014-12-17
      • 1970-01-01
      • 1970-01-01
      • 2012-07-12
      • 2011-03-22
      相关资源
      最近更新 更多