Мне бы хотелось, чтобы веб-приложение ASPNetCore2.0, над которым я работаю, отправляло уведомление конкретным пользователям с помощью SignalR.Я хотел бы вызвать метод концентратора из действия другого контроллера (в отличие от вызова JS клиента).
Я узнал, что это не то, как SignalR предназначен для использования, но я нашел много пользователейу кого было такое же «желание», а также некоторые решения.Я проверил несколько предложенных решений, но самым простым и понятным, по-видимому, был принят ответ на этот пост: Получить Hub Context в SignalR Core из другого объекта .
Итак, я дал емуиди, и я не получаю ошибок вообще.Выходные данные сервера безошибочны, как и вкладки консоли браузера и сети (я использую 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);
}
}
}
Добавил эти биты в метод 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")
И это "_NotifyScriptsPartial.cshtml":
<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\'>×</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();
}
}
}
Есть идеи?