Области обслуживания в ASP.NET Core с концентраторами SignalR - PullRequest
0 голосов
/ 27 июня 2019

Я ввел SignalR в свой проект ASP.NET Core 2, но у меня возникли некоторые проблемы с использованием службы scoped , которую я обычно использую в своих контроллерах.Я чувствую, что проблема может быть связана с разницей в жизненных циклах между HTTP-запросами, веб-сокетами и концентраторами.

При каждом HTTP-запросе промежуточное ПО считывает токен Authorization и обновляет некоторые свойства (например, id, утверждения и т. Д.)..) в сервисе с ограниченным объемом (IUser) для запроса.Я использую этот сервис во всех моих контроллерах без проблем.Чтобы заставить его работать с SignalR, я отправляю параметр запроса access_token и заранее использую некоторое другое middleware , чтобы добавить этот параметр запроса в качестве заголовка, который отлично работает.

Проблема возникаеткогда я пытаюсь получить доступ к службе IUser в моем концентраторе SignalR.При создании хаба для IUser, который вводится, не задано ни одно из свойств, несмотря на то, что промежуточное программное обеспечение для запроса /hub просто устанавливает их.

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

Как мне настроить IUser для конкретного соединения SignalR?

// Startup.cs - User has several settable properties 
services.AddScoped<IUser, User>();
// User Middleware
public class UserMiddleware
{
    private readonly RequestDelegate _next;

    public UserMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public Task Invoke(HttpContext context)
    {
        // retrieve service for this request
        var user = context.RequestServices.GetService<IUser>();

        // set some properties on the User from auth token
        // e.g. User.Id = 1;

        return _next(context);
    }
}
[Authorize(Roles = Claim.Names.Read)]
public class MyHub : Hub
{
    private readonly IUser _user;

    public MyHub(IUser user)
    {
        // user that gets injected has null properties
        _user = user;
    }

    public async Task Foo()
    {
        // do work with the _user credentials
    }
}
public class DownloadController : Controller
{
    private readonly IUser _user;

    public DownloadController(IUser user)
    {
        // user gets injected and has properties set
        _user = user;
    }
}

1 Ответ

0 голосов
/ 28 июня 2019

Чтобы использовать сервис областей в концентраторе сигналов, вы можете добавить ServiceProvider и создать область в нем напрямую:

public class ChatHub : Hub
{      
    private IServiceProvider _serviceProvider;
    public ChatHub(IServiceProvider serviceProvider)
    {
        _serviceProvider= serviceProvider;
    }

    public async Task Foo()
    {
        using (var scope = _serviceProvider.CreateScope())
        {
           var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();

           var user = scope.ServiceProvider.GetRequiredService<IUser>();    

        }

    }
}
...