代码之家  ›  专栏  ›  技术社区  ›  JeremyWeir

ASP.NET MVC-基于已验证用户的动态控制器

  •  1
  • JeremyWeir  · 技术社区  · 16 年前

    如果我希望我的web应用程序的默认URL根据用户显示完全不同的uis,那么最好的方法是什么?我不想对每种类型的用户都使用相同的控制器。换句话说,如果用户登录并转到 http://mysweetapp.com 作为一个管理员用户,他们应该得到他们看到的东西,就像他们去了 http://mysweetapp.com/admin . 如果用户以普通用户的身份登录,他们应该看到相同的事情,就好像他们已经 http://mysweetapp.com/normaluser

    我应该将一个“重定向”控制器作为默认控制器,并让它将客户机发送到适当的控制器吗?

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

    我也试过创建自己的控制器工厂,但我不认为我对这个概念很清楚,无法让它工作。

    谢谢

    5 回复  |  直到 16 年前
        1
  •  1
  •   Dale Ragan    16 年前

    我认为最干净的方法是创建一个自定义路由处理程序,供默认路由使用。然后,如果控制器名称是您的默认控制器名称,您可以分离出要使用的控制器,在下面的示例中,它是: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
  •  1
  •   Steve Willcock    16 年前

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

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

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

        3
  •  0
  •   Adrian    16 年前

    如果不想使用同一个控制器,请首先为每个项目设置单独的控制器和视图-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
  •   Chad Ruppert    16 年前

    你可能想考虑的是领域。这将允许您为每个区域设置单独的控制器。然后允许基于角色或您希望的任何内容访问这些区域。 这将为您提供诸如'/admin/controller/action'、'/users/controller/action'等路由。“模式”按名称空间分隔所有控制器,并处理好路由。轻松分离母版页等。

    它不会给你(可能会混淆,imo)“/”和“/admin/”,在管理员用户看来是一样的,但它会让你把内容和控制器分开。

    您所描述的内容可能会为每个控制器带来大量的方法,而MVC/REST人群通常不喜欢这种方法。这并不可怕,但也不是最佳实践。

    你可以在这个博客上读到有关区域的信息 here . 谷歌“ASP.NET MVC区域”获取更多信息。

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

    展开一点:

    如果没有自定义路由或其他一些恶作剧,操作将通过URL映射到控制器。因此,如果您想让所有管理操作和视图保持不同,但是在根URL上,以及正常的用户操作,这将导致一个必须处理所有这些操作的大控制器,或者一些奇怪的“如果这个角色,这个视图;如果这个角色,那个视图”在每个操作中都会发生一些荒谬的事情。有点乱。

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

    这意味着你所有的视图都将放在一个丑陋的大目录中,目录中充满了各种奇怪的、名字相似但行为不同的视图。

    简而言之,这将成为一个潜在的可怕的维护噩梦,这取决于应用程序的复杂性。

        5
  •  0
  •   Jason Goemaat    14 年前

    可以创建一个从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);
        }
    }
    

    然后在您的应用程序中\u start():

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