Próbuję poprawić moją aplikację, która będzie wymagać wywoływania koncentratora z C# zamiast javascript. Obecny workflow do dodawania zadania w mojej aplikacji jest:SignalR: Jak naprawdę wywołać metodę koncentratora z serwera/C#
- dokonać wywołania API, aby dodać dane do bazy danych
- powrót nowy rekord do kontrolera angularjs
- metoda powołać Hub z kontrolerem
- piasta rozgłasza wywołanie do klientów odpowiednio
Chciałbym pominąć wywołanie metody hubu z mojego kontrolera AngularJS i zadzwonić bezpośrednio z mojej metody kontrolera API.
To właśnie moja piasta obecnie wygląda następująco:
public class TaskHub : Hub
{
public void InsertTask(TaskViewModel task)
{
Clients.Caller.onInsertTask(task, false);
Clients.Others.onInsertTask(task, true);
}
}
Istnieje wiele tak wątków tam na ten temat, ale wszystko czytałem musiałby mi dodając następujący kod do mojego kontrolera API:
var hubContext = GlobalHost.ConnectionManager.GetHubContext<TaskHub>();
hubContext.Clients.All.onInsertTask(task);
Istnieje wiele problemów z tym. Przede wszystkim chcę, aby połączenia rozgłaszania klienta istniały w jednej klasie, a nie wywoływane bezpośrednio z mojego kontrolera API. Po drugie, hubContext
jest instancją IHubContext
zamiast IHubCallerConnectionContext
. Oznacza to, że mam dostęp tylko do wszystkich klientów i nie mogę rozgłaszać różnych odpowiedzi na Caller
i Others
, tak jak obecnie robię.
Czy istnieje sposób na prawdziwie wywołanie metody koncentratora z C# i, najlepiej, dostęp do różnych opcji wywołujących? Idealnie, byłbym w stanie zrobić coś tak proste, jak następujących od mojego kontrolera API (lub jeszcze lepiej, to rozwiązanie z DI):
var taskHub = new TaskHub();
taskHub.InsertTask(task);
góry dzięki.
ROZWIĄZANIE
dla potomności, myślałem, że to moje pełne rozwiązanie jak na sugestię osa za.
pierwsze, zmodyfikowany mój javascript (angularjs) Usługa obejmuje identyfikator połączenia SignalR w nagłówku zwyczaj wniosku o wywołanie API, w tym przypadku należy wpisać:
var addTask = function (task) {
var config = {
headers: { 'ConnectionId': connection.id }
};
return $http.post('/api/tasks', task, config);
};
Potem podniósł połączenia ID od wniosku w moim kontroler API po wykonaniu operacji CRUD zastosowanie, a następnie zadzwonił do mojego piasty:
public HttpResponseMessage Post(HttpRequestMessage request, [FromBody]TaskViewModel task)
{
var viewModel = taskAdapter.AddTask(task);
var connectionId = request.Headers.GetValues("ConnectionId").FirstOrDefault();
TaskHub.InsertTask(viewModel, connectionId);
return request.CreateResponse(HttpStatusCode.OK, viewModel);
}
Moja piasta wygląda to gdzie ja teraz tylko za pomocą metod statycznych wywoływane z mojego kontrolera API:
public class TaskHub : Hub
{
private static IHubContext context = GlobalHost.ConnectionManager.GetHubContext<TaskHub>();
public static void InsertTask(TaskViewModel task, string connectionId)
{
if (!String.IsNullOrEmpty(connectionId))
{
context.Clients.Client(connectionId).onInsertTask(task, false);
context.Clients.AllExcept(connectionId).onInsertTask(task, true);
}
else
{
context.Clients.All.onInsertTask(task, true);
}
}
}
Jak widzisz, mam metodę warunkową w mojej metodzie koncentratora, która jest obsługiwana, jeśli wywołanie w centrum nie zostało zainicjowane z części aplikacji po stronie klienta. Byłoby to, gdyby zewnętrzna aplikacja/usługa nazwała moje API. W takiej sytuacji nie byłoby połączenia SignalR i oczywiście wartości nagłówkowej "ConnectionId".Jednak w moim przypadku nadal chciałbym wywołać metodę onInsertTask
dla wszystkich podłączonych klientów, która informuje ich o zmianie danych. To nigdy nie powinno się zdarzyć, ale po prostu włączyłem to do kompletności.
W kontekście wywołania API SignalR nie wie, który klient jest "dzwoniącym". Normalnie wywołania SignalR przechodzą przez ich własne połączenie, które ma ten kontekst. – heavyd
Rozważyłem to, rozważając problem z możliwością wyboru odbiorców. Nie byłem pewien, czy istnieje sposób na "dołączenie" wywołującego wywołania API, ale (myśląc głośno) myślę, że musisz wtedy uruchomić połączenie/koncentrator po stronie klienta. W przypadkach, gdy rozmówca/publiczność nie ma znaczenia, myślę, że nadal powinno być możliwe wywołanie metody koncentratora z C# (kontroler API w moim przypadku) ... – im1dermike