我在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);
}