Должен ли сервисный уровень иметь доступ к HttpContext?
Я создаю приложение, которое примерно следует за шаблоном репозитория с верхним слоем сервиса, похожим на ранние версии Conery MVC Storefront.
Мне нужно реализовать страницу, которая возвращает всех пользователей, кроме текущего пользователя. У меня уже есть методы GetUsers() на уровне репозитория и сервиса, поэтому вопрос заключается в том, где применять "за исключением текущего пользователя".
Должен ли сервисный уровень знать HttpContext, применяя это правило? Я испытываю соблазн просто передать текущему пользователю (id) от контроллера к этому методу службы, но кажется более чистым, если уровень сервиса был HttpContext-осведомлен и мог сделать это сам по себе.
Очевидной альтернативой является применение этого правила непосредственно в контроллере, но я просто не горяч на этой идее...
Изменить - просто для того, чтобы прокомментировать ответы: Я вижу проблемы с проблемой обратной зависимости, что я полностью игнорировал. Я отмечаю Мехрдада в качестве ответа на голосование, но каждый действительно дал ценный ответ, который стоит прочитать!
Ответы
Ответ 1
Абсолютно нет. Мое мышление при проектировании таких вещей выглядит так: я предполагаю, что мне нужно написать приложение на базе Windows вместе с веб-приложением и попытаться свести к минимуму зависимость от конкретных веб-приложений. Передача HttpContext
напрямую увеличит связь вашего уровня обслуживания с уровнем веб-интерфейса, который не идеален.
Ответ 2
Ответ: нет.
Не только уровень сервиса не должен зависеть от текущего уровня представления, на мой взгляд, он не должен зависеть от текущего приложения. Например, я бы не использовал пользовательский класс AppContext
как JonoW, предлагаемый здесь.
Вместо этого передайте текущего пользователя в качестве параметра методу GetAllUsersExceptForTheCurrentUser
. Таким образом, эта услуга может использоваться любым приложением, которое должно обрабатывать пользователей, а не только текущее приложение.
Ответ 3
Вы должны не создать обратную зависимость между вашим уровнем обслуживания и веб-уровнем. Рассмотрите, что происходит, когда вы хотите расширить свой уровень обслуживания для работы с приложением на основе форм или службой Windows. Теперь вам нужно работать с зависимостью в Интернете, чтобы заставить ваши же методы работать или дублировать некоторые (возможно, небольшие, но все же повторяющиеся) коды. Вам лучше будет извлечь идентификатор пользователя во что-то полезное в контексте уровня сервиса и использовать это значение с уровнем обслуживания. Обработка фильтрации на веб-сайте также приемлема, хотя, если вы делаете это более одного раза, ее нужно будет перестроить в обычное место, и уровень обслуживания станет для нее естественным местом.
Ответ 4
Я считаю хорошей практикой создание пользовательского класса AppContext, который содержит мой текущий пользовательский объект (а также другие контекстные данные). Этот класс не имеет ссылок на System.Web. Любые методы обслуживания, которые должны быть осведомлены о контексте, должны иметь параметр AppContext (например, для проверки прав безопасности или получения текущего пользователя, как в вашем случае). Заполните этот объект в веб-уровне и сохраните его в сеансе, если вам нужно. Таким образом, ваш уровень обслуживания ничего не знает о System.Web.
Ответ 5
Нет. Это сделает ваш код более сложным для тестирования и повторного использования.
Я имею тенденцию создавать интерфейс инфраструктуры для такого рода вещей (назовите его IAuthentication или что-то еще) и наложите на него свойство CurrentUser. Затем я вставляю это в свою службу через свой конструктор. то есть публичный MyService (IAuthentication auth)
Наконец, вы можете создать реализацию IAuthentication, поддерживающую HttpContext (например, WebAuthentication).
Теперь, когда вы создаете свой сервис, вы также создаете его зависимости:
var myService = new MyService(new WebAuthentication());
var otherUsers = myService.GetAllOtherUsers();
Если вы используете контейнер IoC, уродливая зависимость может даже исчезнуть!