asp.net mvc - динамический контроллер на основе аутентифицированного пользователя - PullRequest
1 голос
/ 22 апреля 2009

Если я хочу, чтобы URL моего веб-приложения по умолчанию отображал совершенно разные пользовательские интерфейсы в зависимости от пользователя, каков наилучший способ сделать это? Я действительно не хочу использовать один и тот же контроллер для каждого типа пользователей. Иными словами, если пользователь вошел в систему и зашел на 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 ]

1 голос
/ 23 апреля 2009

На мой взгляд, самый простой способ - создать собственный обработчик маршрута, который будет использоваться вашим маршрутом по умолчанию. Затем вы можете выделить, какой контроллер будет использоваться, если имя контроллера - это имя вашего контроллера по умолчанию, в приведенном ниже примере это: 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();

Надеюсь, это поможет.

1 голос
/ 22 апреля 2009

Для простоты, в вашем методе индекса HomeController (или любом используемом вами контроллере по умолчанию) вы можете поместить некоторый код, подобный этому, а затем ссылки из представления AdminIndex или представления Index могут отправлять пользователей в соответствующие области, когда они начинают переходить. вокруг вашего сайта - таким образом, у вас есть один общий контроллер, а другие контроллеры могут быть специфическими для типа пользователя.

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

вызов user.IsAdministrator, конечно же, псевдокод - замените его на любой метод, который вы используете для работы, если пользователь является администратором

0 голосов
/ 27 ноября 2010

Не могли бы вы создать класс, который выходит из 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());
}
0 голосов
/ 22 апреля 2009

Если вы не хотите использовать один и тот же контроллер, сначала настройте отдельные контроллеры и представления для каждого элемента - mysweetapp.com/admin и mysweetapp.com/normaluser.

Затем вы можете перенаправить определенных пользователей на эту страницу через контроллер по умолчанию на основе их зарегистрированной роли.

if (User.IsInRole("Admin")
            {
                return RedirectToAction("Index", "admin");
            }
            else if (User.IsInRole("Standard")
            {
                return RedirectToAction("Index", "normaluser");
            }
0 голосов
/ 22 апреля 2009

То, что вы могли бы рассмотреть, это области. Это позволит вам иметь отдельные контроллеры для каждой области. Затем разрешите доступ к этим областям в зависимости от ролей или чего угодно. Это даст вам такие маршруты, как «/ admin / controller / action», «/ users / controller / action» и т. Д. «Pattern» разделяет все ваши контроллеры по пространству имен и довольно хорошо справляется с маршрутизацией. Легкое разделение главных страниц и т. Д.

Это не даст вам (потенциально сбивающему с толку, IMO) '/' и '/ admin /' выглядеть одинаково для администратора, но позволит разделить контент и контроллеры.

То, что вы описываете, может привести к потенциально множеству методов для каждого контроллера, что обычно не одобряется толпой MVC / REST. Это не ужасно, но и не считается лучшей практикой.

Вы можете прочитать об областях в этом блоге здесь . Google "asp.net MVC области" для более.

-------- редактировать -----------

Чтобы немного расширить:

Без пользовательских маршрутов или некоторых других махинаций действия отображаются на контроллеры по URL. Поэтому, если вы хотите, чтобы все действия и представления администратора отличались друг от друга, кроме корневого URL, наряду с обычными действиями пользователя, это привело бы к одному большому контроллеру, который должен обрабатывать все эти действия, или к некоторому странному «если это роль, это представление ; если это роль, то представление "своего рода бессмыслица, которая должна была бы случиться в каждом действии. Что-то вроде беспорядка для отладки.

Точно так же механизм представления по умолчанию находит представления также на основе URL.

Это будет означать, что все ваши представления будут находиться в одном большом уродливом каталоге, полном всевозможных странных с одинаковыми именами, но по-разному ведут себя представлений.

Короче говоря, это может стать ужасным кошмаром обслуживания, в зависимости от сложности приложения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...