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

查看:1018
本文介绍了服务器发送事件(EventSource的)标准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.

这是服务器端的code我想(包括来自各个岗位几次失败的尝试):

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}\n\n" & 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 <一个href=\"https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#Event_stream_format\"相对=nofollow>所期望的特定格式,并将引发的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

字段数据之一事件 ID 重试,或空评论(由EventSource的被忽略)。

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

数据可以跨越多行,但每个那些行必须以启动数据:

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写,你不能使用 \\ n 转义序列;你必须使用 vbLf CHR(10)

Note: If you are writing in VB.NET, you can't use the \n escape sequence; 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的部分原因是客户端将尝试重新打开的连接,这将再次被服务器立即关闭;由此产生接近 - >重新开始循环也可以在这里看到

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.

,而不是从该方法排出的,该方法应该有某种形式的循环将被连续地写入到响应流的

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) + "\n\n");
                }
                Response.Flush();
                Thread.Sleep(1000);
            } while (true);
        }
    }
}

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

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