serge
serge

Reputation: 15239

ASP.NET Core How to read the content of an AzureTable

I develop a ASP.NET Core application working with Azure Tables.

So, I created a tables storage account in Azure Portal, created a table, filled it with some test data, and now I would like to display the content of that table to test the reading.

my appsettings.json is

{
    "ConnectionStrings": {
        "MyTables":"DefaultEndpointsProtocol=https;AccountName=yyy;AccountKey=xxx;EndpointSuffix=core.windows.net"
    },

    "Logging": {
        "IncludeScopes": false,
         [etc etc...]
    }
}

And my Startup.cs:

public class Startup
{
    public Startup(IHostingEnvironment env)
    {
        var builder = new ConfigurationBuilder()
            .SetBasePath(env.ContentRootPath)
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
            .AddEnvironmentVariables();
        Configuration = builder.Build();

        // here in debug we can see the connection string, that is OK
        Console.WriteLine($"conn string:{Configuration["ConnectionStrings:MyTables"]}");
    }

    public IConfigurationRoot Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        // Add framework services.
        services.AddMvc();            
    }

And here is my controller I try to Display the values:

using Microsoft.AspNetCore.Mvc;

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using NextMove.Models;
using System.Text;

[...]

public class HelloWorldController : Controller
{
    public string ReadTables() {
        // ????? Code does not work, as Startup not a reference
        string myConnString = Startup.Configuration["ConnectionStrings:MyTables"];
        //////////////////////////////////
        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(myConnString);
        CloudTableClient tableClient = storageAccount.CreateCloudTableClient();
        CloudTable table = tableClient.GetTableReference("themes");
        TableQuery<ProjectThemeEntity> query = new TableQuery<ProjectThemeEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, "fr"));
        StringBuilder response = new StringBuilder("Here is your test table:"); 
        foreach (ProjectThemeEntity item in table.ExecuteQuery(query)) {                
            response.AppendLine($"Key: {item.RowKey}; Value: {item.Description}");
        }
        return response.ToString();
    }

    // 
    // GET: /HelloWorld/
    public IActionResult Index() {
        return View();
    }

Questions:

a) How to fix this code in order to get the connection string?

b) There should be a "Table.ExecuteQuery(query)" as per this MSDN article in the controller's foreach, but it does not find such a method in CloudTable class, I however added the necessary references, as shown in the controller's code above, only two "Async" methods are available:

enter image description here

PS.

-For the (b) question several people has the same issue here, hope the situation changed now...

Upvotes: 0

Views: 186

Answers (1)

Erik Noren
Erik Noren

Reputation: 4339

You can't access Startup.Configuration from the controller because it's not a static property. Even though you've made it public (generally not a good idea) it still requires you to have an instance of Startup to get access to it.

Generally to get access to settings in ASP.NET Core it's best to create a class with the properties you want and use the IOptions pattern to get them with Dependency Injection. In your startup where you configure your services (add services to the dependency injection container) you would use the helper methods to add your configuration object to the container and then in your controller you would specify you wanted an IOptions or IOptionsSnapshot to get access to it.

I'd suggest you don't put your data access in your controller though. It makes your controller harder to read and harder to maintain if you need to change your strategy later. Move your ReadTables method to its own class and add it to the DI container in Startup taking whatever settings you need to create the service. Use constructor injection in your controller to get the service and execute calls from your controller actions where you need them.

Upvotes: 1

Related Questions