protected override async Task <TResult> InterceptAsyncCore <TResult>(IInvocation invocation, Func <IInvocation, Task <TResult> > proceed) { if (!IsServiceMethodInvocation(invocation)) { return(await proceed(invocation)); } string accessToken = await m_TokenService.GetTokenAsync(); var channel = m_GetClientChannel(); using (var scope = new FlowingOperationContextScope(channel)) { var httpRequestProperty = new HttpRequestMessageProperty(); httpRequestProperty.Headers[HttpRequestHeader.Authorization] = $"Bearer {accessToken}"; OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty; try { // Try invoke service method return(await proceed(invocation).ContinueOnScope(scope)); } catch (AggregateException ex) { if (Helpers.CouldBeExpiredTokenException(ex.InnerException)) { // Try to refresh token string newToken = await m_TokenService.GetTokenAsync().ContinueOnScope(scope); if (newToken == accessToken) { // Unauthorized not because of token being expired but for other reasons throw; } httpRequestProperty.Headers[HttpRequestHeader.Authorization] = $"Bearer {newToken}"; return(await proceed(invocation).ContinueOnScope(scope)); } throw; } } }
/// <summary> /// Async service method call /// </summary> public static async Task <TResult> WrapServiceMethodCallAsync <TResult>( Func <Task <TResult> > invokeServiceMethod, IClientChannel clientChannel, ITokenService tokenService) { string accessToken = await tokenService.GetTokenAsync(); // Using OperationContextScope in "async Dispose" scenario // will cause System.InvalidOperationException : // This OperationContextScope is being disposed on a different thread than it was created. // See https://stackoverflow.com/a/22753055 how to get away with it. using (var scope = new FlowingOperationContextScope(clientChannel)) { var httpRequestProperty = new HttpRequestMessageProperty(); httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = $"Bearer {accessToken}"; OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = httpRequestProperty; try { return(await invokeServiceMethod().ContinueOnScope(scope)); } catch (AggregateException ex) { if (Helpers.CouldBeExpiredTokenException(ex.InnerException)) { // Try to refresh token string newToken = await tokenService.GetTokenAsync().ContinueOnScope(scope); if (newToken != accessToken) { httpRequestProperty.Headers[System.Net.HttpRequestHeader.Authorization] = $"Bearer {newToken}"; return(await invokeServiceMethod().ContinueOnScope(scope)); } } throw; } } }
public static SimpleAwaiter <TResult> ContinueOnScope <TResult>(this Task <TResult> @this, FlowingOperationContextScope scope) { return(new SimpleAwaiter <TResult>(@this, scope.BeforeAwait, scope.AfterAwait)); }