asp.net mvc - 基于经过身份验证的用户的动态控制器

时间:2009-04-21 23:09:27

标签: asp.net-mvc

如果我希望我的网络应用的默认网址根据用户显示完全不同的用户界面,那么最好的方法是什么?我真的不想为每种类型的用户使用相同的控制器。换句话说,如果用户登录并转到http://mysweetapp.com并且是管理员用户,他们应该得到他们会看到的内容,就好像他们已经转到http://mysweetapp.com/admin一样。如果用户以普通用户身份登录,他们应该看到同样的事情,就好像他们已经去过http://mysweetapp.com/normaluser

我是否应该将“重定向”控制器作为我的默认控制器,让它将客户端发送到适当的控制器?

routes.MapRoute(
               "Default",
               "{controller}/{action}/{id}",
               new { controller = "Redirect", action = "Index", id = "0" });

我也尝试过创建自己的ControllerFactory,但我不认为我对这个概念很清楚,也无法让它发挥作用。

由于

5 个答案:

答案 0 :(得分:1)

为简单起见,在您的HomeController索引方法(或您正在使用的任何默认控制器)中,您可以放置​​一些这样的代码,然后AdminIndex视图或索引视图中的链接可以在用户开始导航时将其发送到适当的区域围绕您的站点 - 这样您就有了一个共享控制器,其他控制器可以特定于用户类型。

return user.IsAdministrator ? View("AdminIndex") : View("Index");

user.IsAdministrator调用当然是伪代码 - 如果用户是管理员用户,则使用您正在使用的任何方法替换它

答案 1 :(得分:1)

我认为最干净的方法是创建一个默认路由使用的自定义路由处理程序。然后,如果控制器名称是您的默认控制器名称,您可以分离出要使用的控制器,在下面的示例中,它是:Home。然后检查用户是否是管理员,并使用您想要使用的控制器处理请求。

以下是代码:

public class CustomHttpHandler : IHttpHandler
{
    public RequestContext RequestContext { get; private set; }

    public CustomHttpHandler(RequestContext requestContext)
    {
        try
        {
            string controllerName = RequestContext.RouteData.GetRequiredString("controller");
            if (controllerName.Equals("home", StringComparison.CurrentCultureIgnoreCase))
            {
                bool isAdmin = RequestContext.HttpContext.User.IsInRole("Admin");
                controllerName = isAdmin ? "admin" : "normaluser";
            }

            IControllerFactory factory = ControllerBuilder.Current.GetControllerFactory();
            IController controller = factory.CreateController(RequestContext, controllerName);
            if (controller != null)
            {
                controller.Execute(RequestContext);
            }
        }
        finally
        {
            factory.ReleaseController(controller);
        }
    }
}

public class CustomRouteHandler : IRouteHandler
{
    public IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        return new CustomHttpHandler(requestContext);
    }
}

// Now use the CustomRouteHandler when you map your default route.
routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = "" }
).RouteHandler = new CustomRouteHandler();

希望这有帮助。

答案 2 :(得分:0)

您可能需要考虑的是区域。这将允许您为每个区域分别设置控制器。然后允许根据角色或任何你想要的方式访问这些区域。 这将为您提供“/ admin / controller / action”,“/ users / controller / action”等路由。“pattern”按命名空间分隔所有控制器,并且可以很好地处理路由。轻松分离母版等

它不会给你(可能令人困惑的,IMO)'/'和'/ admin /'看起来与管理员用户相同,但它会让你分开内容和控制器。

你所描述的将导致每个控制器可能有大量的方法,这通常是MVC / REST人群所不喜欢的。这并不可怕,但它也不是最佳实践。

您可以在此博客here上阅读相关领域。谷歌'asp.net mvc领域'更多。

--------编辑-----------

扩大一点:

如果没有自定义路由或其他一些恶作剧,则操作将通过URL映射到控制器。因此,如果您希望保持所有管理操作和视图不同,但在根URL上,以及正常的用户操作,这将导致一个大控制器必须处理所有这些操作,或者一些奇怪的“如果这个角色,这个视图;如果那个角色,那个观点“在每个动作中必须发生的那种废话。可能有点混乱。

同样,默认视图引擎也会根据网址查找视图。

这意味着你的所有观点都将放在一个丑陋的目录中,这个目录中充斥着各种奇怪的同名但行为不同的观点。

简而言之,根据应用程序的复杂程度,这将成为潜在的可怕的维护噩梦。

答案 3 :(得分:0)

如果您不想使用相同的控制器,请首先为每个项目设置单独的控制器和视图 - mysweetapp.com/admin和mysweetapp.com/normaluser。

然后,您可以根据其登录角色,通过默认控制器将特定用户重定向到此页面。

if (User.IsInRole("Admin")
            {
                return RedirectToAction("Index", "admin");
            }
            else if (User.IsInRole("Standard")
            {
                return RedirectToAction("Index", "normaluser");
            }

答案 4 :(得分:0)

你能创建一个从DefaultControllerFactory扩展并覆盖CreateController的类吗?

public class RedirectControllerFactory : DefaultControllerFactory
{
    public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
    {
        if (controllerName.Equals("Redirect"))
        {
            controllerName = requestContext.HttpContext.User.IsInRole("Admin") ? "Admin" : "NormalUser";
        }
        return base.CreateController(requestContext, controllerName);
    }
}

然后在你的Application_Start()中:

protected void Application_Start()
{
    // ...
    ControllerBuilder.Current.SetControllerFactory(new RedirectControllerFactory());
}