将Signalr消息发送给特定用户

时间:2020-10-20 08:36:06

标签: javascript c# .net-core signalr signalr-hub

在我的项目中,我设置了SignalR,将消息发送给连接到我的站点的每个用户。我正在更改此设置,因此我的消息只会发送给生成消息的用户。但是,我无法获得用户身份,我希望有人能够告诉我我做错了什么/遗漏了。

在我的StartUp类中,ConfigureServices内有以下几行:

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

然后在我的Configure中,有以下几行:

app.UseAuthentication();
app.UseAuthorization();
app.UseWebSockets();
app.UseEndpoints(endpoints =>
{
  endpoints.MapHub<UserErrorHub>("/UserErrorHub", options =>
  {
    options.Transports =
       HttpTransportType.WebSockets |
       HttpTransportType.LongPolling;
  });
  endpoints.MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}");
});

接下来,我的视图在<script>块中设置了以下连接字符串:

 var url = "@Url.Content("~/UserErrorHub")";

    var connection = new signalR.HubConnectionBuilder()
        .withUrl(url, { transport: signalR.HttpTransportType.WebSockets | signalR.HttpTransportType.LongPolling}, options =>
        {
            options.UseDefaultCredentials = true;     
        }
        .configureLogging(signalR.LogLevel.Information)
        .build();

最后我的集线器中有以下课程:

public class UserErrorHub : Hub
{
    public async override Task OnConnectedAsync()
    {
        string name;
        var user = Context.User;
        if (user.Identity.IsAuthenticated)
        {
            name = user.Identity.Name;
        }
        else
        {
            name = "anonymous";
        }
        await Clients.All.SendAsync("Message",  "hello there!" + name);
    }

    public async Task Message( string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", message);
    }
}

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

当我运行项目时,我无法使我的用户名在连接时出现,而是出现了所有“匿名”名称,这不是我想要的。有人可以告诉我我在做什么错吗?

2 个答案:

答案 0 :(得分:1)

对于我的情况,我必须删除singalR端点并使用较旧的已废弃方法

        app.UseSignalR(builder =>
        {
            builder.MapHub<UserErrorHub >("/userErrorHub");
        });

不要忘记中心上的Authorize属性

       [Authorize]

答案 1 :(得分:0)

这是我实现it的方式。我已经删除了以下几行代码,供您遵循。

定义中心类

public class ConnectionHub : Hub
    {
        public async Task Send(string userId)
        {
            var message = $"Send message to you with user id {userId}";
            await Clients.Client(userId).SendAsync("ReceiveMessage", message);
        }
 
        public string GetConnectionId()
        {
            return Context.ConnectionId;
        }
    }

在您的startup.cs

public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc();
            services.AddSignalR();
        }
 
        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            app.UseSignalR(routes =>
            {
                routes.MapHub<ConnectionHub>("/connectionHub");
            });
            app.UseMvc(routes =>
            {
                routes.MapRoute(
                    name: "default",
                    template: "{controller=Home}/{action=Index}/{id?}");
            });
        }

然后在您的js代码中

(function () {
        var connection = new signalR.HubConnectionBuilder().withUrl("/connectionHub").build();
 
        connection.start().then(function () {
            console.log("connected");
 
            connection.invoke('getConnectionId')
                .then(function (connectionId) {
                    sessionStorage.setItem('conectionId', connectionId);
                    // Send the connectionId to controller
                }).catch(err => console.error(err.toString()));;
 
 
        });
 
        $("#sendmessage").click(function () {
            var connectionId = sessionStorage.getItem('conectionId');
            connection.invoke("Send", connectionId);
        });
 
        connection.on("ReceiveMessage", function (message) {
            console.log(message);
        });
 
    })();