来自Controller .Net Core 2.1的Call Signalr方法

时间:2018-10-09 09:18:43

标签: c# asp.net-core-mvc signalr signalr-hub asp.net-core-signalr

我正在尝试从(ASP.NET Core)MVC控制器调用signalr Hub类中的方法,但是我找不到在线示例来演示如何操作。

注意:有很多将旧版本的Signalr与.Net Framework结合使用的示例,但是我看不到这些示例说明如何在.Net Core中执行此操作。

我需要将MVC操作结果中的ID直接传递到我的集线器,而无需将该ID传递到页面,然后必须将客户端连接重新传递到集线器。

public class ChatHub : Hub
{ 
    public async Task DoSomething(int id)
    {            
        //// Something in here.
    }
}



public class HomeController : Controller
{
    private readonly IHubContext<ChatHub> _hubContext;

    public HomeController(IHubContext<ChatHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task<ActionResult> Index(int id) 
    {

         //// Call the DoSomething method from here, passing the id across.
         await _hubContext.Clients.All.SendAsync("AddToGroup", groupId);
    }
}

请问有办法吗? (还是我看错了方向,有没有更好的方法来达到相同的结果?)

更新:如果我将Id传递到视图中,然后使用JavaScript调用Hub,那么它将调用DoSomething方法,因此我可以看到它们全部正确地挂在一起,但是当我尝试用C#来调用它。

3 个答案:

答案 0 :(得分:3)

我认为您误会了它们是如何协同工作的(直到昨天我都做过同样的事情),中心代码是供客户端脚本代码调用然后执行的,而IHubContext是用作要发送到客户端的强类型方法

集线器

// This class is used by the JavaScript Client to call into the .net core application.
public class ChatHub : Hub<IChatClient>
{

    public static ConcurrentDictionary<string, string> Connections = new ConcurrentDictionary<string, string>();

    // As an example, On connection save the user name with a link to the client Id for later user callback
    public override Task OnConnectedAsync()
    {
        var user = Context.User.Identity.Name;

        Connections.AddOrUpdate(this.Context.ConnectionId, user, (key, oldValue) => user);

        return base.OnConnectedAsync();
    }

    public override Task OnDisconnectedAsync(Exception exception)
    {
        // Do something on disconnect.
    }

    // Add other methods you want to be able to call from JavaScript side in here...
    public void SendMessage(int id, string message)
    {
        // Message doing stuff here.
    }
}

ChatClient界面

// This provides strongly-typed methods that you'll have on the Client side but these don't exist on the server.
public interface IChatClient
{
    //So this method is a JS one not a .net one and will be called on the client(s)
    Task DoSomething(int id);

    Task NotificationUpdate(int id, string message);
}

控制器

public class HomeController : Controller
{
    private readonly IHubContext<ChatHub, IChatClient> _hubContext;

    public HomeController(IHubContext<ChatHub, IChatClient> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task<ActionResult> Index(int id) 
    {

         // This calls the method on the Client-side
         await _hubContext.Clients.All.DoSomething(id);
    }
}

答案 1 :(得分:2)

您可以使用IHubContext来做到这一点:

public class HomeController : Controller
{
    private readonly IHubContext<ChatHub> _hubContext;

    public HomeController(IHubContext<ChatHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task<ActionResult> Index(int id) 
    {
         //// Call the DoSomething method from here, passing the id across.
         await _hubContext.Clients.All.SendAsync("DoSomething", id);
    }
}

Full docs and examples here.

答案 2 :(得分:-1)

似乎您需要的是Strogly-typed hub,它将允许从控制器调用集线器方法,这是上面链接中的基本代码示例(适用于您的代码):

public class ChatHub : Hub<IChatHub>
{
    public async Task DoSomething(int id)
    {
        // 
    }
}

public interface IChatHub
{
    Task DoSomething(int id);
}

然后,您可以这样调用IHubContext

public class HomeController : Controller
{
    private readonly IHubContext<ChatHub, IChatHub> _hubContext;

    public HomeController(IHubContext<ChatHub, IChatHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task<ActionResult> Index(int id) 
    {
         await _hubContext.Clients.All.DoSomething(id);
    }
}

希望这对您有所帮助。