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

时间:2022-06-26 17:12:38

I'm trying to set up my MVC project to have URLs so that I can go to:

我正在尝试设置我的MVC项目有url,这样我可以:

/Groups/

/团体/

/Groups/Register

/团体/注册

/Groups/Whatever

/团体/无论

But in my controller, I can also flag some actions as admin only, so that they are accessed at:

但在我的控制器中,我也可以标记一些仅作为admin的操作,以便在:

/Admin/Groups/Delete/{id}

/管理/组织/删除/ { id }

I would like to keep one GroupController, and have actions so that:

我想保留一个GroupController,并有这样的操作:

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

Allows:

允许:

/Groups is a valid URL.

/组是有效的URL。

/Admin/Groups is a valid URL (but would call some other action besides Index - maybe)

/Admin/Groups是一个有效的URL(但是会调用索引之外的其他操作——可能)

/Admin/Groups/Delete/{id} is a valid URL (post only, whatever)

/Admin/Groups/Delete/{id}是一个有效的URL

/Groups/Delete is an INVALID url.

/组/删除是一个无效的url。

I realize this is probably a pretty broad question, but I'm new to MVC and I'm not really sure where to start looking, so if you could just point me in the right direction that would be hugely appreciated.

我知道这可能是一个很宽泛的问题,但我对MVC并不熟悉,我不确定从哪里开始找,所以如果你能给我指出正确的方向,我会非常感激。

1 个解决方案

#1


2  

As we discussed in the comments below, while it is possible to use my original answer below to achieve the routing solution you requested, a better solution is to use Areas, establish an Admin area, and create controllers in your Admin area to handle the administrative tasks for different objects, such as Group, User, etc. This allows you to set up restricted administrative functions more easily, and is both a better design and a better security model.

正如我们在下面的评论中讨论的,虽然可以使用下面我最初的回答来达到你要求的路由解决方案,更好的解决方案是使用领域,建立一个管理区域,并在管理区域中创建控制器处理不同对象的管理任务,如集团用户,等等。这允许您设置限制更容易管理功能,并且是一个更好的设计和更好的安全模型。

ORIGINAL ANSWER

原来的答案

What you want can be accomplished by using the following routes:

你想要的可以通过以下途径来实现:

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 
    ); 
} 

However, as Akos said in the comments, it is a much better design to separate the administrative functions into a different controller. While this is possible, I would recommend against using this design.

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

UPDATE

更新

It is possible to use a RouteConstraint on your Default route to make it fail if Admin actions are requested. The Default route would look like this:

如果请求管理操作,则可以在默认路由上使用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
    ); 

The RouteConstraint would look like this:

这条路线看起来是这样的:

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());
    }
}

#1


2  

As we discussed in the comments below, while it is possible to use my original answer below to achieve the routing solution you requested, a better solution is to use Areas, establish an Admin area, and create controllers in your Admin area to handle the administrative tasks for different objects, such as Group, User, etc. This allows you to set up restricted administrative functions more easily, and is both a better design and a better security model.

正如我们在下面的评论中讨论的,虽然可以使用下面我最初的回答来达到你要求的路由解决方案,更好的解决方案是使用领域,建立一个管理区域,并在管理区域中创建控制器处理不同对象的管理任务,如集团用户,等等。这允许您设置限制更容易管理功能,并且是一个更好的设计和更好的安全模型。

ORIGINAL ANSWER

原来的答案

What you want can be accomplished by using the following routes:

你想要的可以通过以下途径来实现:

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 
    ); 
} 

However, as Akos said in the comments, it is a much better design to separate the administrative functions into a different controller. While this is possible, I would recommend against using this design.

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

UPDATE

更新

It is possible to use a RouteConstraint on your Default route to make it fail if Admin actions are requested. The Default route would look like this:

如果请求管理操作,则可以在默认路由上使用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
    ); 

The RouteConstraint would look like this:

这条路线看起来是这样的:

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());
    }
}