Это правильное использование проекта и контроллер MVC ASP.NET ?


Я немного не уверен, что код принадлежит в сервис и что принадлежит в контроллеры.

Допустим, я создаю сайт, который требует тонкого уровня разрешения (например, у пользователя есть разрешения, основанные на их уровне пользователя (если они вошли в систему) определения того, они могут просматривать, редактировать, добавлять сущностей имеет свой набор требований).

Процесс почти одинаковый для всех лиц:

  • Получить текущего пользователя, либо зарегистрированный или Анонимный
  • Получить запрашиваемое лицо
    • Проверьте, что это не нуль
    • Проверьте, не заблокированы системой
  • Проверить, что пользователь имеет разрешения на просмотр/редактирование на объект, а также всех родительских организаций

Итак, что должен идти туда, где?

Прямо сейчас, мой контроллер вызывает сервис, чтобы получить объект и передает Пользователю (или null для анонимной).

Служба делает вызов в хранилище, которое получает объект по идентификатору. Затем он убеждается, что пользователь имеет разрешение на просмотр его. Код в основном:

// Controller
public ActionResult Get(int id)
{
    string error;
    var entity = EntityService.Get(id, GetUser(), out error);
    if(entity == null)
      // Display error
    else
      // Display entity
}

// Service
public Entity Get(int id, User user, out string error)
{
   var entity = Repository.Get(id);
   // null check
   // permissions check
   // if it passes, return the entity, otherwise assign error and return null
}

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

Какие-либо предложения по лучший дизайн?



430
4
задан 31 марта 2011 в 01:03 Источник Поделиться
Комментарии
3 ответа

Могу ошибаться, но я думаю, что вы принимаете на вопрос контроллер/шаблон сервиса в целом, а не только для ролей.
Для всех моих проектов, за исключением наиболее тривиальных, я в конечном итоге с политиками (в основном бл) слой между контроллером и обслуживание. Действие контроллера создает класс политике и выполняет ее, внутри политики, он призывает услуг, получить сведения и т. д.... зависимость вкачать все в вашей политике так можно издеваться над этими службами. Контроллеры заканчивают очень маленький, который мне так нравится!

1
ответ дан 4 апреля 2011 в 04:04 Источник Поделиться

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

Если у вас есть конкретные требования доступа на каждую запись, на основе пользователей', у вас есть пара вариантов.

А) делать то, что ты делаешь сейчас, передать объект пользователя к сервисам слой, и пусть услуги всем разобраться и вернуть соответствующий код ошибки. В этом случае, вероятно, служба выбирает все данные, которые необходимы для обслуживания запроса, так что если вы ожидаете высокий уровень разрешения неудачи, это наверное не подходит, потому что вы будете тратить много ввода-вывода на базе запросов, которые не будут работать. Если в ваших представлениях списка, вы arleady исключить записи пользователь не имеет доступа к вашей записи защита на уровне, чтобы люди из Ури snoopting (/объект/деталь/#### например) этого может быть достаточно.

Б) реализовать метод или два в ваших услугах слой, который принимает имя пользователя и значением EntityId. Затем он делает минимальный выбор базы данных, чтобы определить, если имя пользователя имеет доступ к EntityId и он просто возвращает true или false. Это хороший вариант, если вы ожидаете, что большое количество запросов для сущностей будет выполнена авторизация, поскольку в неудачные экземпляры, вы будете выбирать только несколько битов данных из базы данных, а не весь запрос, однако, для запросов, которые разрешены, вы в конечном итоге делает выбор из двух вариантов. Только вы можете решить, если это стоит его или нет. Но это делает код немного более простой:

if(! services.UserEntityAccess(userID, entityID))
{
return View("NoAccessView");
}

return View(services.ReadEntity(entityID));

В) гибрид A и B, при инициализации нового экземпляра службы слой, убедитесь, что ваш пользовательский объект является параметром в конструктор сервиса, то к вашим услугам может всегда осуществляется в "рамках" конкретного пользователя. Это, наверное, я бы и внутренне, вы можете решить, какой вариант A или B лучше работает, опираясь в основном на сколько неудачных авторизаций вы ожидали, то здесь преимущество заключается в том, что если вы догадались неправильно, это легко изменить, потому что его обработана внутри класса, и вам не нужно изменить любой код вызова.

public ActionResult Get(int id)
{
var svc = new ServicesLayer(GetUser());
var entResponse = svc.GetEntity(id);

if (entResponse.Error != null)
{
return View("ErrorView",entResponse.Error);
}

return View(entResponse.Entity);
}

1
ответ дан 1 апреля 2011 в 04:04 Источник Поделиться

Можно , наверное, рефакторинг много повторяющихся функций к действию фильтров. Например, когда вы проверяете разрешения можно использовать AuthorizationFilter, который проверяет разрешения, прежде чем действие выполняется событие, и если оно не устраивает, RedirectToAction называется. Причина, по которой я, наверное, сказал, потому что это зависит от вас возможность управлять разрешениями на уровне контроллера, а не индивидуальном уровне лица, и там не достаточно информации в вашем вопросе, чтобы знать это наверняка. Рефакторинг этих проблем в фильтрах действий, которые возвращают перенаправить результаты помогут вам определить причину сбоев (неверный, несанкционированных и т. д.), Потому что вы будете перенаправлять пользователя на другую страницу в зависимости от того, какое условие не удалось.

1
ответ дан 3 апреля 2011 в 06:04 Источник Поделиться