ASP.NET MVC3将各种子文件夹路由到同一个控制器

时间:2011-09-08 22:02:03

标签: asp.net-mvc asp.net-mvc-3 asp.net-mvc-routing asp.net-mvc-areas

我正在尝试设置我的MVC项目以获取URL,以便我可以访问:

  

/组/

     

/组/注册

     

/组/无论

但是在我的控制器中,我还可以将一些操作标记为仅限管理员,以便在以下位置访问它们:

  

/管理/组/删除/ {ID}

我想保留一个GroupController,然后采取行动:

public class GroupController : Controller
{
    public ActionResult Index(){
        return View();
    }
    [AdminAction]
    public ActionResult Delete(int id){
        ...
        return View();
    }
}

允许:

  

/ Groups是有效的网址。

     

/ Admin / Groups是一个有效的URL(但除了索引之外还会调用其他一些操作) -

     

/ Admin / Groups / Delete / {id}是有效的网址(仅限帖子,无论如何)

     

/ Groups / Delete是一个无效的网址。

我意识到这可能是一个非常广泛的问题,但我是MVC的新手,我不确定从哪里开始寻找,所以如果你能指出我正确的方向,那将非常感激。< / p>

1 个答案:

答案 0 :(得分:2)

正如我们在下面的评论中所讨论的那样,尽管可以使用下面的原始答案来实现您请求的路由解决方案,但更好的解决方案是使用区域,建立Admin区域,并在您的管理区域可以处理不同对象的管理任务,例如组,用户等。这使您可以更轻松地设置受限制的管理功能,并且是更好的设计和更好的安全模型。

原始回答

您可以使用以下路线完成所需的工作:

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

    routes.MapRoute( 
        "Admin", // Route name 
        "admin/{controller}/{action}/{id}", // URL with parameters 
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults

    routes.MapRoute( 
        "Default", // Route name 
        "{controller}/{action}/{id}", // URL with parameters 
        new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults 
    ); 
} 

然而,正如Akos在评论中所说,将管理功能分成不同的控制器是一个更好的设计。虽然这是可能的,但我建议不要使用这种设计。

<强>更新

如果请求管理员操作,可以在默认路由上使用RouteConstraint使其失败。默认路由如下所示:

    routes.MapRoute( 
        "Default", // Route name 
        "{controller}/{action}/{id}", // URL with parameters 
        new { controller = "Home", action = "Index", id = UrlParameter.Optional, // Parameter defaults 
        new { action = IsNotAdminAction() } // route constraint
    ); 

RouteConstraint看起来像这样:

public class IsNotAdminAction : IRouteConstraint 
{
    private string adminActions = "create~delete~edit";

    public IsNotAdminAction()
    { }

    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        // return false if there is a match
        return !adminActions.Contains(values[parameterName].ToString().ToLowerInvariant());
    }
}