How to connect an Azure Storage Account to an ASP.NET Core project?

-1

I'm using VS2017 with ASP.NET Core 2.0 (Angular template) and I need to do basic table-based CRUD operations in Azure Storage.

Is there any way to do scaffolding in my environment?

    
asked by anonymous 22.08.2017 / 21:06

2 answers

1
Unfortunately, there is no way to connect an Azure Storage Account via Connected Services using any version and layout of ASP.NET Core (at least in Visual Studio 2017), however, there is a manual way to bridge this gap, follow the steps which I used to solve the problem:

First, I needed to install the NuGet package WindowsAzure.Storage .

In my Models folder, I created a Foo class that represented the model of my Azure table. All model classes inherit from TableEntity , which has those basic properties for all Azure tables: PartitionKey , RowKey , ETag , etc.

public class Foo : TableEntity {
  public string FooField { get; set; }
  public string FooField2 { get; set; }  
}

I created a Repositories folder in the project root and added a FooRepository class for table manipulation (CRUD)

public class FooRepository {

  private readonly CloudStorageAccount storageAccount { get; }

  public FooRepository(string connectionString) {
    storageAccount = CloudStorageAccount.Parse(connectionString);
  }

  public Task<IEnumerable<Foo>> GetAsync() {
    // ...
  }

  public Task<Foo> GetAsync(string partitionKey, string rowKey) {
    // ...
  }

  public Task UpdateAsync(string partitionKey, string rowKey, Foo updatedEntity) {
    // ...
  }

  public Task DeleteAsync(string partitionKey, string rowKey) {
    // ...
  }

  public Task CreateAsync(Foo newEntity) {
    // ...
  }
}

The FooRepository was referenced in my FooController , which looked something like this:

[Produces("application/json")]
[Route("api/Foo")]
public class FooController : Controller {
    readonly FooRepository repo = new FooRepository("connectionString");

    [HttpGet]
    public async Task<List<Foo>> Get() {
        return (await repo.GetEntitiesAsync()).Item1;
    }       
}

The connection string can be found in the Azure portal. You can pass it as I did, every time I reference a Repository , or put it in a structured file like * .xml or * .json and read it fixedly, by taking the connectionString of the repositories constructor, which is a practice I recommend, since these connection strings may eventually change (DRY!).

A Repository can be more abstract, as I did in the example below:

public class BaseRepository<T> : IRepository where T : class, ITableEntity, new() {

    CloudStorageAccount IRepository.StorageAccount { get; set; }
    CloudTableClient IRepository.TableClient { get; set; }
    CloudTable IRepository.Table => ((IRepository)this).TableClient.GetTableReference(nameof(T));

    public BaseRepository(string connString) {
        ((IRepository) this).StorageAccount = CloudStorageAccount.Parse(connString);
        ((IRepository) this).TableClient = ((IRepository) this).StorageAccount.CreateCloudTableClient();
    }

    public Task CreateAsync(T entity) {
        TableOperation insertOperation = TableOperation.Insert(entity);
        return ((IRepository) this).Table.ExecuteAsync(insertOperation);
    }

    public async Task<T> GetEntityAsync(string partitionKey, string rowKey) {
        TableOperation retrieveOperation = TableOperation.Retrieve<T>(partitionKey, rowKey);

        T entity = (await ((IRepository)this).Table.ExecuteAsync(retrieveOperation)).Result as T;
        return entity;
    }

    public async Task<Tuple<List<T>, TableContinuationToken>> GetEntitiesAsync(TableContinuationToken token = null) {
        List<T> list = new List<T>();
        TableQuery<T> query = new TableQuery<T>().Take(15);

        TableQuerySegment<T> tableQueryResult = await ((IRepository)this).Table.ExecuteQuerySegmentedAsync(query, token);
        list.AddRange(tableQueryResult.Results);

        return Tuple.Create(list, tableQueryResult.ContinuationToken);
    }

    public async Task<T> DeleteEntityAsync(string partitionKey, string rowKey) {
        T entityToDelete = await GetEntityAsync(partitionKey, rowKey);

        TableOperation deleteOperation = TableOperation.Delete(entityToDelete);
        await ((IRepository)this).Table.ExecuteAsync(deleteOperation);

        return entityToDelete;
    }
}

Being IRepository a simple interface:

interface IRepository {
    CloudStorageAccount StorageAccount { get; set; }
    CloudTableClient TableClient { get; set;  }
    CloudTable Table { get; }
}

See that GetEntitiesAsync(TableContinuationToken) is only taking 15 results, when the user passes the page, you call the method by passing the returned token. More details about handling can be read here >.

    
25.08.2017 / 02:03
2

Azure Storage Emulator

First you must configure the Azure Storage emulator locally, so you can develop it without the need to go remote.

The storage emulator is available as part of Microsoft Azure SDK . You can also install the storage emulator individually ( download here ).

After installing, just run the Azure Storage Emulator application, select the type you want to emulate and that's it.

Azure Storage Explorer

To help, you can also use Azure Storage Explorer to make your storage consumption more friendly - either in Azure, or locally .

Download Azure Storage Explorer here .

Sources:

link link

    
24.08.2017 / 09:38