使用SignalR从ASPNetCore MVC应用程序中的控制器操作调用Hub方法

时间:2018-06-12 15:11:35

标签: asp.net-core-2.0 signalr-hub asp.net-core-signalr

我希望ASPNetCore2.0 webapp能够使用SignalR向特定用户发送通知。我想从另一个控制器的操作中调用hub的方法(而不是客户端的JS调用)。

据我所知,这不是SignalR的用途,但我发现很多用户都有同样的愿望'还有一些解决方案。 我已经检查了几个建议的解决方案,但最简单和更清晰的似乎是这篇文章的接受答案:Get Hub Context in SignalR Core from within another object

所以我试了一下,我没有任何错误。服务器的输出没有错误,浏览器的控制台和网络选项卡也是如此(我使用的是Chrome)。调试时,流程顺畅,程序完全按照应有的方式执行...除非用户没有收到任何通知......

你们有没有发现这个问题?

我创建了一个包含集线器共享方法的类:

using Microsoft.AspNetCore.SignalR;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace WebApp.Hubs
{
    public class HubMethods
    {
        private readonly IHubContext<PostsHub> _hubContext;

        public HubMethods(IHubContext<PostsHub> hubContext)
        {
            _hubContext = hubContext;
        }

        public async Task Notify(string postId, string sender, List<string> users)
        {
            await _hubContext.Clients.Users(users).SendAsync("Notify", sender, postId);
        }
    }
}

然后我创建了一个集线器:

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.SignalR;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace WebApp.Hubs
{
    [Authorize]
    public class PostsHub : Hub
    {
        private HubMethods _hubMethods;

        public PostsHub(HubMethods hubMethods)
        {
            _hubMethods = hubMethods;
        }

        public async Task Notify(string postId, string sender, List<string> users)
        {
            await _hubMethods.Notify(postId, sender, users);
        }
    }
}

将这些位添加到Startup的ConfigureServices方法:

[...]// Services before these...
services.AddSignalR();
services.AddScoped<HubMethods>();

services.AddMvc();

启动配置方法:

app.UseSignalR(routes =>
{
    routes.MapHub<PostsHub>("/postshub");
});

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "default",
        template: "{controller=Home}/{action=Index}/{id?}");
});

然后这些线到视图:

<script src="~/lib/signalr/signalr.js"></script>
@await Html.PartialAsync("_NotifyScriptsPartial")

这是&#34; _NotifyScriptsPartial.cshtml&#34;:

<script>
    var connection = new signalR.HubConnectionBuilder().withUrl('/PostsHub').build();

    connection.on('Notify', function (sender, postId) {
        var post = postId;
        var sentBy = sender;
        var content = '<a href=\'#\' class=\'close\' data-dismiss=\'alert\' aria-label=\'close\'>&times;</a>' +
        'You just received a new comment from <strong>' +
        sentBy + '</strong>. Click <a href = \'#\' class=\'alert-link\' >here</a> to view the post.'
        var alert = document.createElement('div');
        alert.classList.add('alert', 'alert-info', 'alert-dismissible');
        alert.html(content);
        document.getElementById('pageContent').appendChild(alert);
    });
</script>

最后,在应该发送通知的控制器中,我添加了这些:

public class PostsController : Controller
{
    private readonly HubMethods _hubMethods;

    public PostsController(HubMethods hubMethods)
    {
        _hubMethods = hubMethods;
    }

    // POST: Create a new post
    [Authorize]
    [HttpPost]
    public async Task<IActionResult> Create(DetailsModel model, List<string> readers)
    {
        if (ModelState.IsValid)
        {

        // Do stuff here... including creating the newPostId, userId and receipients variables used below

            await _hubMethods.Notify(newPostId, userId, receipients);

            // Do more stuff and eventually...

            return View();
        }
    }
}

有什么想法吗?

1 个答案:

答案 0 :(得分:0)

在Asp.Net Core 2.1中,我可以像这样使用集线器,它可以解决我的问题,而且您在控制器中也使用了这样的集线器。希望对您有所帮助。

SortDescription

我可以从浏览器的控制台获取“数据”文本。如果您在项目中使用jQuery,请在DataContext之间添加这些代码,因为您试图加载部分html,而我认为您的代码需要在ready()事件之后运行。对不起,如果我误会了你。