Azure Storage - micklpl/avanade-azure-workshop GitHub Wiki

Available tags

storage-add-data-to-tables storage-read-data storage-images-api storage-blobs

Azure Table Storage Basics

git checkout storage-add-data-to-tables

Add WindowsAzure.Storage NuGet to WebApp project.

Open Models/Table Storage Models folder in WebApp and add following classes:

 public class TeamEntity : TableEntity
 {
   public TeamEntity()
   {

   }
   public TeamEntity(string partition, string id)
   {
       PartitionKey = partition;
       RowKey = id;
   }
   public string Group { get; set; }
   public string Name { get; set; }
   public string Url { get; set; }
   public string Flag { get; set; }
   public int Points { get; set; }
}

public class PlayerEntity : TableEntity
{
    public PlayerEntity(string teamId, string id)
    {
        PartitionKey = teamId;
        RowKey = id;
    }

    public string TeamId { get { return PartitionKey; } }
    public int? Number { get; set; }
    public string Position { get; set; }
    public string FullName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Club { get; set; }
    public int Goals { get; set; }
    public string Thumbnail { get; set; }
}

Open DevController and modify MapPlayer and MapTeam methods replacing dynamic as a return value with PlayerEntity and TeamEntity

private PlayerEntity MapPlayer(Player player)
{
    return new PlayerEntity(player.TeamId, Guid.NewGuid().ToString())
    {
        Club = player.Club,
        DateOfBirth = player.DateOfBirth,
        Number = player.Number,
        Position = player.Position,
        FullName = player.FullName
    };
}

private TeamEntity MapTeam(Team team)
{
    return new TeamEntity(2018.ToString(), team.Name.Replace(" ", ""))
    {
        Flag = team.Flag,
        Name = team.Name,
        Group = team.Group.ToString()
    };
}

Open TeamsRepository and add following method

private CloudTableClient GetClient()
{
    CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["storageConnectionString"]);
    return storageAccount.CreateCloudTableClient();
}

Implement StoreTeams and StorePlayers methods:

    public async Task StoreTeams(IEnumerable<TeamEntity> teams)
    {
        var tableClient = GetClient();
        CloudTable table = tableClient.GetTableReference("teams");

        await table.CreateIfNotExistsAsync();

        TableBatchOperation batchOperation = new TableBatchOperation();

        foreach(var team in teams)
        {
            batchOperation.Insert(team);
        }

        table.ExecuteBatch(batchOperation);
    }

    public async Task StorePlayers(IEnumerable<PlayerEntity> players)
    {
        var tableClient = GetClient();
        CloudTable table = tableClient.GetTableReference("players");

        await table.CreateIfNotExistsAsync();            

        foreach (var group in players.GroupBy(p => p.PartitionKey))
        {
            foreach(var player in group)
            {
                TableBatchOperation batchOperation = new TableBatchOperation();
                batchOperation.Insert(player);
                table.ExecuteBatch(batchOperation);
            }                
        }            
    }

Open Azure Portal and navigate to storage account, open Access keys section and copy one of Connection Strings. Then paste it into AppSettings under storageConnectionString key.

Deploy your Web app to Azure. Enter /Dev url and click Fill Azure Table Storage

Azure Storage Explorer

Download Azure Storage Explorer (link) and log in using your Azure account credentials.

Expan tables and browse the data. Try to find:

  • all the teams from group H
  • all the players with number 10
  • all the players under 20

Azure Table Storage Basics (2)

git checkout storage-read-data

Make sure to restore all Nuget Packages

Run the application and observe the data flow.

Open TeamsRepository.cs and implement two missing methods:

public IEnumerable<TeamEntity> FetchTeams()
{
    var tableClient = GetClient();
    CloudTable table = tableClient.GetTableReference("teams");
    var query = new TableQuery<TeamEntity>();
    return table.ExecuteQuery(query).OrderBy(f => f.Group);
}

public IEnumerable<PlayerEntity> FetchPlayers(string teamId)
{
    var tableClient = GetClient();
    CloudTable table = tableClient.GetTableReference("players");
    var query = new TableQuery<PlayerEntity>()
                        .Where(TableQuery.GenerateFilterCondition(nameof(PlayerEntity.PartitionKey), QueryComparisons.Equal, teamId));
    return table.ExecuteQuery(query).OrderBy(f => f.Number);
}

Deploy your Web App.

Bing Search API

git checkout storage-images-api

Open Azure Portal and Navigate to your Resource Group. Add New Resource.

Type in Bing Search and choose Bing Search v7. Create resource choosing S3 pricing tier.

Open Keys tab, copy first key and paste it into appSettings as bingImagesSearchKey and in Application Settings of your Web App.

Run the application, browse player profiles.

Open Bing API resource, observe Monitoring diagrams

Azure Blob Storage

git checkout storage-blobs

Open PlayersService.cs and analyze GetPlayerImages method. Try to implement all empty methods used there.

Open BinaryFilesRepository and add following method:

private CloudBlobClient GetBlobStorageClient()
{
   CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["storageConnectionString"]);
   return storageAccount.CreateCloudBlobClient();
}

Implement SaveBlob method:

public void SaveBlob(string containerName, string fileName, byte[] bytes)
{
    var cloudBlobClient = GetBlobStorageClient();
    var container = $"{containerName}-{fileName}".ToLower();
    var cloudBlobContainer = cloudBlobClient.GetContainerReference(container);
    cloudBlobContainer.CreateIfNotExists();

    BlobContainerPermissions permissions = new BlobContainerPermissions
    {
        PublicAccess = BlobContainerPublicAccessType.Blob
    };
    cloudBlobContainer.SetPermissions(permissions);

    CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(Guid.NewGuid().ToString() + ".png");

    using (var stream = new MemoryStream(bytes, writable: false))
    {
        cloudBlockBlob.UploadFromStream(stream);
    }            
}

Try to run the application and open few player profiles. Open Storage Explorer. Locate your blobs. Click on Properties tab. Copy the URL and try to open it in the browser.

Implement missing repository methods:

public bool AnyFileExists(string containerName, string fileName)
{
    var cloudBlobClient = GetBlobStorageClient();
    var container = $"{containerName}-{fileName}".ToLower();
    var cloudBlobContainer = cloudBlobClient.GetContainerReference(container);
    return cloudBlobContainer.Exists();
}

public List<string> GetBlobUrls(string containerName, string fileName)
{
    var cloudBlobClient = GetBlobStorageClient();
    var container = $"{containerName}-{fileName}".ToLower();
    var cloudBlobContainer = cloudBlobClient.GetContainerReference(container);
    return cloudBlobContainer.ListBlobs().Select(b => b.Uri.ToString()).ToList();
}

Open Azure Portal and browse Storage account metrics.

⚠️ **GitHub.com Fallback** ⚠️