MVC 3基于请求参数使用不同的控制器

Lev*_*kon 1 model-view-controller asp.net-mvc asp.net-mvc-routing asp.net-mvc-areas

过去几天我一直在网上寻找解决方案,而且我找不到多少.希望我没有使用正确的术语,这是一件容易的事情.

我想使用如下路径:

/{projectId}
Run Code Online (Sandbox Code Playgroud)

并且在生命周期的早期某处可以访问路径值字典,我可以查询数据库或会话对象以获取用于此请求的控制器名称.然后,能够指定要使用的控制器, route.Values["controller"] = controllerName;并通过该控制器与请求参数的所有爵士乐等进行请求.

可能吗?

我目前正在使用区域,并且有以下路径:

/ProjectType1/{projectId}
/ProjectType2/{projectId}
Run Code Online (Sandbox Code Playgroud)

但是我觉得处理所有人的领域Html.Link并且讨厌为每个项目类型定义新区域真的很头疼.我很想找到更有活力的东西.

Dar*_*rov 7

你可以写一个自定义路线:

public class MyRoute : Route
{
    public MyRoute(string url, IRouteHandler routeHandler)
        : base(url, routeHandler)
    { }

    public override RouteData GetRouteData(HttpContextBase httpContext)
    {
        var rd = base.GetRouteData(httpContext);
        var projectId = rd.GetRequiredString("projectId");

        // TODO: Given the projectId decide which controller to choose:
        // you could query the database or whatever it is needed here

        if (projectId == "1")
        {
            rd.Values["controller"] = "Foo";
        }
        else if (id == "2")
        {
            rd.Values["controller"] = "Bar";
        }
        else if (id == "3")
        {
            rd.Values["controller"] = "Baz";
        }
        else
        {
            // unknown project id
            throw new HttpException(404, "Not found");
        }

        // we will always be using the Index action but this could
        // also be variable based on the projectId
        rd.Values["action"] = "index";

        return rd;
    }
}
Run Code Online (Sandbox Code Playgroud)

然后注册:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
    routes.Add(new MyRoute("{projectId}", new MvcRouteHandler()));
}
Run Code Online (Sandbox Code Playgroud)

现在:

  • /1 会调用 FooController/Index
  • /2 会调用 BarController/Index
  • /3 会调用 BazController/Index
  • /something_else 将抛出404未找到