The advent of cloud computing has ensured round-the-clock data accessibility for users. With the emergence of various service providers, it has become easier for users to store data with permanent availabity.

Here are some of the Major Cloud Storage providers:

  • AWS (Amazon Web Service)
  • Azure
  • DropBox
  • GoogleDrive
  • OneDrive

Data on these storages can be accessed by users either via web-based clients or APIs exposed by these providers.

Let’s say we created a Web Application that has a feature to convert PDF files to image files. C1 Web API already has the built-in service to convert them to different file formats (JPEG, PNG, TIFF, BMP, GIF) to make our task much easier.

Now, end users of this application may want to upload PDF files from their cloud storage providers and then store the converted files back to the cloud service provider.

Since each of these providers would have their own implementations for an API and different authentication mechanisms, we would need to write separate code to implement CRUD operations for each of these cloud providers. It would become cumbersome to maintain the code for all of them.

A prudent approach would be to write the CRUD & authentication mechanisms for all services inside a single service and then expose common Restful API for all the Cloud Storages.

In 2019 v2, we have added Cloud Storage support to ComponentOne WebAPI, which provides common RESTAPI methods to list, upload, delete and download files separately for each cloud storage provider.

To perform operations on Cloud Storage, C1 WEBAPI would act as the middleware between the Client and Cloud Service Storage APIs. C1 WebAPI would abstract the different CRUD & authentication implementation for cloud storage providers and provide common REST implementation to clients.

Let's have a look at C1 Cloud Service Architecture:

Cloud Storages - CRUD Operations using RESTFul C1 WebAPI Services

Let’s review the implementation steps using C1 Web API

  1. Adding C1.Web.Api.Cloud DLL/package
  2. Cloud storage registration & authentication (AWS, Azure, DropBox, Google Drive, OneDrive)
  3. CRUD operations on cloud storage

Create WebAPI project using C1 Template

ComponentOne provides a built-in template for C1 WebAPI, which can be used to create a WebAPI project with C1 services.

To begin, open Visual Studio | New | Project | C1 | WebAPI which will open the following template:

Cloud Storages - CRUD Operations using RESTFul C1 WebAPI Services

Here, we would fill the project name and select the project location, then click OK.

Once you click OK, another dialog opens, which can be used to select the required service. If it is not in the list, we can later add the required DLL’s from Nuget or add from a local machine.

Cloud Storages - CRUD Operations using RESTFul C1 WebAPI Services

Adding C1.Web.Api.Cloud Dll/package

To use the Cloud Storage, the C1.Web.Api.Cloud DLL or package is required to added an existing or a new WebApi project using the NuGet Package Manager. It installs the required dependencies to interact with Cloud Storages.

Cloud storage registration & authentication

Each Cloud Storage has its own authentication method to perform an operation by authorized users. We need to add the registration code inside the Configuration method of the Startup class.

Startup.cs

public class Startup 
  { 
    private readonly HttpConfiguration config = GlobalConfiguration.Configuration; 

  public void Configuration(IAppBuilder app) 
    { 
      app.UseCors(CorsOptions.AllowAll); 
      // c1 cloud service code here, according to suitable service 
      ... 
    } 
} 

Here is the list of authentication mechanisms for various APIs:

AWS (Amazon Web Service)

AWS requires three credentials for authentication:

  • Bucket name
  • Access token
  • Secret key

A Bucket can be created here. Access Token and Secret Key are available at the following link.

Region should also be set to use AWS.

Required DLL(s):

  • AWSSDK.Core
  • AWSSDK.S3
AWS Registration
app.UseStorageProviders().AddAWSStorage("AWS", AWSAccessTocken, AWSSecretKey, AWSBucketName, region); 

AZURE

To use Azure Storage, we need to create a storage account and get the connection string by following this tutorial.

Once the connection string is retrieved, we need to create the container to store the files by following this tutorial.

Required DLL(s):

  • WindowsAzure.Storage

Now that we have the required credentials and DLL to use Azure storage inside this project, we need to register Azure Storage with the required credentials using the following code snippet:

Azure Registration
app.UseStorageProviders().AddAzureStorage("Azure", AzureStorageConnectionString); 

DropBox

To use the Dropbox Cloud Storage, we need to create an application to store the files. Click here to build your application.

After creating the application, we need an access token for authentication. Click here to generate the access token.

Required DLL(s):

  • Dropbox.Api
DropBox Registration
app.UseStorageProviders().AddDropBoxStorage("DropBox", DropboxAppAccessToken, ApplicationName); 

GoogleDrive

To work with Google Drive cloud storage, we are required to create an application and generate the credentials.json by following this link.

After generating the credentials.json, include it in the project.

Required DLL(s):

  • Google.Apis
  • Google.Apis.Auth
  • Google.Apis.Core
  • Google.Apis.Drive.v3

To access the GoogleDrive API, the credentials stored in the json file should be extracted based on the Scope of the Application. Please use the following code snippet to get user credentials.

private UserCredential GetUserCredential(string[] scopes) 
  { 
              UserCredential credential; 

              using (var fileStream = 
                    new 
FileStream(HttpContext.Current.Server.MapPath("credentials.json"), FileMode.Open, FileAccess.Read)) 
            { 
                // The file token.json stores the user's access and refresh tokens, and is created 
                // automatically when the authorization flow completes for the first time. 
                string credPath = "token.json"; 
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(GoogleClientSecrets.Load(fileStream).Secrets, 
                scopes, 
                "user", 
                CancellationToken.None, 
                new 
FileDataStore(HttpContext.Current.Server.MapPath(credPath), true)).Result; 
              } 
              return credential; 
      } 
