/// <summary> /// Parses the specified exception. /// </summary> /// <param name="ex">Exception to parse.</param> /// <returns>Parsed exception.</returns> /// <exception cref="ArgumentNullException">Exception is null.</exception> /// <exception cref="ArgumentException">Exception is not of type InvalidOperationException.</exception> public static ParsedException Parse(Exception ex) { if (ex == null) { throw new ArgumentNullException("ex"); } if (!(ex is InvalidOperationException)) { throw new ArgumentException("Exception is not of type InvalidOperationException", "ex"); } ParsedException parsedException = new ParsedException(); string messageToBeParsed = ex.Message; if (ex.InnerException != null) { messageToBeParsed = ex.InnerException.Message; } try { StringReader stringReader = new StringReader(messageToBeParsed); XmlErrorResponse errorObject = ParsedException.xmlSerializer.Deserialize(stringReader) as XmlErrorResponse; parsedException = new ParsedException(errorObject); } catch (InvalidOperationException) { } if (String.IsNullOrEmpty(parsedException.Code)) { parsedException.Code = messageToBeParsed; } return(parsedException); }
/// <summary> /// Delegate to invoke the specified operation, and retry if necessary. /// </summary> /// <param name="operation">Operation to invoke.</param> private void InvokeOperationWithRetry(Action operation) { int retryCount = Constants.MaxRetryAttempts; while (retryCount > 0) { try { operation(); // Operation was successful retryCount = 0; } catch (InvalidOperationException ex) { // Operation not successful // De-serialize error message to check the error code from AzureAD Service ParsedException parsedException = ParsedException.Parse(ex); if (parsedException == null) { // Could not parse the exception so it wasn't in the format of DataServiceException throw; } // Look at the error code to determine if we want to retry on this exception switch (parsedException.Code) { // These are the errors we don't want to retry on // Please look at the descriptions for details about each of these case Constants.MessageIdAuthorizationIdentityDisabled: case Constants.MessageIdAuthorizationIdentityNotFound: case Constants.MessageIdAuthorizationRequestDenied: case Constants.MessageIdBadRequest: case Constants.MessageIdContractVersionHeaderMissing: case Constants.MessageIdHeaderNotSupported: case Constants.MessageIdInternalServerError: case Constants.MessageIdInvalidDataContractVersion: case Constants.MessageIdInvalidReplicaSessionKey: case Constants.MessageIdInvalidRequestUrl: case Constants.MessageIdMediaTypeNotSupported: case Constants.MessageIdThrottledPermanently: case Constants.MessageIdThrottledTemporarily: case Constants.MessageIdUnauthorized: case Constants.MessageIdUnknown: case Constants.MessageIdUnsupportedQuery: case Constants.MessageIdUnsupportedToken: { // We just create a new exception with the message // and throw it so that the 'OnException' handler handles it throw new InvalidOperationException(parsedException.Message.Value, ex); } // This means that the token has expired. case Constants.MessageIdExpired: { // Renew the token and retry the operation. This is done as a // part of the operation itself (AddHeaders) this.AccessToken = null; retryCount--; break; } default: { // Not sure what happened, don't want to retry throw; } } } } }