google-apigoogle-api-dotnet-clientgoogle-email-migration

Google.Apis.Email_Migration_v2


I am attempting to retrieve the HttpStatusCode from every UploadAsync method call. I need the status code as to properly perform an exponential back-off algorithm to retry a failed upload, display an error message to the user when not retrying the upload and to report success of the upload. I do not care how it is received, so long as it is clean and not being parsed from the Exception.Message (string) property like Tor Jonsson suggested in the link provided below.

To force the "Bad Request Error [400]" I simply provided an invalid userkey (email) in the constructor for MailResource.InsertMediaUpload.
e.g. MailResource.InsertMediaUpload(mailItem, "invalidEmail@domain.com", stream, "message/rfc822")

Problem

1) GoogleApiException.HttpStatusCode is always 0 (unavailable). Even when Exception.Message appears to contain a status code in brackets. e.g. [400]
2) Cannot find GoogleApiRequestException.

Questions
1) What is the best way to perform the exponential back-off algorithm???
2) Is this the expected behaviour for this property in this case?
3) Does GoogleApiRequestException still exist, if so where?

Side Note:
I also noticed that the GoogleApiRequestException class is no longer in the same file as GoogleApiException class. Has it been moved to another namespace or deleted? Because I would like to attempt to catch a GoogleApiRequestException object and grab its RequestError object.

I added links to the two diffs for what I mean:

Before: http://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis/GoogleApiException.cs?r=a8e27790f8769c1d6aaae030bb46c79daa7cdbad

After: http://code.google.com/p/google-api-dotnet-client/source/browse/Src/GoogleApis/GoogleApiException.cs?r=d6f06e92d90b635c179013e2c287b42b82909c09

Sources

I'm using the latest binaries from NuGet (1.6.0.8-beta)

The only question I found related to my problem: (Can only post two links... heres the raw) stackoverflow.com/questions/18985306/httpstatuscode-not-set-in-exceptions-when-using-google-net-apis

Code: (Using a custom logger to write to debugview)

    public int Index; // Used to Id the process
    private void TryUpload(MailResource.InsertMediaUpload upload, out IUploadProgress uploadProgress, out bool retryUpload)
    {
        uploadProgress = null;
        retryUpload = false;
        CancellationToken token;

        try
        {
            uploadProgress = upload.UploadAsync(token).Result;

            if (uploadProgress.Exception != null)
            {
                _logger.WriteTrace("EXCEPTION!!! Type: {0}", uploadProgress.Exception.GetType().ToString()); // Remove:

                // *) Handle all of the various exceptions
                if (uploadProgress.Exception is JsonReaderException)
                {
                    JsonReaderException jreEx = uploadProgress.Exception as JsonReaderException;
                    _logger.WriteTrace("JsonReaderException-> Message: {0}", jreEx.Message);
                }

                if (uploadProgress.Exception is TokenResponseException)
                {
                    TokenErrorResponse trEx = uploadProgress as TokenErrorResponse;
                    _logger.WriteTrace("TokenErrorResponse-> Message: {0}", trEx.Error);
                }

                if (uploadProgress.Exception is HttpRequestValidationException)
                {
                    HttpRequestValidationException hrvEx = uploadProgress.Exception as HttpRequestValidationException;
                    _logger.WriteTrace("HttpRequestValidationException-> Message: {0}", hrvEx.Message);
                    _logger.WriteTrace("HttpRequestValidationException-> Status Code: {0}", hrvEx.GetHttpCode());
                }

                if (uploadProgress.Exception is GoogleApiException)
                {
                    GoogleApiException gApiEx = uploadProgress.Exception as GoogleApiException;
                    _logger.WriteTrace("GoogleApiException-> Message: {0}", gApiEx.Message);
                    _logger.WriteTrace("GoogleApiException-> Status Code: {0}", gApiEx.HttpStatusCode);
                }
            }
        }
        catch (Exception ex)
        {
            _logger.WriteTrace(ex, "An exception occured while uploading...");
        }
        finally
        {
            if (uploadProgress != null)
                _logger.WriteTrace("Upload Completed... Status: {0} Exception?: {1}", 
                    uploadProgress.Status, 
                    (uploadProgress.Exception == null) ? "None" : uploadProgress.Exception.ToString());
            else
                _logger.WriteTrace("Upload Aborted... Exited without returning a status!");
        }
    }

Output Snippet
[5224] (T101) VSLLC: EXCEPTION!!! Type: Google.GoogleApiException
[5224] (T101) VSLLC: GoogleApiException-> Message: Google.Apis.Requests.RequestError
[5224] Bad Request [400]
[5224] Errors [
[5224] Message[Bad Request] Location[ - ] Reason[badRequest] Domain[global]
[5224] ]
[5224] (T101) VSLLC: GoogleApiException-> Status Code: 0
[5224] (T101) VSLLC: Upload Completed... Status: Failed Exception?: The service admin has thrown an exception: Google.GoogleApiException: Google.Apis.Requests.RequestError
[5224] Bad Request [400]
[5224] Errors [
[5224] Message[Bad Request] Location[ - ] Reason[badRequest] Domain[global]
[5224] ]
[5224]
[5224] at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
[5224] at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
[5224] at Microsoft.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
[5224] at Google.Apis.Upload.ResumableUpload`1.d__0.MoveNext() in c:\code\google.com\google-api-dotnet-client\default\Tools\Google.Apis.Release\bin\Debug\output\default\Src\GoogleApis\Apis[Media]\Upload\ResumableUpload.cs:line 373


Sorry for the extensive post! Thanks for your time!


Solution

    1. The library already supports exponential back-off for 503 responses. In case of 400 (bad request) you should not retry, because you will get the same response over and over again. Take a look in the service initializer parameter DefaultExponentialBackOffPolicy You can also take a look in our ExponentialBackOff implementation. BackOffHandler wraps the logic and implements unsuccessful response handler and exception handler.
    2. GoogleApiRequest doesn't exists anymore.
    3. It looks like we are not setting the status code properly, as you can find here. I open a new issue in our issue tracker, available here - https://code.google.com/p/google-api-dotnet-client/issues/detail?id=425. Feel free to add more content to it.