Search code examples
c#.netgoogle-drive-apifolder-permissions

Setting folder permissions in Google Drive API


I'm getting the error below when trying to create a folder, and set its permissions. It will work without passing the permissions in the file metadata.

But I'd like to create folders with permissions to specific users, who each have their own g-mail accounts. How can I accomplish this? Thanks!

Error message:

Exception message upon compiling/executing

The Code:

using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Drive.v3.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;


namespace DriveQuickstart
{
  class Program
  {
    // If modifying these scopes, delete your previously saved credentials
    // at ~/.credentials/drive-dotnet-quickstart.json
    static string[] Scopes = { DriveService.Scope.Drive };
    static string ApplicationName = "Drive API .NET Quickstart";

    static void Main(string[] args)
    {
      UserCredential credential;

      using (var stream =
      new FileStream("client_secret.json", FileMode.Open, FileAccess.ReadWrite))
      {
        string credPath = System.Environment.GetFolderPath(
        System.Environment.SpecialFolder.Personal);

        credPath = Path.Combine(credPath, ".credentials/drive-dotnet-quickstart.json");

        credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
        GoogleClientSecrets.Load(stream).Secrets,
        Scopes,
        "user",
        CancellationToken.None,
        new FileDataStore(credPath, true)).Result;
        Console.WriteLine("Credential file saved to: " + credPath);
      }

      // Create Drive API service.
      var service = new DriveService(new BaseClientService.Initializer()
      {
        HttpClientInitializer = credential,
        ApplicationName = ApplicationName,
      });

      Permission perm = new Permission();

      perm.Type = "user";
      perm.EmailAddress = "[email protected]";
      perm.Role = "owner";

      IList<Permission> perms = new List<Permission>();

      perms.Add(perm);

      var fileMetadata = new Google.Apis.Drive.v3.Data.File()
      {
        Name = "Invoices",
        MimeType = "application/vnd.google-apps.folder",
        Description = "Blah blah " + System.DateTime.Now.Hour + ":" + System.DateTime.Now.Minute + ":" + System.DateTime.Now.Second,
        Permissions = perms
      };

      var request = service.Files.Create(fileMetadata);
      request.Fields = "id";
      var file = request.Execute();
      Console.WriteLine("Folder ID: " + file.Id);

      Console.Read();

    }
  }
}

Solution

  • As you can see in the Documentation, The Permissions[] property is not indicated as a writable field. Therefore, populating Permissions[] in the resource body before file creation isn't the right approach; just like the error indicates "resource body contains fields which are not directly writable".

    So how to create a shared folder?

    You must first Create the folder and then Create the Permission for it, using its Id.

    You can modify your code into :

    var fileMetadata = new Google.Apis.Drive.v3.Data.File()
    {
        Name = "Invoices",
        MimeType = "application/vnd.google-apps.folder",
        Description = "Blah blah " + System.DateTime.Now.Hour + ":" + System.DateTime.Now.Minute + ":" + System.DateTime.Now.Second
    };
    
    Permission perm = new Permission();
    perm.Type = "user";
    perm.EmailAddress = "[email protected]";
    perm.Role = "owner";
    
    var request = service.Files.Create(fileMetadata);
    request.Fields = "id";
    
    try 
    {
        service.Permissions.Create(perm, request.Execute().Id).Execute(); //Creating Permission after folder creation.
    }
    catch (Exception e) 
    {
        Console.WriteLine("An error occurred: " + e.Message);
    }