首页 > 解决方案 > 尝试激活 api 控制器时无法解析类型“Microsoft.AspNetCore.SignalR.HubConnectionContext”的服务

问题描述

我正在使用 ASP.NET Core (MVC) 开发一个 Web 应用程序,它将向一组用户显示一些信息。它们将使用 Windows Athentication 进行身份验证。我最近开始使用 SignalR,因为我希望他们接收基于由另一个用 Python 编写的程序触发的某些操作的推送通知。该 Python 程序将 HTTP 发布请求发送到 Web 应用程序中的 API 控制器。但是,我希望将这些通知发送给特定用户。

这是我在 api 控制器中的 post 方法:

[HttpPost]
    public void Post([FromBody] Notice notice)
    {
        //_pushHub.Clients.All.SendAsync("ReceiveMessage", notice.Title, notice.Body);
        _pushHub.Clients.User(_nuidProvider.GetUserId(_connection)).SendAsync("ReceiveMessage", notice.Title, notice.Body);
    }

它接收一个Notice 类的对象,它有两个字段:Title 和Body。

然后我使用方法 SendAsync() 发送这些值。当我为所有客户端执行它时,它会成功发送。但是,由于我需要将其发送给特定用户,因此我尝试按照以下说明操作:https ://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-5.0

我按照建议创建了这个类:

namespace MyApp.Services
{
    public class NameUserIdProvider : IUserIdProvider
    {
        public string GetUserId(HubConnectionContext connection)
        {
            return connection.User?.Identity?.Name;
        }
    }
}

然后我将它添加到 ConfigureServices 的 StartUp 中:

        services.AddSingleton<IUserIdProvider, NameUserIdProvider>();
        services.AddSignalR();

最后,我修改了 JS 文件以包含以下语句:options.UseDefaultCredentials = true; 按照说明中的建议:

const conn = new signalR.HubConnectionBuilder().withUrl('/pushHub', options => {
    options.UseDefaultCredentials = true;
}).build();

conn.on('ReceiveMessage', (title, body) => {
    const t = title.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    const b = body.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
    const date = new Date().toLocaleTimeString();
    const msg = date + ' ' + t + ' ' + b;
    const li = document.createElement('li');
    li.innerHTML = msg;
    document.getElementById('msgsList').appendChild(li);

    Push.create(title, {
        body: body,
        timeout: 9000
    });
});

conn.start().catch(err => console.error(err.toString()));

完整的 api 控制器看起来像这样,但我不确定我是否做得对:

namespace MyApp.Controllers.api
{
    [Route("api/[controller]")]
    [ApiController]
    public class NoticesController : ControllerBase
    {
        private readonly IHubContext<PushHub> _pushHub;
        private readonly IUserIdProvider _nuidProvider;
        private readonly HubConnectionContext _connection;

        public NoticesController(IHubContext<PushHub> pushHub, IUserIdProvider nuidProvider, HubConnectionContext connection)
        {
            _pushHub = pushHub;
            _nuidProvider = nuidProvider;
            _connection = connection;
        }

        // POST api/<NoticesController>
        [HttpPost]
        public void Post([FromBody] Notice notice)
        {
            //_pushHub.Clients.All.SendAsync("ReceiveMessage", notice.Title, notice.Body);
            _pushHub.Clients.User(_nuidProvider.GetUserId(_connection)).SendAsync("ReceiveMessage", notice.Title, notice.Body);
        }

    }
}

我想我没有将正确的连接对象传递给 GetUserId 方法。

任何建议将不胜感激。谢谢!

标签: asp.net-mvcasp.net-coresignalrwindows-authentication

解决方案


推荐阅读