我在日志中看到了这个错误,但我无法弄清楚如何重现它。它不会定期发生。
异常消息:响应开始后无法建立会话。 堆栈跟踪:
at Microsoft.AspNetCore.Session.DistributedSession.Set(String key,Byte [] value)
CustomMiddleware.cs:
public async Task Invoke(HttpContext context, AlertWriter alertWriter, AlertReader alertReader)
{
var sessionAlerts = context.Session.GetString(AlertKey);
if (!string.IsNullOrWhiteSpace(sessionAlerts))
{
var alerts = JsonConvert.DeserializeObject<List<Alert>>(sessionAlerts);
alertReader.Initialize(alerts);
context.Session.Remove(AlertKey);
}
await _next.Invoke(context);
if (context.Response.StatusCode >= 300 && context.Response.StatusCode < 400)
{
alertWriter.Alerts = alertWriter.Alerts.Union(alertReader).ToList();
}
var serializedAlerts = JsonConvert.SerializeObject(alertWriter.Alerts);
//ERROR IS HERE
context.Session.SetString(AlertKey, serializedAlerts);
}
在Startup.cs中,app.UseSession();
是第一个app.Use ...我打电话。
Documentation表示如果&#34;在您已经开始写入响应流后,尝试创建新的会话(即尚未创建会话cookie),则会发生此错误&#34; < / em>的
如何避免此错误?似乎如果我尝试在任何自定义中间件中访问会话,我将不得不检查.AspNetCore.Session cookie是否存在?
答案 0 :(得分:1)
您必须在发送内容之前设置标头。
在await _next.Invoke(..)
之前执行此操作通常是安全的。但是在_next
之后调用它之后,无法保证在链中稍后调用的中间件确实或者没有写入流。
您可以通过缓存响应来绕过它,直到您的中间件完成,但这可能会产生严重的性能影响,因为整个流需要存储在内存中,然后再存储在写入原始流的后续中间件中。在大响应中,这可能会显着增加应用程序的内存使用量。
像
这样的东西using (var buffer = new MemoryStream())
{
var body = context.Response.Body;
context.Response.Body = buffer;
...
await _next.Invoke(...);
// set headers or session
context.Session.SetString(AlertKey, serializedAlerts);
// read buffer and write to body
}