Azure vs GCP part 5: Storage (Azure)
Tags: azure, gcp, cloud
Published: 2018-03-04 15:02:05

---
title: "Azure vs GCP part 5: Storage (Azure)"
published: true
description: In this series, I compare Azure and GCP as C# developer
tags: azure,gcp,cloud
cover_image: https://thepracticaldev.s3.amazonaws.com/i/m57mmv4hgz9xrskaital.PNG
---

Any application needs some place to store data, such as SQL, NoSQL, Storage etc. In this article, I look into Azure Storage service, and I write separate article for GCP Storage.

# Azure Storage
Azure Storage is linked under Azure Storage Account. So I need to create account first, but I need to understanding what options are available. 

### Azure Storage Types
Azure offers several types of storage and services.

- Blob: Store files such as image, documents, or VHD for VM. It provides REST endpoint and SDKs for many langauges.
- Files: Highly available network share which you can access via SMB. It also provides REST endpoint.
- Disk: Works as native file system for VM.
- Tables: Tabular data storage.
- Queue: Queue objects.

Oh first three sounds similar? Yes it does. So there is good matrix to understand the differences.

[Comparison: Files and Blobs](https://docs.microsoft.com/en-us/azure/storage/common/storage-decide-blobs-files-disks#comparison-files-and-blobs)
[Comparison: Files and Disks](https://docs.microsoft.com/en-us/azure/storage/common/storage-decide-blobs-files-disks#comparison-files-and-disks)

In this article, as I need storage from Web Application point of view, I use blob storage.

### Account Options

In addition to Storage Options, I need to select account option.

- General purpose V2 (GPV2)
- General purpose V1 (GPV1)
- Blob storage

You can read the detail [here](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-options) but simply put, GPV2 = GPV1 + Blob storage. Checkout [Recommendation](https://docs.microsoft.com/en-us/azure/storage/common/storage-account-options#recommendations) section for more detail which account you want to use.

### Performance 
Azure Storage offers two storage types.

- Premium: SSD base. Good for VMs.
- Standard: Normal HDD base.

It also offer two access tiers.

- Hot: Good for frequently accessed storage. Lower access cost. 
- Cold: Good for fewer accessed storage. Lower storage cost.

### Other things
There are many more things you should know about the service, such as security, redundancy, access methods. You can find those information at [Planning for an Azure Files deployment](https://docs.microsoft.com/en-us/azure/storage/files/storage-files-planning)

It also provides Azure platform level features same as other services, such as:
- ACL
- Firewall
- Custom DNS
- Monitoring
- CDN
- Reporting
- Integrate with other services, etc. 

Integration is interesting topic as it works with Azure Search, Event Grid, etc. I keep this for the future topic.

## Azure Blob Storage
See [here](https://docs.microsoft.com/en-us/azure/storage/blobs/storage-blobs-introduction) for detail. I just share structure concept here.

Blob service has following structure.
![concept](https://docs.microsoft.com/en-us/azure/storage/blobs/media/storage-blobs-introduction/blob1.png)

- Account: Storage Account which explained above.
- Container: Works as grouping or like folder.
- Blob: Actual content.

# Let's code!!
Okay, enough talk!! Let's write code as that's what I am interested in.

1\. First of all, I create storage account. There are several ways to create it, but I use CLI in portal. Go to [Azure Portal](https://portal.azure.com) and select "Cloud Shell".
![portal](https://thepracticaldev.s3.amazonaws.com/i/lpf0a5o8pb2j9uutmvw1.PNG)

2\. Run the code to create account. I provision my account in East US, with Geo-redundant, with normal storage as Hot tier and https access only. Second command displays connection string which I use in the application.
```shell
az storage account create -n cloudcomparestorage -g CloudCompareRG --kind storageV2 --sku Standard_GRS --access-tier Hot --location eastus --https-only
az storage account show-connection-string -n cloudcomparestorage -g cloudcomparerg
```
3\. Create a images container for blob. I set it public accessible.
```shell
az storage container create --name images --public-access blob --account-name cloudcomparestorage
```

4\. As blob storage is ready, open Visual Studio and create new project. Select "ASP.NET Core Web Application" and create it.
![code](https://thepracticaldev.s3.amazonaws.com/i/gx6qz5gs705tig6ntqxc.PNG)

5\. Select "Web API" and click OK.
![code](https://thepracticaldev.s3.amazonaws.com/i/hs7f1sokt46yoxoqnrvq.PNG)

6\. Add "WindowsAzure.Storage" NuGet package.
![code](https://thepracticaldev.s3.amazonaws.com/i/97mvr09xuqsypg4vxn56.PNG)

7\. Rename existing "ValueController.cs" to "StorageController.cs", then paste the code. Replace the storage key at line 20.

```csharp
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using System;
using System.Threading.Tasks;

namespace Storage.Controllers
{
    [Route("api/[controller]")]
    public class StorageController : Controller
    {
        static CloudBlobClient blobClient;
        const string blobContainerName = "images";
        static CloudBlobContainer blobContainer;

        public StorageController()
        {
            CloudStorageAccount storageAccount = 
                CloudStorageAccount.Parse("<Your connection string>");

            // Create a blob client for interacting with the blob service.
            blobClient = storageAccount.CreateCloudBlobClient();
            blobContainer = blobClient.GetContainerReference(blobContainerName);
        }
       
        // GET api/storage/filename
        [HttpGet("{filename}")]
        public async Task<IActionResult> Get(string filename)
        {
            try
            {
                CloudBlockBlob blob = blobContainer.GetBlockBlobReference(filename);
                var image = await blob.OpenReadAsync();
                return new ObjectResult(image);
            }
            catch (Exception ex)
            {
                return NotFound();
            }
        }

        // POST api/storage
        [HttpPost]
        public async Task Post(IFormFile file)
        {
            try
            {
                CloudBlockBlob blob = blobContainer.GetBlockBlobReference(file.FileName);
                await blob.UploadFromStreamAsync(file.OpenReadStream());
            }
            catch (Exception ex)
            {               
            }
        }

        // DELETE api/storage/filename
        [HttpDelete("{filename}")]
        public async Task<IActionResult> Delete(string filename)
        {
            try
            {
                CloudBlockBlob blob = blobContainer.GetBlockBlobReference(filename);
                await blob.DeleteAsync();
                return Ok();
            }
            catch (Exception ex)
            {
                return NotFound();
            }
        }
    }
}

```
## Test it
1\. Hit F5 to debug the applicaiton. Check the address and port.

2\. Open [Postman](https://www.getpostman.com/) and select "POST" as verb, enter the endpoint address, then click "Body". 
![test](https://thepracticaldev.s3.amazonaws.com/i/z83nbc28hkbubncizqxi.PNG)

3\. Select "File" from key dropdown.
![test](https://thepracticaldev.s3.amazonaws.com/i/apkmtwbv6sownxrd20pf.PNG)

4\. Enter "file" to key and choose any image file from your local PC and hit "Send". I selected "apple-touch-icon.png".
![test](https://thepracticaldev.s3.amazonaws.com/i/qnnvallbjcby88tn4nef.PNG)

5\. Switch verb from "POST" to "GET", then add "/<filename> to the address.
![test](https://thepracticaldev.s3.amazonaws.com/i/u5aqmge0pgczjtbtpux9.PNG)

6\. Go to Azure Portal Cloud shell and run the command to confirm that there is a blob file.

```shell
az storage blob list --account-name cloudcomparestorage -c images --query '[].{name:name}'
```
7\. As I set the blob public access, you can also access to the image via browser from anywhere.

https://<storage account name>.blob.core.windows.net/<container name>/<file name>

8\. In Postman, change verb to "DELETE" and hit send.
![test](https://thepracticaldev.s3.amazonaws.com/i/i9g9q7zv4zozxbpmpjzq.PNG)

# Deploy to each platform

Now the code works. Let's deploy to Azure Web Apps and GCP App Engine. See [part 1]
(https://dev.to/kenakamu/azure-vs-gcp-part-1-aspnet-developer-experience-22i) for how to detail.

## Azure Web Apps
Yes it works as expected. Nothing to write here. But I used Windows version.
![azure](https://thepracticaldev.s3.amazonaws.com/i/y2yqldn5hrb2ihnu639e.PNG)

## GCP App Engine
This also works as expected. Though storage still sits on Azure, web api lives in GCP :)
![gcp](https://thepracticaldev.s3.amazonaws.com/i/e5dbbiuvezumnwcckbqs.PNG)


# Summary

When I develop a Web API, it's easy enough with SDK, and I don't have to care where the storage is, and how they are backup, scale, or secured. But when I think about service plans and options, there are so many thing to consider. However, with several clicks, I can tweak performance, resiliency, security, and so on :)  

I bet GCP should have similar capability but let's see it in the next article.

Ken