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;
                }
            }
        }
Example #2
0
        /// <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;
                }
            }
        }
Example #3
0
 public static SimpleAwaiter <TResult> ContinueOnScope <TResult>(this Task <TResult> @this, FlowingOperationContextScope scope)
 {
     return(new SimpleAwaiter <TResult>(@this, scope.BeforeAwait, scope.AfterAwait));
 }