服务器使用标准 asp.net mvc 发送事件(事件源)导致错误 [英] server sent events (eventsource) with standard asp.net mvc causing error

查看:28
本文介绍了服务器使用标准 asp.net mvc 发送事件(事件源)导致错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试处理服务器发送的事件,但我无法让它在 MVC 项目(不是 WebAPI)中工作.我在网上没有找到任何好的样品.

I am trying my hand at server-sent events, but I cannot get it to work within an MVC project (not WebAPI). I haven't found any good samples online.

这是我尝试过的服务器端代码(包括来自各种帖子的几次失败的尝试):

This is the server-side code I tried (including several failed attempts from various posts):

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}

" & DateTime.Now.ToString(), "text/event-stream")
End Function

这里是 Javascript

and here is the 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);
};

出于某种原因,它总是进入onerror,并且那里没有信息它可能是什么类型的错误.

For some reason it's always going into onerror, and there is no information there what type of error it might be.

我做错了什么?

顺便说一句,我不认为这个动作真的应该返回任何东西,因为我的理解是它应该只写一个字符串一个字符串.

BTW, I don't think this action should really return anything, since my understanding is it should only be writing to the stream string by string.

推荐答案

EventSource 期望特定格式,如果流与该格式不匹配,则会引发 onerror -- 一组分隔的字段/值对行通过 :,每行以换行符结尾:

EventSource expects a specific format, and will raise onerror if the stream doesn't match that format -- a set of lines of field/value pairs separated by a :, with each line ending in a newline character:

field: value
field: value

field 可以是 data,event,id,retry 之一, 或者为空评论(将被 EventSource 忽略).

field can be one of data,event,id,retry, or empty for a comment (will be ignored by EventSource).

data 可以跨越多行,但每一行都必须以 data 开头:

data can span multiple lines, but each of those lines must start with data:

每个事件触发器必须以双换行符结束

Each event trigger has to end with a double newline

data: 1
data: second line of message

data: 2
data: second line of second message

注意:如果你在VB.NET中编写,则不能使用 转义序列来编写换行符;你必须使用 vbLfChr(10).

Note: If you are writing in VB.NET, you can't use the escape sequence to write newlines; you have to use vbLf or Chr(10).

顺便说一句,EventSource 应该保持与服务器的开放连接.来自 MDN(重点是我的):

As an aside, EventSource is supposed to hold an open connection to the server. From MDN (emphasis mine):

EventSource 接口用于接收服务器发送的事件.它通过 HTTP 连接到服务器并以文本/事件流格式接收事件而无需关闭连接.

The EventSource interface is used to receive server-sent events. It connects to a server over HTTP and receives events in text/event-stream format without closing the connection.

一旦控制退出MVC控制器方法,结果将被打包并发送到客户端,并且连接将被关闭.EventSource 的一部分是客户端会尝试重新打开连接,这会再次被服务器立即关闭;结果 close ->重新打开循环也可以在这里看到.

Once control exits from an MVC controller method, the result will be packaged up and sent to the client, and the connection will be closed. Part of EventSource is that the client will try reopening the connection, which will once again be immediately closed by the server; the resulting close -> reopen cycle can also be seen here.

该方法不应退出该方法,而应具有某种循环,该循环将不断写入 Response 流.

Instead of exiting from the method, the method should have some sort of loop that will be continuously writing to the Response stream.

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


C# 示例

客户端:

<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>

服务端:

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) + "

");
                }
                Response.Flush();
                Thread.Sleep(1000);
            } while (true);
        }
    }
}

这篇关于服务器使用标准 asp.net mvc 发送事件(事件源)导致错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