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.