#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
injectIHttpContextAccessor
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