asp.net-mvc server-sent-events eventsource

eventos enviados por el servidor(eventsource) con un error estándar de asp.net mvc que causa un error



asp.net-mvc server-sent-events (1)

EventSource espera un formato específico y generará un onerror si la secuencia no coincide con ese formato: un conjunto de líneas de pares de campo / valor separados por a : cada línea termina en un carácter de nueva línea:

field: value field: value

field puede ser uno de data , event , id , retry o vacío para un comentario (EventSource lo ignorará).

data pueden abarcar varias líneas, pero cada una de esas líneas debe comenzar con data:

Cada evento desencadenante debe terminar con una nueva línea doble

data: 1 data: second line of message data: 2 data: second line of second message

Nota: Si está escribiendo en VB.NET, no puede usar la secuencia de escape /n para escribir líneas nuevas; tienes que usar vbLf o Chr(10) .

Por otro lado, se supone que EventSource mantiene una conexión abierta al servidor. De MDN (énfasis mío):

La interfaz EventSource se usa para recibir eventos enviados por el servidor. Se conecta a un servidor a través de HTTP y recibe eventos en formato de texto / secuencia de eventos sin cerrar la conexión .

Una vez que el control sale de un método de controlador MVC, el resultado se empaquetará y se enviará al cliente, y se cerrará la conexión. Parte de EventSource es que el cliente intentará reabrir la conexión, que nuevamente será cerrada inmediatamente por el servidor; El ciclo de cierre -> reapertura resultante también se puede ver here .

En lugar de salir del método, el método debería tener algún tipo de bucle que escribirá continuamente en la secuencia de Response .

Ejemplo en VB.NET

Imports System.Threading Public Class HomeController Inherits Controller Sub Message() Response.ContentType= "text/event-stream" Dim i As Integer Do i += 1 Response.Write("data: DateTime = " & Now & vbLf) Response.Write("data: Iteration = " & i & vbLf) Response.Write(vbLf) Response.Flush ''The timing of data sent to the client is determined by the Sleep interval (and latency) Thread.Sleep(1000) Loop End Sub End Class

Ejemplo en C #

Lado del cliente:

<input type="text" id="userid" placeholder="UserID" /><br /> <input type="button" id="ping" value="Ping" /> <script> var es = new EventSource(''/home/message''); es.onmessage = function (e) { console.log(e.data); }; es.onerror = function () { console.log(arguments); }; $(function () { $(''#ping'').on(''click'', function () { $.post(''/home/ping'', { UserID: $(''#userid'').val() || 0 }); }); }); </script>

Lado del servidor:

using System; using System.Collections.Concurrent; using System.Threading; using System.Web.Mvc; using Newtonsoft.Json; namespace EventSourceTest2.Controllers { public class PingData { public int UserID { get; set; } public DateTime Date { get; set; } = DateTime.Now; } public class HomeController : Controller { public ActionResult Index() { return View(); } static ConcurrentQueue<PingData> pings = new ConcurrentQueue<PingData>(); public void Ping(int userID) { pings.Enqueue(new PingData { UserID = userID }); } public void Message() { Response.ContentType = "text/event-stream"; do { PingData nextPing; if (pings.TryDequeue(out nextPing)) { Response.Write("data:" + JsonConvert.SerializeObject(nextPing, Formatting.None) + "/n/n"); } Response.Flush(); Thread.Sleep(1000); } while (true); } } }

Estoy intentando suerte en los eventos enviados por el servidor, pero no puedo hacer que funcione dentro de un proyecto MVC (no WebAPI). No he encontrado ninguna buena muestra en línea.

Este es el código del lado del servidor que probé (incluidos varios intentos fallidos de varias publicaciones):

Function GetRows() as ActionResult Dim ret = New HttpResponseMessage '' ret.Content.w '' Return ret Response.ContentType = "text/event-stream" Response.Write("data: " & "aaaa") Dim flag = False If flag Then For i = 0 To 100 Response.Write("data: " & i) Next End If Response.Flush() ''Return Content("Abv") ''Return Content(("data: {0}/n/n" & DateTime.Now.ToString(), "text/event-stream") End Function

y aquí está el Javascript

var source = new EventSource("/Tool/GetRows"); source.onmessage = function (event) { document.getElementById("messages").innerHTML += event.data + "<br>"; }; source.onerror = function (e) { console.log(e); };

Por alguna razón, siempre entra en un onerror , y no hay información sobre qué tipo de error podría ser.

¿Qué estoy haciendo mal?

Por cierto, no creo que esta acción realmente deba devolver nada, ya que entiendo que solo debería estar escribiendo en la secuencia secuencia por secuencia.