title: Google Drive API V3 update: no exception but doesn't update
body: <p>I'm trying to update a file on google drive with this code:</p>
  
  <pre><code>private async Task UpdateFileAsync(string fullPath, IList&lt;string&gt; parents, string id)
  {
      string mimeT = GetMimeType(fullPath);
      Google.Apis.Drive.v3.Data.File file = new Google.Apis.Drive.v3.Data.File();
      file.Name = System.IO.Path.GetFileName(fullPath);
      //file.MimeType = mimeT;
      //file.Parents = parents;
  
      //using (var fStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
      //{
      //    byte[] byteArray = new byte[fStream.Length];
      byte[] byteArray = System.IO.File.ReadAllBytes(fullPath);
          //await fStream.ReadAsync(byteArray, 0, (int)fStream.Length);
          using (var stream = new MemoryStream(byteArray))
          {
              var request = _DriveService.Files.Update(file, id, stream, mimeT);// .Create(file, stream, mimeT);
              request.AddParents = string.Join(",", parents);
              var progress = await request.UploadAsync();
              if (progress.Exception != null)
                  throw progress.Exception;
          }
      //}
  }
  private string GetMimeType(string fileName)
  {
      string mimeType = "application/unknown";
      string ext = System.IO.Path.GetExtension(fileName).ToLower();
      Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
      if (regKey != null &amp;&amp; regKey.GetValue("Content Type") != null)
          mimeType = regKey.GetValue("Content Type").ToString();
      return mimeType;
  }
  </code></pre>
  
  <p>I haven't touched the commented lines so you can see what have I tried.
  The file is a XML witch I first download, fetching the <code>Id</code> and <code>Parents</code>, and then modify locally so I want to update it.</p>
  
  <p>The local path <code>fullPath</code> comes from a <code>FileInfo.GetFullPath()</code> beforehand, and I've checked it exists and it's correctly updated locally at runtime with a breakpoint.</p>
  
  <p>As you can see, first I tried to set <code>MimeType</code> and <code>Parents</code> directly in the google <code>File</code> object, then I read about the non-writable fields so I deleted that part of the code. I've also tried with various streams, first I used only the <code>FileStream</code>, then I tried both the ways you can see in the code.</p>
  
  <p>I've checked the permissions but I put them here in case I forgot something:</p>
  
  <pre><code>private readonly string[] Scopes = {
          SheetsService.Scope.Spreadsheets,
          DriveService.Scope.DriveFile,
          DriveService.Scope.Drive,
          DriveService.Scope.DriveAppdata,
          DriveService.Scope.DriveMetadata };
  ...
  _Credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
      GoogleClientSecrets.Load(stream).Secrets,
      Scopes,
      "user",
      CancellationToken.None,
      new FileDataStore(credPath, true));
  </code></pre>
  
  <p>The code runs fine, <code>progress.Exception</code> is always null, but the file does not get updated. I can also download and upload files without a problem.</p>
  
  <p>And again I'm pretty sure it's a little thing I'm forgotting, but again it seems that I'm not able to see it. I don't know what's happening.</p>
  
  <p>.</p>
  
  <hr>
  
  <p><strong>Edit:</strong>
  As proposed by DaImTo in the comments I've tried to watch the progress of the upload this way:</p>
  
  <pre><code>private async Task UpdateFileAsync(string fullPath, IList&lt;string&gt; parents, string id)
  {
      try
      {
          string mimeT = GetMimeType(fullPath);
          Google.Apis.Drive.v3.Data.File file = new Google.Apis.Drive.v3.Data.File();
          file.Name = System.IO.Path.GetFileName(fullPath);
          //file.MimeType = mimeT;
          //file.Parents = parents;
  
          using (var fStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
          {
              byte[] byteArray = new byte[fStream.Length];
              //byte[] byteArray = System.IO.File.ReadAllBytes(fullPath);
              await fStream.ReadAsync(byteArray, 0, (int)fStream.Length);
              using (var stream = new MemoryStream(byteArray))
              {
                  var request = _DriveService.Files.Update(file, id, stream, mimeT);// .Create(file, stream, mimeT);
                  request.AddParents = string.Join(",", parents);
                  request.ProgressChanged += (Google.Apis.Upload.IUploadProgress prog) =&gt;
                  {
                      switch (prog.Status)
                      {
                          case Google.Apis.Upload.UploadStatus.Uploading:
                              {
                                  var forget = Log.WriteAsync($"------------- Progreso subida: {prog.BytesSent.ToString()}");
                                  break;
                              }
                          case Google.Apis.Upload.UploadStatus.Completed:
                              {
                                  var forget = Log.WriteAsync("------------- Upload complete.");
                              //var memData = memStream.ToArray();
                              break;
                              }
                          case Google.Apis.Upload.UploadStatus.Failed:
                              {
                                  var forget = Log.WriteAsync("------------- Upload failed.");
                                  break;
                              }
                      }
                  };
                  request.ResponseReceived += (Google.Apis.Drive.v3.Data.File f) =&gt;
                  {
                      var forget = Log.WriteAsync($"------------- File uploaded succesfully: {f.Name}");
                  };
                  var progress = await request.UploadAsync();
  
                  if (progress.Exception != null)
                      throw progress.Exception;
              }
          }
      }
      catch (Exception e)
      {
          e.ShowException();
      }
  }
  </code></pre>
  
  <p>Also, the method before this one when I serialize the file to upload and get the local path of the file:</p>
  
  <pre><code>private async Task SerializeAndUpdateDataFileAsync(DriveContaData data, CancellationToken cancelToken)
  {
      var path = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, Properties.Settings.Default.DriveContaDataName);
      var tmp = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "tmp" + Properties.Settings.Default.DriveContaDataName);
  
      try
      {
          await SerializeDriveContaDataAsync(
                          tmp,
                          new SerializableProxy_DriveContaData(data));
          if (cancelToken.IsCancellationRequested)
              return;
  
          System.IO.File.Delete(path);
          System.IO.File.Move(tmp, path);
          await UpdateFileAsync(path, Properties.Settings.Default.MJContaFolderID.Cast&lt;string&gt;().ToList(), Properties.Settings.Default.DriveContaDataId);
          if (cancelToken.IsCancellationRequested)
              return;
          DataFileSavedAndUploaded = true;
      }
      catch (Exception e)
      {
          e.ShowException();
      }
  }
  </code></pre>
  
  <p>The log shows the <code>File uploaded succesfully</code> and <code>Upload complete</code> lines.</p>
  
  <p>.</p>
  
  <hr>
  
  <p><strong>Edit2:</strong>
  Ok, I've made a new, clean project, and copy/modified the code to make only the update.
  Same results, local file is correct, login correct, permissions correct, nothing happens when trying to update the file on drive: no exceptions, no update.</p>
  
  <p>This class make the update:</p>
  
  <pre><code>public class GoogleLogin
  {
      public GoogleLogin() { _FilesLoader = new DriveFilesLoader(); }
  
      private const string ApplicationName = "DriveMJConta";
      private UserCredential _Credential;
      private SheetsService _SheetsService;
      private DriveService _DriveService;
      private DriveFilesLoader _FilesLoader;
      private readonly string[] Scopes = {
          SheetsService.Scope.Spreadsheets,
          DriveService.Scope.DriveFile,
          DriveService.Scope.Drive,
          DriveService.Scope.DriveAppdata,
          DriveService.Scope.DriveMetadata };
      private IList&lt;string&gt; _Parents;
      private string _Id;
  
      public bool IsSigned { get; private set; }
  
      private async Task SetMJContaAppFolderAsync()
      {
          var files = _FilesLoader.ListFiles(
                  _DriveService,
                  new DriveFilesLoader.FilesListOptionalParms()
                  {
                      Q = @"name = '- DriveContaDataSave.xml' ",
                      Fields = "files(parents, id)"
                  });
          _Parents = files.Files[0].Parents;
          _Id = files.Files[0].Id;
      }
      private string GetMimeType(string fileName)
      {
          string mimeType = "application/unknown";
          string ext = System.IO.Path.GetExtension(fileName).ToLower();
          Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
          if (regKey != null &amp;&amp; regKey.GetValue("Content Type") != null)
              mimeType = regKey.GetValue("Content Type").ToString();
          return mimeType;
      }
  
      public async Task GetUserCredentialAsync()
      {
          //MessengerNSpace.Messenger.SendGuidedMessage("GOOGLELOGIN_START");
          try
          {
              var assembly = Assembly.GetExecutingAssembly();
              using (Stream stream = assembly.GetManifestResourceStream("PruebaGoogleDrive.Resources.client_secret.json"))
              {
                  string credPath = System.Environment.GetFolderPath(
                      System.Environment.SpecialFolder.Personal);
  
                  if (!IsSigned)
                  {
                      _Credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
                          GoogleClientSecrets.Load(stream).Secrets,
                          Scopes,
                          "user",
                          CancellationToken.None,
                          new FileDataStore(credPath, true));
                      //Log.WriteAsync("Credential file saved to: " + credPath);
                  }
                  else
                  {
                      await GoogleWebAuthorizationBroker.ReauthorizeAsync(
                          _Credential,
                          CancellationToken.None);
                      //Log.WriteAsync("Credential file saved to: " + credPath);
                  }
              }
  
              _DriveService = new DriveService(new BaseClientService.Initializer()
              {
                  HttpClientInitializer = _Credential,
                  ApplicationName = ApplicationName
              });
  
              await SetMJContaAppFolderAsync();
          }
          catch(Exception e)
          {
              e.ShowException();
          }
  
          MessageBox.Show("Login OK");
      }
      public async Task UpdateFileAsync(string fullPath)
      {
          try
          {
              string mimeT = GetMimeType(fullPath);
              Google.Apis.Drive.v3.Data.File file = new Google.Apis.Drive.v3.Data.File();
              file.Name = System.IO.Path.GetFileName(fullPath);
              //file.MimeType = mimeT;
              //file.Parents = parents;
  
              using (var fStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, true))
              {
                  byte[] byteArray = new byte[fStream.Length];
                  //byte[] byteArray = System.IO.File.ReadAllBytes(fullPath);
                  await fStream.ReadAsync(byteArray, 0, (int)fStream.Length);
                  using (var stream = new MemoryStream(byteArray))
                  {
                      var request = _DriveService.Files.Update(file, _Id, stream, mimeT);// .Create(file, stream, mimeT);
                      request.AddParents = string.Join(",", _Parents);
                      request.ProgressChanged += (Google.Apis.Upload.IUploadProgress prog) =&gt;
                      {
                          switch (prog.Status)
                          {
                              case Google.Apis.Upload.UploadStatus.Uploading:
                                  {
                                      MessageBox.Show($"------------- Progreso subida: {prog.BytesSent.ToString()}");
                                      break;
                                  }
                              case Google.Apis.Upload.UploadStatus.Completed:
                                  {
                                      MessageBox.Show("------------- Upload complete.");
                                      //var memData = memStream.ToArray();
                                      break;
                                  }
                              case Google.Apis.Upload.UploadStatus.Failed:
                                  {
                                      MessageBox.Show("------------- Upload failed.");
                                      break;
                                  }
                          }
                      };
                      request.ResponseReceived += (Google.Apis.Drive.v3.Data.File f) =&gt;
                      {
                          MessageBox.Show($"------------- File uploaded succesfully: {f.Name}");
                      };
                      var progress = await request.UploadAsync();
  
                      if (progress.Exception != null)
                          throw progress.Exception;
                  }
              }
          }
          catch (Exception e)
          {
              e.ShowException();
          }
      }
  }
  </code></pre>
  
  <p>I had the intention to make a concole project but I missclick and made a WPF project... doesn't matter, just made two buttons and in code-behind put this:</p>
  
  <pre><code>public partial class MainWindow : Window
  {
      public MainWindow()
      {
          InitializeComponent();
      }
  
      private GoogleLogin gl;
  
      private void Login_Click(object sender, RoutedEventArgs e)
      {
          gl = new GoogleLogin();
          Task.Run(() =&gt; gl.GetUserCredentialAsync());
      }
  
      private void Update_Click(object sender, RoutedEventArgs e)
      {
          Task.Run(() =&gt; gl.UpdateFileAsync(System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "- DriveContaDataSave.xml")));
      }
  }
  </code></pre>
  
  <p><code>DriveFilesLoader</code> is DaImTo class. I used it (and copy/paste here) just to speed things up:</p>
  
  <pre><code>public class DriveFilesLoader
  {
      public class FilesListOptionalParms
      {
          /// 
  
          /// The source of files to list.
          /// 
          public string Corpora { get; set; }
          /// 
  
          /// A comma-separated list of sort keys. Valid keys are 'createdTime', 'folder', 'modifiedByMeTime', 'modifiedTime', 'name', 'quotaBytesUsed', 'recency', 'sharedWithMeTime', 'starred', and 'viewedByMeTime'. Each key sorts ascending by default, but may be reversed with the 'desc' modifier. Example usage: ?orderBy=folder,modifiedTime desc,name. Please note that there is a current limitation for users with approximately one million files in which the requested sort order is ignored.
          /// 
          public string OrderBy { get; set; }
          /// 
  
          /// The maximum number of files to return per page.
          /// 
          public int? PageSize { get; set; }
          /// 
  
          /// The token for continuing a previous list request on the next page. This should be set to the value of 'nextPageToken' from the previous response.
          /// 
          public string PageToken { get; set; }
          /// 
  
          /// A query for filtering the file results. See the "Search for Files" guide for supported syntax.
          /// 
          public string Q { get; set; }
          /// 
  
          /// A comma-separated list of spaces to query within the corpus. Supported values are 'drive', 'appDataFolder' and 'photos'.
          /// 
          public string Spaces { get; set; }
          /// 
  
          /// Selector specifying a subset of fields to include in the response.
          /// 
          public string Fields { get; set; }
          /// 
  
          /// Alternative to userIp.
          /// 
          public string QuotaUser { get; set; }
          /// 
  
          /// IP address of the end user for whom the API call is being made.
          /// 
          public string UserIp { get; set; }
      }
  
      /// 
  
      /// Lists or searches files. 
      /// Documentation https://developers.google.com/drive/v3/reference/files/list
      /// Generation Note: This does not always build corectly.  Google needs to standardise things I need to figuer out which ones are wrong.
      /// 
      /// Authenticated drive service.  
      /// Optional paramaters.        /// FileListResponse
      public Google.Apis.Drive.v3.Data.FileList ListFiles(DriveService service, FilesListOptionalParms optional = null)
      {
          try
          {
              // Initial validation.
              if (service == null)
                  throw new ArgumentNullException("service");
  
              // Building the initial request.
              var request = service.Files.List();
              if(optional != null)
                  ApplyOptionalParameters(ref request, optional);
              // Applying optional parameters to the request.                
              request = (FilesResource.ListRequest)ApplyOptionalParms(request, optional);
              // Requesting data.
              return request.Execute();
          }
          catch (Exception ex)
          {
              throw new Exception("Request Files.List failed.", ex);
          }
      }
  
      private void ApplyOptionalParameters(ref FilesResource.ListRequest request, FilesListOptionalParms parms)
      {
          if(!string.IsNullOrEmpty(parms.Corpora))
              request.Corpora = parms.Corpora;
          if(!string.IsNullOrEmpty(parms.OrderBy))
              request.OrderBy = parms.OrderBy;
          if (parms.PageSize.HasValue)
              request.PageSize = parms.PageSize;
          if (!string.IsNullOrEmpty(parms.PageToken))
              request.PageToken = parms.PageToken;
          if (!string.IsNullOrEmpty(parms.Q))
              request.Q = parms.Q;
          if (!string.IsNullOrEmpty(parms.Spaces))
              request.Spaces = parms.Spaces;
          if (!string.IsNullOrEmpty(parms.Fields))
              request.Fields = parms.Fields;
          if (!string.IsNullOrEmpty(parms.QuotaUser))
              request.QuotaUser = parms.QuotaUser;
          if (!string.IsNullOrEmpty(parms.UserIp))
              request.UserIp = parms.UserIp;
      }
  
      /// 
  
      /// Using reflection to apply optional parameters to the request.  
      /// 
      /// If the optonal parameters are null then we will just return the request as is.
      /// 
      /// The request. 
      /// The optional parameters. 
      /// 
      public object ApplyOptionalParms(object request, object optional)
      {
          if (optional == null)
              return request;
  
          System.Reflection.PropertyInfo[] optionalProperties = (optional.GetType()).GetProperties();
  
          foreach (System.Reflection.PropertyInfo property in optionalProperties)
          {
              // Copy value from optional parms to the request.  They should have the same names and datatypes.
              System.Reflection.PropertyInfo piShared = (request.GetType()).GetProperty(property.Name);
              if (property.GetValue(optional, null) != null) // TODO Test that we do not add values for items that are null
                  piShared.SetValue(request, property.GetValue(optional, null), null);
          }
  
          return request;
      }
  }
  </code></pre>
  
  <p>Also the <code>Exception</code> extension, just if someone want to copy/paste to avoid compile errors and try it perse:</p>
  
  <pre><code>public static class ExceptionExtensions
  {
      public static void ShowException(this Exception e, string additionalMessagePrefix = "")
      {
          var msg = $@"{additionalMessagePrefix}
              Error: 
  {e.Message} ;
  
              Trace: 
  {e.StackTrace} ;";
  
          Exception innerEx = e.InnerException;
  
          while(innerEx != null)
          {
              msg = msg + $@"
  
              InnerException: 
  {(e.InnerException != null ? innerEx.Message : "")} ; 
  
              InnerException Trace:
  {(e.InnerException != null ? innerEx.StackTrace : "")} ;";
  
              innerEx = innerEx.InnerException;
          }
  
          System.Windows.MessageBox.Show(msg);
      }
  }
  </code></pre>