protected override async Task OnReconnected(IRequest request, String connectionId) { Log("Entered"); if (_asyncLocalScopeOperation.Value != null) { throw new InvalidOperationException("Expected empty operation scope."); } IServiceScope opScope = _asyncLocalScopeRequest.Value?.Scope.ServiceProvider.CreateScope() ?? this.rootServiceProvider.CreateScope(); using (ScopeWrapper sw = new ScopeWrapper(opScope)) { _asyncLocalScopeOperation.Value = sw; Log("Created operation scope: " + sw.Id); try { await base.OnReconnected(request, connectionId).ConfigureAwait(false); } finally { if (_asyncLocalScopeOperation.Value != sw) { throw new InvalidOperationException("Operation Scope has changed unexpectedly."); } _asyncLocalScopeOperation.Value = null; } Log("Disposing operation scope: " + sw.Id); } Log("Leaving"); }
private static void Log(String message, [CallerMemberName] String callerName = null) { ScopeWrapper requestScope = _asyncLocalScopeRequest.Value; ScopeWrapper opScope = _asyncLocalScopeOperation.Value; String requestScopeStr = requestScope == null ? "null" : "set " + requestScope.Id; String operationScopeStr = opScope == null ? "null" : "set " + opScope.Id; String format = String.Format(CultureInfo.InvariantCulture, "{0} - {1} - Request scope: {2}. Operation scope: {3}.", callerName, message, requestScopeStr, operationScopeStr); Debug.WriteLine(format); }
// Originally I thought `ProcessRequest` was invoked for every operation/request and its lifespan was that of the request (while it executes OnConnected, OnReceived, OnDisconnected, and OnReconnected) - but it turns out I was wrong. // It depends on the Transport - e.g. longPolling will run `OnReceived` inside `ProcessRequest`, but with WebSockets `OnReceived` is not (but `OnConnected` is). public override async Task ProcessRequest(HostContext context) { Log("Entered"); if (_asyncLocalScopeRequest.Value != null) { throw new InvalidOperationException("Expected empty request scope."); } if (_asyncLocalScopeOperation.Value != null) { throw new InvalidOperationException("Expected empty operation scope."); } using (ScopeWrapper sw = new ScopeWrapper(this.rootServiceProvider.CreateScope())) { _asyncLocalScopeRequest.Value = sw; Log("Created request scope: " + sw.Id); try { await base.ProcessRequest(context).ConfigureAwait(false); } finally { if (_asyncLocalScopeRequest.Value != sw) { throw new InvalidOperationException("Request Scope has changed unexpectedly."); } _asyncLocalScopeRequest.Value = null; } Log("Disposing request scope: " + sw.Id); } Log("Leaving"); }