[]
        
(Showing Draft Content)

Share and Collaborate

DsPdfViewer allows you to share a PDF document with other users. The document can be shared in view or/and edit mode and can be worked upon by multiple users in real time. You can also observe the presence of other users and the changes made by them in the shared document, known as real-time collaboration.

The below image shows a PDF document in shared mode which has been edited by multiple users and their changes are visible along with their user names.


Once configured to use the SupportApi, a PDF document can be edited in following ways:

  • Annotations

  • Form fields

  • Form filling

  • Comments

Set up Collaboration Mode

The collaboration mode, where multiple users can work on a shared document, is designed to work only with persistent client connections. To ensure this, the SupportApi includes the following nuget package dependencies:

  • AspNetCore.SignalR for ASP.NET Core version

  • AspNet.SignalR.Core for ASP.NET/OWIN self host version

When a shared document is modified, the server-side SupportApi code instantly pushes the changes to connected clients as soon as the changes become available. The steps listed below describe how to set up collaboration mode in ASP.NET Core Web Application and ASP.NET WebForms Application:

Web Application in .NET 6/ .NET 7

To support persistent client connections for collaboration mode, configure your web application by editing Program.cs file following the steps mentioned below:

  1. Add SignalR service to the services collection by calling “SupportApi.Connection.GcPdfViewerHub.ConfigureServices(services);”.

    GcPdfViewerHub.ConfigureServices(builder.Services);
  2. Map SignalR hub.

    // Configure signalr hub for collaboration mode.
    IApplicationBuilder applicationBuilder = app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
        endpoints.MapHub("/signalr", opts => {
            opts.TransportMaxBufferSize = 268435456L;
            opts.ApplicationMaxBufferSize = 268435456L;
        });
    });

Web Application in .NET Core 3.1/ .NET 5

To support persistent client connections for collaboration mode, configure your web application by editing Startup.cs file following the steps mentioned below:

  1. Add SignalR service to the services collection by calling SupportApi.Connection.GcPdfViewerHub.ConfigureServices(services); Inside the ConfigureServices method:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddRazorPages();
        // Enable routing:
        services.AddMvc((opts) => { opts.EnableEndpointRouting = false; });
        services.AddRouting();
        // Add SignalR service to the services collection:
        SupportApi.Connection.GcPdfViewerHub.ConfigureServices(services);
    }
  2. Map SignalR hub inside the Configure method as follows:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapRazorPages();
            // Map SignalR hub:
            endpoints.MapHub<SupportApi.Connection.GcPdfViewerHub>("/signalr");
        });
    }

WebForms Application

To support persistent client connections for collaboration mode, configure your web application by editing Startup.cs file:

[assembly: OwinStartup(typeof(SupportApiDemo_WebForms.Startup))]namespace SupportApiDemo_WebForms 
{
    public class Startup 
    {
        public void Configuration(IAppBuilder app)
        {
            // ... the rest of the code goes here
            SupportApi.Connection.GcPdfViewerHub.Configure(app);
            // Optionally, you can add known users, these users will be displayed in the user interface as a suggestions pop-up:
            GcPdfViewerController.Settings.AvailableUsers.Add("Anonymous");
            GcPdfViewerController.Settings.AvailableUsers.Add("James");
            GcPdfViewerController.Settings.AvailableUsers.Add("Lisa");
            // For example, you can use your own shared document storage
            // which implements the ICollaborationStorage interface:
            GcPdfViewerController.Settings.Collaboration.Storage.UseCustomStorage(myCloudStorage);
        }
    }
}

!type=note

Note: Using SupportApi in ASP.NET Core projects requires ASP.NET Core 3.0 or later. For more details on how to upgrade an existing ASP.NET Core 2.2 project to 3.0, refer this link.

Store Changes in Collaboration Mode

When you make changes to PDF documents in shared mode, the modified documents are stored in server's memory by default. These changes are discarded in either of the below cases:

  • If the server is restarted

  • Or after 8 hours, which is the default period for automatically clearing documents in memory

To prevent this, you can do any of the following:

.NET 6/ .NET 7

  1. Use local folder (file system) storage by using below code:

    GcPdfViewerController.Settings
      .Collaboration
      .Storage
      .UseFileSystem(Path.Combine(env.ContentRootPath, "LocalStorage"), 8);
  2. Change the lifetime of shared documents to retain the changes in shared documents for 24 hours by using below code:

    GcPdfViewerController.Settings
      .Collaboration
      .Storage
      .UseMemory(24);
  3. Use a custom storage type to store shared documents by implementing ICollaborationStorage interface:

    public class FileSystemStorage : ICollaborationStorage
    {
            private readonly string _directoryPath;
            private object _readLock = new object();
            private object _writeLock = new object();
            public FileSystemStorage(string directoryPath)
            {
                _directoryPath = directoryPath;
            }
           //ICollaborationStorage interface implementation
            public Task<byte[]> ReadData(string key)
            {           
                return Task.Factory.StartNew(() =>
                {
                    string filePath = Path.Combine(_directoryPath, $"{key}");
                    if (File.Exists(filePath))
                    {
                        lock (_readLock)
                        {
                            return File.ReadAllBytes(filePath);
                        }
                    }
                    return null;
                });
    
            }
            public Task WriteData(string key, byte[] data)
            {
                return Task.Factory.StartNew(() =>
                {
                    var filePath = Path.Combine(_directoryPath, $"{key}");
                    lock (_writeLock)
                    {
                        if (data == null)
                        {
                            if (File.Exists(filePath))
                                File.Delete(filePath);
                        }
                        else
                        {
                            File.WriteAllBytes(filePath, data);
                        }
                    }
                });
            }
    }

