Создайте общий класс из IHttpContextAccessor, чтобы передать его через библиотеки классов

#c# #asp.net-core #configuration

#c# #asp.net-core #конфигурация

Вопрос:

Я использую .NET Core 3.1, и для каждого запроса мне нужно получить доступ к некоторым зарегистрированным заявлениям пользователей и передать их в business service (другую библиотеку классов) вне проекта API.

Я пытался создать UserService:

 public class UsersService
    {
       private readonly IHttpContextAccessor _context;

       public UsersService(IHttpContextAccessor context)
       {
         _context = context;
       }

    public UserSession GetUser()
    {
        return new UserSession()
        {
            UserDisplayName = _context.HttpContext.User?.Identity?.Name,

        };
    }
}
  

и в Startup.cs

         public void ConfigureServices(IServiceCollection services)
    {
        services.AddHttpContextAccessor();
  

который должен использоваться / вводиться другими бизнес-сервисами или подобными репозиториями:

     public class ExampleBusinessService
{
    private readonly IUnitOfWork _unitOfWork;
    private IUsersService _userService;
    public ExampleBusinessService(IUnitOfWork unitOfWork, IUsersService userService)
    {
        this._unitOfWork = unitOfWork;
        this._userService = userService;
    }


    
  

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

Можно ли этого добиться?

Конечно, я не могу создать UserService в API, а затем использовать его в других библиотеках, потому что библиотеки mens должны иметь ссылку на веб-проект.

Если нет, возможно ли в контроллере для класса запуска получить необходимую информацию от текущего пользователя и передать ее службам? Или как-то сделать это в контроллере? Как говорят, мне нужен пользовательский класс с информацией, полученной от зарегистрированного пользователя в бизнес-сервисах (отдельная библиотека классов) и репозиториях (отдельная библиотека классов)

вот как выглядит решение, мне нужно получить доступ к зарегистрированной информации пользователя (пользовательский класс UserSession) в библиотеке BusinessServices:

введите описание изображения здесь

Спасибо

Комментарии:

1. Класс контроллера является HTTP-сервером, и вашему API (клиенту) потребуется отправить запрос на сервер и получить ответ.

2. Все это API, просто бизнес-логика находится в другой библиотеке классов (тот же проект)

3. Так разве вам не нужен просто экземпляр бизнес-логики в классе usersession?

4. Ваш проект api должен ссылаться на все другие проекты, которые ему нужны, а другие проекты могут ссылаться на все остальные без api и себя, и в конце вы можете использовать зависимости, определенные в общем запуске, там, где они вам нужны. В вашем случае кажется, что вы забыли добавить ссылку и использовать для IHttpContextAccessor и его dll. Возможно, вам потребуется установить пакет, содержащий IHttpContextAccessor, в вашей dll перед его использованием.

5. @spzvtbg установите Microsoft. AspNetCore. Http в библиотеке?

Ответ №1:

IHttpContextAccessor Тип является частью ASP.NET Базовый фреймворк и как таковой доступен только в вашем веб-проекте. Если у вас есть ваша UsersService реализация в другом проекте, вы не сможете правильно ссылаться на средство доступа к контексту.

Хороший способ решить эту проблему — отделить контракт от реализации: определите a IUsersService в вашем проекте библиотеки и ссылайтесь на него только для своей бизнес-логики. Пользователям сервиса не нужно знать, от чего может зависеть реализация; их волнует только то, что они могут использовать общедоступный интерфейс этого сервиса.

Затем в вашем веб-проекте создайте реализацию IUsersService , которая использует IHttpContextAccessor для доступа к пользовательской информации. Поскольку реализация находится в веб-проекте, она может правильно обращаться к средству доступа контекста.

Наконец, объедините интерфейс и реализацию, зарегистрировав реализацию сервиса как часть вашего веб-приложения:

 services.AddTransient<IUsersService, UsersService>();
  

Как только ваши службы (за пределами веб-проекта) теперь потребуют IUsersService , они получат реализацию, которая использует средство доступа к контексту для доступа к пользовательской информации, и все должно работать без необходимости добавлять ссылку на ASP.NET Базовая структура в ваших (иначе не связанных) библиотеках.

Комментарии:

1. И таким образом, внешняя библиотека не будет нуждаться в ссылке на веб-проект. Очень приятно. Спасибо!

2. Что, если у нас есть проекты микросервисов, где каждому API микросервиса требуется информация. В приведенном выше решении мне нужно реализовать этот пользовательский сервис в каждом проекте api microservices, что опять-таки сделано неправильно. есть какие-либо предложения в случае микросервисов?

3. @RahmanBokhari Вы можете повторно использовать реализации в микросервисах, но я бы сказал, что вам, вероятно, не нужно иметь службу пользователей во всех ваших микросервисах.

Ответ №2:

Хорошо, я понимаю вашу озабоченность, и, похоже, вы подходите к проблеме неправильно. Чтобы указать на это, я считаю, что это то, что вы хотите:

  • У вас есть ExampleBusinessService , который находится в общей библиотеке классов
  • У вас есть UsersService , который занимается услугами пользовательских сеансов и т.д.
  • Вы хотите получить доступ к информации о сеансе через IHttpContextAccessor

Прежде всего, оба ExampleBusinessService и UsersService не должны быть в проекте API или привязаны к нему вообще. Вы можете свободно размещать их в своей библиотеке классов.

Вот как вы можете подойти к этому:

  • Во-первых, в вашей библиотеке классов добавьте Microsoft.AspNetCore.Http пакет.
  • Создайте статический класс UsersService (в библиотеке классов)
  • Добавьте следующий код (в UsersService )
 public static class UsersService
{
    // extend IHttpContextAccessor 
    public static UserSession GetUserSession( this IHttpContextAccessor accessor)
    {
         return new UserSession
         {
             UserDisplayName = _context.HttpContext.User?.Identity?.Name,
         }
    }
}
  
  • Теперь в вашем ExampleBusinessService inject IHttpContextAccessor
 public class ExampleBusinessService
{
    private readonly IHttpContextAccessor _contextAccessor;

    public ExampleBusinessService(IHttpContextAccessor accessor)
    {
        _contextAccessor = accessor,
    }

    // now do whatever you want with the session info
    public SomeBusinessAboutSessionInfo()
    {
        // retrieve the session
        var userSession = _contextAccessor.GetUserSession();
        //...your logic
    }
}
  

Последняя часть (это важно)

  • Добавьте IHttpContextAccessor в свой IServiceCollection проект API

services.AddTransient<IHttpContextAccessor, HttpContextAccessor>();

Теперь все должно получиться!!!

Ответ №3:

В случае добавления полного dotnetcore в общее решение (проект внешней библиотеки классов). Просто добавьте ссылку на Microsoft.AspNetCore.HTTP для получения доступа к IHttpContextAccessor