Estoy tratando de crear un proceso de notificación de trabajo utilizando Signalr como notificador. Mi panorama es que tengo un proyecto winforms que controlará las etapas del proceso. El sistema en el que afecta el proceso en un proyecto MVC.
Tal como está, tengo estos proyectos: Proceso (Winforms) Sistema (Framework 4.8 MVC) Servicio (framework 4.8) SignalRSelfHost (Consola)
La capa de Servicio es referenciada por los proyectos de Proceso y Sistema y contiene la lógica para cada paso del proceso. Cuando una etapa comienza o finaliza, debe llamar a los clientes conectados y avisarles.
Inicialmente creé las cosas del señalador en el proyecto del sistema y pude llamar a los métodos de servicio desde los botones en una página con los mensajes de inicio/finalización que se entregaban como era de esperar. Luego creé la aplicación winforms y llamé a los mismos métodos de servicio. Cuando hice esto, no se enviaron mensajes al cliente web.
Vale la pena decir en este punto que el proyecto winforms no sabe nada sobre Signalr, se dejó que el servicio negociara con Signalr usando esto:
var context = GlobalHost.ConnectionManager.GetHubContext<ProcessHub>(); context.Clients.All.StageStarted(stage.started);
Luego me di cuenta de que aunque las dos rutas hacia el servicio ejecutan el mismo código, tal vez los concentradores que están creando están separados y nunca hablarán como uno solo.
Entonces pensé que tal vez necesitaba un servidor de señalización común separado tanto del lado del sistema como del proceso que ambos pueden consumir. Creé una aplicación de consola de notas que actuará como un host propio y que luego se ejecuta como:
http://localhost:8080
Luego puedo volver a apuntar mis etiquetas de script para buscar esa URL en lugar de ../signalr en el lado web de las cosas.
Mi problema ahora es cómo exactamente puedo hacer que WinForms y las aplicaciones web inyecten el contexto correcto en el servicio.
Intenté crear un constructor para mi servicio de esta manera:
private IHubContext<ProcessHub> Clients {get;set;} public ProcessService(IHubContext<ProcessHub> clients) { Clients = clients; }
Pero no estoy usando el núcleo, así que no pude encontrar la manera de crear una instancia de ese servicio desde mi controlador (normalmente usaría DI en .net core y registraría mis servicios). Intenté esto pero claramente estaba mal...
public ProcessController(IHubContext<ProcessHub> clients) { _processService = new ProcessService(clients); }
Esto me dice que necesito un constructor sin parámetros para el controlador. Si creo uno de esos, supongo que no puedo usar el servicio según lo previsto. No he intentado conectar los formularios de ganancias al servicio, ya que supongo que me encontraré con un problema similar.
¿Alguien puede ayudarme con a) estoy ladrando completamente en el árbol equivocado ... b) cómo puedo crear una instancia de mi servicio y hacerle saber sobre el contexto de mi centro.
¡Muchas muchas gracias!
Déjame mostrarte mi solución y está funcionando conmigo, estoy usando asp.NET MVC .net4.6 y winforms .net4.8
[HubName("notifyHub")] public class NotifyHub : Hub { public void Send(string name, string message) { Clients.All.broadcastMessage(name, message); } public Task JoinGroup(string groupName) { return Groups.Add(Context.ConnectionId, groupName); } public Task LeaveGroup(string groupName) { return Groups.Remove(Context.ConnectionId, groupName); } }
public ActionResult CreateCustomer(Customer customer) { if (ModelState.IsValid) { db.Customers.Add(customer); db.SaveChanges(); var notificationHub = Microsoft.AspNet.SignalR.GlobalHost.ConnectionManager.GetHubContext<NotifyHub>(); notificationHub.Clients.Group(YourCustomGroupOfClients.ToString()).UpdateCustomer(customer); return RedirectToAction("Index"); } return View(customer); }
// Create this hub globally just one time public static HubConnection hubConnection = new HubConnection(baseUrl);
readonly IHubProxy stockTickerHubProxy = Globals.hubConnection.CreateHubProxy("notifyHub");
stockTickerHubProxy.On<Customer>("UpdateCustomer", async customer => { try { var oldCust = await db.Customers.FirstOrDefaultAsync(a => a.id == customer.id); if (oldCust == null) { db.Customer.Add(customer); } else { oldCust.Cust_Name = customer.Cust_Name; oldCust.Phone1 = customer.Phone1; } await db.SaveChangesAsync(); if (InvokeRequired) Invoke(new MethodInvoker(delegate { Refresh_DG_Customers(); })); } catch (Exception) { } });