ASP.NET MVC Действия, которые возвращают разные представления, или просто делают кучу действий? - PullRequest
3 голосов
/ 12 марта 2010

Итак, я нахожусь в ситуации, когда мне нужно отобразить другое представление, основанное на «роли», которую имеет аутентифицированный пользователь.

Мне интересно, какой подход лучше здесь:

[Authorize(Roles="Admin")]
public ActionResult AdminList(int? divID, int? subDivID) 
{
    var data = GetListItems(divID.Value, subDivID.Value);
    return View(data);
}

[Authorize(Roles = "Consultant")]
public ActionResult ConsultantList(int? divID, int? subDivID)
{
    var data = GetListItems(divID.Value, subDivID.Value);
    return View(data);
}            

или я должен сделать что-то подобное

[Authorize]
public ActionResult List(int? divID, int? subDivID)
{
    var data = GetListItems(divID.Value, subDivID.Value);
    if(HttpContenxt.User.IsInRole("Admin")) 
    { return View("AdminList", data ); }

    if(HttpContenxt.User.IsInRole("Consultant")) 
    { return View("ConsultantList", data ); }

    return View("NotFound");
}

Ответы [ 3 ]

5 голосов
/ 12 марта 2010

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

Один из подходов заключается в рефакторинге кода проверки уродливой роли в сервисный уровень (который может быть внедрен при использовании контейнера IoC):

[Authorize]
public ActionResult List(int? divID, int? subDivID)
{
    var permission = _userService.GetKeyRole(HttpContext.User);
    if(permission != null) 
    {
       var data = GetListItems(divID.Value, subDivID.Value);
       return View(permission + "List", data );
    }
    return View("NotFound");
}

И извлеченный метод:

public class UserService : IUserService
{
    public string GetKeyRole(IPrincipal user)
    {
        if(user.IsInRole("Admin")) return "Admin";
        if(user.IsInRole("Consultant")) return "Consultant";
        return null;
    }
}
5 голосов
/ 12 марта 2010

В случае, когда действие концептуально одинаково, но дисплей отличается, я бы выполнил одно действие и вернул бы разные представления в зависимости от вашего дискриминатора. Я бы пошел с вашим вторым примером, слегка измененным. Обратите внимание, что нет необходимости получать данные, если пользователь не в соответствующей роли.

[Authorize] 
public ActionResult List(int? divID, int? subDivID) 
{ 
    var view = HttpContext.User.IsInRole("Admin")
                   ? "AdminList"
                   : (HttpContext.User.IsInRole("Consultant")
                         ? "ConsultantList"
                         : null);
    if (view == null)
    {
        return View("NotFound");
    }

    var data = GetListItems(divID.Value, subDivID.Value); 

    return View( view, data );
}

Вы, конечно, понимаете, что у вас есть потенциал для необработанного исключения, когда вы ссылаетесь на Значение потенциально нулевого Nullable<int>, верно?

Кроме того, если вы делаете это часто, вы можете преобразовать конструкцию префикса представления в общий метод.

public string GetRolePrefix()
{
    return HttpContext.User.IsInRole("Admin")
                   ? "Admin"
                   : (HttpContext.User.IsInRole("Consultant")
                         ? "Consultant"
                         : null);
}

Тогда назовите это как

...
var prefix = GetRolePrefix();
if (prefix == null)
{
    return View("NotFound");  // more likely "NotAuthorized" ???
}

...get model...

return View( prefix + "List", data );
0 голосов
/ 28 января 2014

Вот третий подход. Это комбинация обоих подходов, предложенных Нейтом, сохраняет одно место для логики, как во втором подходе, но разделяет пользователей на действия, как в первом.

[ChildActionOnly]
public ActionResult List(int? divID, int? subDivID) 
{
    var data = GetListItems(divID.Value, subDivID.Value);
    return View(data);
}

[Authorize(Roles="Admin")]
public ActionResult AdminList(int? divID, int? subDivID) 
{
    return List(divID, subDivID);
}

[Authorize(Roles = "Consultant")]
public ActionResult ConsultantList(int? divID, int? subDivID)
{
    return List(divID, subDivID);
}

Хитрость в том, что MVC будет пытаться искать представления, названные действием запроса, а не то, которое выдает результат. Поэтому, когда вы запускаете AdminList, он фактически возвращает действие List с представлением AdminList.

Редактировать: Был ли понижающий голос за неправильный ответ на вопрос? Позвольте мне перефразировать мой ответ.

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