Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/263.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ASPNET核心服务器已发送事件/响应刷新_C#_Asp.net Core_Asp.net Core Mvc_Asp.net Core 1.0 - Fatal编程技术网

C# ASPNET核心服务器已发送事件/响应刷新

C# ASPNET核心服务器已发送事件/响应刷新,c#,asp.net-core,asp.net-core-mvc,asp.net-core-1.0,C#,Asp.net Core,Asp.net Core Mvc,Asp.net Core 1.0,虽然没有官方文档,但有人知道如何使用ASP.NET核心实现SSE吗 我怀疑一个实现可能会使用自定义中间件,但在控制器操作中可能会这样做?客户端-wwwroot/index.html 在页面加载时,为http://www.somehost.ca/sseurl。然后将其事件写入控制台 <body> <script type="text/javascript"> var source = new EventSource('sse');

虽然没有官方文档,但有人知道如何使用ASP.NET核心实现SSE吗

我怀疑一个实现可能会使用自定义中间件,但在控制器操作中可能会这样做?

客户端-wwwroot/index.html 在页面加载时,为
http://www.somehost.ca/sse
url。然后将其事件写入控制台

<body>
    <script type="text/javascript">

        var source = new EventSource('sse');

        source.onmessage = function (event) {
            console.log('onmessage: ' + event.data);
        };

        source.onopen = function(event) {
            console.log('onopen');
        };

        source.onerror = function(event) {
            console.log('onerror');
        }

    </script>
</body>
服务器端备选方案#2-使用控制器 控制器执行与中间件完全相同的操作

[Route("/api/sse")]
public class ServerSentEventController : Controller
{
    [HttpGet]
    public async Task Get()
    {
        var response = Response;
        response.Headers.Add("Content-Type", "text/event-stream");

        for(var i = 0; true; ++i)
        {
            await response
                .WriteAsync($"data: Controller {i} at {DateTime.Now}\r\r");

            response.Body.Flush();
            await Task.Delay(5 * 1000);
        }
    }
}
Firefox中的客户端控制台输出 这是Firefox控制台窗口中的结果。每五秒钟就有一条新消息到达

onopen
onmessage: Message 0 at 4/15/2016 3:39:04 PM
onmessage: Message 1 at 4/15/2016 3:39:09 PM
onmessage: Message 2 at 4/15/2016 3:39:14 PM
onmessage: Message 3 at 4/15/2016 3:39:19 PM
onmessage: Message 4 at 4/15/2016 3:39:24 PM
参考资料:


服务器发送的事件可以完全在控制器操作中实现

这是基于Shaun Luttin的回答,但它更像是一个真实的例子,它将无限期地保持打开连接,并将消息发送到
EventSource
,以响应正在创建的消息

using Example.Models;
using Example.Repositories;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Example.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class SseMessagesController : ControllerBase
    {
        private readonly IMessageRepository messageRepository;
        private readonly JsonSerializerSettings jsonSettings;

        public SseMessagesController(IMessageRepository messageRepository)
        {
            this.messageRepository = messageRepository;
            this.jsonSettings = new JsonSerializerSettings();
            jsonSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        }

        [HttpGet]
        public async Task GetMessages(CancellationToken cancellationToken)
        {
            Response.StatusCode = 200;
            Response.Headers.Add("Content-Type", "text/event-stream");

            EventHandler<MessageCreatedArgs> onMessageCreated = async (sender, eventArgs) =>
            {
                try
                {
                    var message = eventArgs.Message;
                    var messageJson = JsonConvert.SerializeObject(message, jsonSettings);
                    await Response.WriteAsync($"data:{messageJson}\n\n");
                    await Response.Body.FlushAsync();
                }
                catch (Exception)
                {
                    // TODO: log error
                }
            };
            messageRepository.MessageCreated += onMessageCreated;

            while (!cancellationToken.IsCancellationRequested) {
                await Task.Delay(1000);
            }

            messageRepository.MessageCreated -= onMessageCreated;
        }
    }
}
使用Example.Models;
使用示例库;
使用Microsoft.AspNetCore.Http;
使用Microsoft.AspNetCore.Mvc;
使用Newtonsoft.Json;
使用Newtonsoft.Json.Serialization;
使用制度;
使用系统线程;
使用System.Threading.Tasks;
名称空间示例.控制器
{
[路由(“api/[控制器]”)]
[ApiController]
公共类SseMessagesController:ControllerBase
{
私有只读IMessageRepository messageRepository;
私有只读JsonSerializerSettings jsonSettings;
公共SseMessagesController(IMessageRepository messageRepository)
{
this.messageRepository=messageRepository;
this.jsonSettings=new JsonSerializerSettings();
jsonSettings.ContractResolver=新的CamelCasePropertyNamesContractResolver();
}
[HttpGet]
公共异步任务GetMessages(CancellationToken CancellationToken)
{
Response.StatusCode=200;
添加(“内容类型”、“文本/事件流”);
EventHandler onMessageCreated=async(发送方,eventArgs)=>
{
尝试
{
var message=eventArgs.message;
var messageJson=JsonConvert.SerializeObject(message,jsonSettings);
wait Response.WriteAsync($“数据:{messageJson}\n\n”);
等待响应。Body.FlushAsync();
}
捕获(例外)
{
//TODO:日志错误
}
};
messageRepository.MessageCreated+=onMessageCreated;
而(!cancellationToken.IsCancellationRequested){
等待任务。延迟(1000);
}
messageRepository.MessageCreated-=onMessageCreated;
}
}
}
每当
EventSource
连接到
/api/ssemessages
时,我们将向消息存储库上创建的
消息添加一个事件委托。然后,我们每1秒检查一次
EventSource
是否已关闭,这将导致请求被取消。取消请求后,我们将删除事件委托

