在ASP中根据服务器发送事件的流存储SessionID.净框架



我在ASP的API内使用服务器发送的事件。. Net框架,我已经有sessionId()HttpContext.Current.Session.SessionID)在API控制器动作中,但我需要在OnStreamAvailable方法中访问它,所以我可以将它作为键添加到字典中。

Index是Endpoint,如何添加sessionId而不是Guid到字典的键??

[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
public class SSEController : ApiController
{
private static readonly uint HEARTBEAT_INTERVAL = 10; //10 seconds
private static readonly ConcurrentDictionary<String, StreamWriter> _streams = new ConcurrentDictionary<String, StreamWriter>();

[System.Web.Http.Route("SSE/")]
[System.Web.Http.HttpGet]
public HttpResponseMessage Index(HttpRequestMessage request)
{
var sessionId = HttpContext.Current.Session.SessionID;
var response = request.CreateResponse();
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Cache-Control", "no-cache, must-revalidate");
response.Content = new PushStreamContent(OnStreamAvailable, "text/event-stream");
return response;
}
[System.Web.Http.HttpGet]
[System.Web.Http.Route("SSE/SendMessage")]
public void SendMessage(String name)
{
var d = JsonConvert.SerializeObject(new { data = name });
MessageCallback(d);
}

public async Task OnStreamAvailable(Stream stream, HttpContent headers, TransportContext context)
{
StreamWriter streamwriter = new StreamWriter(stream)
{
AutoFlush = true
};
await streamwriter.WriteLineAsync($"event: info");
await streamwriter.WriteLineAsync($"data: Connected 😇nn");
await streamwriter.WriteLineAsync();
_streams.TryAdd(Guid.NewGuid().ToString(), streamwriter);

}
public static void MessageCallback(String data = "", String EVENT = "message")
{
foreach (var keyValuePair in _streams)
{
try
{
keyValuePair.Value.WriteLine($"event: {EVENT}");
keyValuePair.Value.WriteLine($"data: {data} nn");
keyValuePair.Value.WriteLine();
}
catch (Exception ex)
{
keyValuePair.Value.Close();
keyValuePair.Value.Dispose();
_streams.TryRemove(keyValuePair.Key, out _);
}
}
}

}

实际上,这个问题很简单,在与同事讨论后,他建议我应该声明一个非静态全局变量,它将只在当前请求中起作用,所以我可以在OnStreamAvailable方法中使用该变量。

我确实这样做了,并测试了它,它工作完美!

所以这是解决方案:

private static readonly uint HEARTBEAT_INTERVAL = 10; //10 seconds
public static readonly ConcurrentDictionary<String, StreamWriter> _streams = new ConcurrentDictionary<String, StreamWriter>();
👉private String sessionIdOfCurrentRequest;

[System.Web.Http.Route("SSE/")]
[System.Web.Http.HttpGet]
public HttpResponseMessage Index(HttpRequestMessage request)
{
👉sessionIdOfCurrentRequest = HttpContext.Current.Session.SessionID.ToString(); 
var response = request.CreateResponse();
response.Headers.Add("Access-Control-Allow-Origin", "*");
response.Headers.Add("Cache-Control", "no-cache, must-revalidate");
response.Content = new PushStreamContent(OnStreamAvailable, "text/event-stream");
return response;
}
public async Task OnStreamAvailable(Stream stream, HttpContent headers, TransportContext context)
{
StreamWriter streamwriter = new StreamWriter(stream)
{
AutoFlush = true
};
await streamwriter.WriteLineAsync($"event: info");
await streamwriter.WriteLineAsync($"data: Connectednn");
await streamwriter.WriteLineAsync();
👉_streams.TryAdd(sessionIdOfCurrentRequest, streamwriter);

}

最新更新