Asp.net Core 3.1 SSE EventSource返回MIME类型错误问题咨询
问题根因
该错误是代码逻辑不兼容ASP.NET Core 运行环境导致的,无需修改Startup.cs默认配置即可解决:
你当前使用的是ASP.NET Framework 时代的SSE写法,ASP.NET Core 中[ApiController]特性会自动将控制器方法的返回值序列化为JSON,直接返回HttpResponseMessage类型时,框架不会将其识别为原生HTTP响应,反而会把整个对象序列化为JSON结构,导致响应头的Content-Type被自动设置为application/json,你代码里配置的text/event-stream完全不生效。同时PushStreamContent类本身不属于ASP.NET Core 原生类库,写法不适配当前环境。
修正方案
1. 重写SSE订阅接口
直接操作当前请求的HttpContext响应对象,手动配置SSE所需的响应头:
[ApiController] [Route("/SSE/[action]")] public class SSEController : Controller { private static ConcurrentBag<StreamWriter> clients = new ConcurrentBag<StreamWriter>(); [HttpPost] public async Task SSECallbackMsg() { await CallbackMsg("test"); } private async Task CallbackMsg(string content) { // SSE消息必须符合格式:data: {内容}\n\n,否则前端EventSource无法触发message事件 var sseMessage = $"data: {content}\n\n"; var invalidClients = new List<StreamWriter>(); foreach (var client in clients) { try { if (client.BaseStream.CanWrite) { await client.WriteAsync(sseMessage); await client.FlushAsync(); // 如果不需要保持长连接,单次推送后可以释放,否则不要执行Dispose // client.Dispose(); // invalidClients.Add(client); } else { invalidClients.Add(client); } } catch (Exception) { invalidClients.Add(client); } } // 清理失效客户端 foreach (var invalidClient in invalidClients) { clients.TryTake(out _); invalidClient.Dispose(); } } [HttpGet] public async Task GETSubscibe() { // 配置SSE所需响应头 Response.Headers.Add("Content-Type", "text/event-stream"); Response.Headers.Add("Cache-Control", "no-cache"); Response.Headers.Add("Connection", "keep-alive"); await Response.Body.FlushAsync(); // 把当前客户端加入连接池 var clientWriter = new StreamWriter(Response.Body, Encoding.UTF8); clients.Add(clientWriter); // 保持长连接不返回,直到连接断开 await Task.Delay(Timeout.Infinite, HttpContext.RequestAborted); } }
2. 可选跨域配置
如果前端页面和服务端地址端口不一致,需要在Startup.cs中添加CORS配置允许跨域请求:
- 在
ConfigureServices方法中添加:
services.AddCors(options => { options.AddPolicy("AllowSSE", policy => { policy.AllowAnyHeader() .AllowAnyMethod() .AllowCredentials() .WithOrigins("你的前端地址,比如http://localhost:8080"); }); });
- 在
Configure方法中,UseRouting之后、UseAuthorization之前添加:
app.UseCors("AllowSSE");
其他注意事项
- SSE的消息格式必须严格遵循
data: 消息内容\n\n的规范,缺少前缀或换行符都会导致前端无法正常接收消息 - 原代码中推送完消息立即释放
StreamWriter会直接断开长连接,EventSource会按照默认规则自动重连,如果需要持续推送不要主动释放连接对象
内容的提问来源于stack exchange,提问作者Hem Shivam
相关产品推荐
相关产品推荐