事件委托从事件参数中获取
消息
对象,将其序列化为JSON(在返回对象结果时使用驼峰大小写与ASP.NET内核的默认行为一致),将JSON写入主体,并刷新主体的流以将数据推送到
事件源

有关创建事件委托的详细信息,请参见和


另外,如果你在Nginx后面主持这个节目,你会想阅读和。

你说的是信号机吗?不,核心还没有信号机。事实上,信号机3在rc1决赛中可以在官方nuget提要以及myget stables和nightlies上看到。这就是我问的原因。但是,当ASP.NET Core 1.0按照路线图上提到的那样发布时,它还没有准备好发布。谢谢,我没有意识到这一点。我会看看源代码,也许我会发现一些有用的东西。在这种情况下,完整的框架有点过头了。我有一个单向通道,使用websockets实现,我正在寻找使其更简单的方法。pre-Core:谢谢Shaun,你的答案看起来非常全面。我将很快转移信誉点,我在本地机器和Azure上的RC1上复制这个仍然有问题。看起来在每次迭代中都没有刷新响应。也许现在正是转向RC2之前的好时机。谢谢你把话题推到最前沿:)现在我可以确认,这在RC2之前的版本上是可以预期的,但在RC1上不是。@zygimanta是个好东西。RC1产品很好,是一款“上线”产品。尽管RC2是未来,所以开始学习它是个好主意。我很高兴听到这对你有用。:)我还注意到您正在使用IHttpContextAccessor,而不是继承ControllerBase并调用this.HttpContext。我以前在RC1上没见过这个。这样做有什么好处吗?@Zygimantas我不确定一个比另一个有什么好处。我知道新的MVC支持普通的旧crl对象(POCO)控制器。换句话说,这些控制器不是从
Controller
类继承的。我倾向于放弃简单项目的继承,以避免开销。继承
控制器
类有很多好处。可以说,它有很多助手方法。这是课堂。查看它的公共/保护成员,看看它给了你什么:嘿,delial,谢谢你的回答!不知道你是否知道,但这个问题已经问了3年多了——如果你想把精力集中在新问题上,你可以使用“最新”标签来实现这一点。例如,是指向最新C#问题的链接。您有GitHub回购协议还是gi
using Example.Models;
using Example.Repositories;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Example.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class SseMessagesController : ControllerBase
    {
        private readonly IMessageRepository messageRepository;
        private readonly JsonSerializerSettings jsonSettings;

        public SseMessagesController(IMessageRepository messageRepository)
        {
            this.messageRepository = messageRepository;
            this.jsonSettings = new JsonSerializerSettings();
            jsonSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        }

        [HttpGet]
        public async Task GetMessages(CancellationToken cancellationToken)
        {
            Response.StatusCode = 200;
            Response.Headers.Add("Content-Type", "text/event-stream");

            EventHandler<MessageCreatedArgs> onMessageCreated = async (sender, eventArgs) =>
            {
                try
                {
                    var message = eventArgs.Message;
                    var messageJson = JsonConvert.SerializeObject(message, jsonSettings);
                    await Response.WriteAsync($"data:{messageJson}\n\n");
                    await Response.Body.FlushAsync();
                }
                catch (Exception)
                {
                    // TODO: log error
                }
            };
            messageRepository.MessageCreated += onMessageCreated;

            while (!cancellationToken.IsCancellationRequested) {
                await Task.Delay(1000);
            }

            messageRepository.MessageCreated -= onMessageCreated;
        }
    }
}