Google Drive Registration
string[] scopes = { DriveService.Scope.Drive };
app.UseStorageProviders().AddGoogleDriveStorage("GoogleDrive", GetUserCredential(scopes), applicationName); 

OneDrive

OneDrive provides the access token upon registering the app successfully. Get started here.

OneDrive Registration
app.UseStorageProviders().AddOneDriveStorage("OneDrive", OneDriveAccessToken); 

CRUD operations on cloud storage

Read files from Cloud Storage

Once the Storage is registered, the Cloud API is accessible here.

Now that our API is ready, we can fetch the file list at the provided location. To fetch the files and folder from the targeted location, the URL will be as follows:

    var baseUrl = “http://localhost /api/storage/"; 
    var cloudStorage = "Azure/"; // Cloud Storage name from where the data should be fetched 
    var initPath = "apitest/Test/"; // Initial Path at the CloudStrorage where the files should be list 
    var fetchListUrl = _baseUrl + "List/" + _cloudStorage + initPath;

Now that the URL is ready to fetch the list from CloudStorage, we will make an ajax call to list the Data and display inside Wijmo 5 TreeView.

Ajax call to fetch the list
<script>
function fetchList() { 
    $.ajax({ 
        url: fetchListUrl, 
        success: function (data) { 
          data.forEach(function (item) { 
            if (item.Type == 0) { 
                item.Childs = []; 
                item.ParentPath = item.Name + "/"; 
            } 
          }); 
          tree.itemsSource = data; 
        } 
      }); 
    }
</script> 
Create TreeView to show the file list
HTML: <div id="tree"></div>
JavaScript: 
<script>
onload = function () { 
  tree = new wijmo.nav.TreeView("#tree", { 
    displayMemberPath: 'Name', 
    childItemsPath: 'Childs', 
    lazyLoadFunction: lazyLoadFunction 
  }); 
  fetchList(); 
  }
</script> 
Reading files from sub folders

Since Cloud Storage can contain files with a subfolder, we may need to load the file list from the sub folders separately, by specifying the folder path.

<script>
function lazyLoadFunction(node, callback) { 
      var item = node.dataItem; 
      var subPath = item.ParentPath; 
      var url = fetchListUrl + subPath; 
      // if CloudStrorage is GoogleDrive 
      if (item.ItemID) { 
          url += "?itemid=" + item.ItemID; 
      } 
      $.ajax({ 
        url: url 
      }).then(function (data) { 
          data.forEach(function (item) { 
            if (item.Type == 0) { 
                item.Childs = []; 
                item.ParentPath = subPath + item.Name; 
            } else { 
              item.ParentPath = subPath + "/"; 
            } 
          }); 
          callback(data); 
        }); 
      }
</script> 
Upload file

Note: The file is uploaded to the API using FormData. While creating FormData, we need to set the FormData parameter name as “file” to upload files correctly.

To upload the file from the Client to Cloud Storage,the following code should be used.

<script>
var operationUrl = _baseUrl + _cloudStorage + initPath; 
function UploadFile() { 
    var item = tree.selectedItem; 
    if (!item) { 
      alert("No Item selected to uplaod path"); 
    } 
    var file = document.getElementById("file").files[0]; 
    var data = new FormData(); 
    data.append("file", file); 
    var _url = operationUrl + "?subpath=" + item.ParentPath + file.name; 
    // if CloudStrorage is GoogleDrive 
    if (item.ItemID) { 
        _url += "?itemid=" + item.ItemID; 
    } 
    $.ajax({ 
        url: _url, 
        type: 'POST', 
        data: data, 
        cache: false, 
        contentType: false, 
        processData: false 
    }).then(function (res) { 
      alert("Uploaded") 
    }) 
  }
</script> 
Delete File

The following code should be used to delete the file from the servers.

function DeleteFile() { 
  var item = tree.selectedItem; 
  if (!item) { 
      alert("No item to delete"); 
  } else { 
      var path = item.ParentPath ? item.ParentPath : ""; 
      var url = operationUrl + path + "?subpath=" + item.Name; 
      // if CloudStrorage is GoogleDrive 
      if (item.ItemID) { 
          url += "?itemid=" + item.ItemID; 
      } 
      $.ajax({ 
        url: url, 
        type: 'DELETE', 
        cache: false, 
        contentType: false, 
        processData: false, 
        success: function (data, success, obj) { 
          alert("Deleted"); 
        } 
      }); 
    } 
  } 
Download file

The following code should be used to download the file from the server.

function DownloadFile() { 
      var item = tree.selectedItem; 
      if (!item) { 
          alert("No item to download"); 
      } else { 
        var path = item.ParentPath ? item.ParentPath : ""; 
        var url = operationUrl + path + "?subpath=" + item.Name; var elem = wijmo.createElement("[](" + url + ")"); elem.click(); 
      } 
    }

Refer to the C1WebApiExplorer demo for reference here. Get the sample application here. The GIF below can also be used as a helpful demo.

Cloud Storages - CRUD Operations using RESTFul C1 WebAPI Services

See the C1WebAPI for yourself

Download the latest version of ComponentOne Studio Enterprise

Download Now!