.NET Core 3.1/ .NET 5

  1. Use local folder (file system) storage by using below code:

    GcPdfViewerController.Settings
      .Collaboration
      .Storage
      .UseFileSystem(Path.Combine(env.ContentRootPath, "LocalStorage"), 8);
  2. Change the lifetime of shared documents to retain the changes in shared documents for 24 hours by using below code:

    GcPdfViewerController.Settings
      .Collaboration
      .Storage
      .UseMemory(24);
  3. Use a custom storage type to store shared documents by implementing ICollaborationStorage interface:

    public class FileSystemStorage : ICollaborationStorage
    {
            private readonly string _directoryPath;
            private object _readLock = new object();
            private object _writeLock = new object();
            public FileSystemStorage(string directoryPath)
            {
                _directoryPath = directoryPath;
            }
           //ICollaborationStorage interface implementation
            public Task<byte[]> ReadData(string key)
            {           
                return Task.Factory.StartNew(() =>
                {
                    string filePath = Path.Combine(_directoryPath, $"{key}");
                    if (File.Exists(filePath))
                    {
                        lock (_readLock)
                        {
                            return File.ReadAllBytes(filePath);
                        }
                    }
                    return null;
                });
    
            }
            public Task WriteData(string key, byte[] data)
            {
                return Task.Factory.StartNew(() =>
                {
                    var filePath = Path.Combine(_directoryPath, $"{key}");
                    lock (_writeLock)
                    {
                        if (data == null)
                        {
                            if (File.Exists(filePath))
                                File.Delete(filePath);
                        }
                        else
                        {
                            File.WriteAllBytes(filePath, data);
                        }
                    }
                });
            }
    }

Share a PDF Document

You can share a PDF document by clicking on the 'share' button in DsPdfViewer's toolbar.


To add the 'share' button in toolbar, use the following code:

viewer.toolbarLayout.viewer.default = ["share"];
viewer.applyToolbarLayout();

When you click on 'share' button, the 'Manage Access' dialog box opens as shown below:


You can provide access to other users and set their permissions to 'View only' or 'View and Change'.


You can also change the access of existing users or stop sharing the document with them.


!type=note

Note: The PDF document owner can perform all the above operations. Other users cannot edit/delete the document owner or change his permissions. However, other users with edit permissions can add other users, change their permissions or stop sharing the document.

Open a Shared PDF Document

You can open a shared PDF document by using the 'Shared Documents' panel. This panel lists all the documents that the current user has shared and has access to, with information about the access mode.


To add the 'Shared Documents' panel to the sidebar panel, use the following code:

var viewer = new DsPdfViewer("#root", { supportApi: 'api/pdf-viewer'} );
viewer.addSharedDocumentsPanel();

Real-time Co-authoring

When multiple users collaborate in a PDF document at the same time, you can see the real-time changes along with the name of users. Whenever a shared document is opened, the ‘shared mode’ label with the document's access type is shown on the top right corner of the document, as shown below:


You can also use "sharing" option in API to configure document sharing options, like:

  • Disallow user names unknown to the server by using the following code:

    var viewer = new DsPdfViewer("#root", { userName: "John", sharing: { disallowUnknownUsers: true }, supportApi: "api/pdf-viewer" } );
  • Specify known user names and disallow other user names by using the following code:

    var viewer = new DsPdfViewer("#root", {
          userName: "John",
          sharing: {
              knownUserNames: ["Jaime Smith", "Jane Smith"],
              disallowUnknownUsers: true,
          },
          supportApi: "api/pdf-viewer"
     });
  • Use presenceColors setting to set the exact colors for user presence indicators by using the following code:

    var viewer = new DsPdfViewer("#root", {
            sharing: {
                knownUserNames: ['Jamie Smith', 'Lisa'],
                presenceColors: { 'Anonymous': '#999999', 'Jamie Smith': 'red',  'Lisa': 'blue' }
            },
            supportApi: "api/pdf-viewer"
    });
  • Use presenceMode setting to change the mode of presence for collaboration users. The possible values for presenceMode setting are:

    • 'on' or 'true' - the presence of all users (including the active one) will be shown. This is the default value.

    • 'others' - all users except the active user will be shown.

    • 'off' or false - users presence will not be shown.

    // change presenceMode to 'others':
    var viewer = new DsPdfViewer("#root", {
        sharing: {
            presenceMode: 'others'
        },
        supportApi: "api/pdf-viewer"
    });