Search code examples
c#asp.net-coredependency-injectionconfiguration

Dependency Injection of builder.Configuration is not working


I want to access secrets through IConfiguration and I'm setting it up like this in Program.cs:


namespace Project
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var builder = WebApplication.CreateBuilder(args);
            
            builder.Configuration
                .AddJsonFile("secrets.json");

            builder.Services.AddSingleton<IConfiguration>(builder.Configuration);
            builder.Services.AddTransient<IS3Service, S3Service>();

            var app = builder.Build();

            ...

            app.Run();
        }
    }
}

But when I try to access it from another class configuration is null:

using Amazon.S3;
using Amazon.S3.Model;

using Amazon.S3;
using Amazon.S3.Model;
using PixelFlow.Models.S3Service;

namespace PixelFlow.Services
{
    public interface IS3Service
    {
        public Task<bool?> ObjectExistsAsync(string fileName);
        public Task<GetObjectResponse?> GetObjectAsync(string fileName);
        public Task<ListObjectsPage?> ListObjectsAsync(int maxObjectsCount, string nextPageCursor);
        public Task<bool> UploadObjectAsync(string filePath, string fileName);
    }

    public class S3Service : IS3Service
    {
        private static IConfiguration _configuration;
        
        public S3Service(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        private static readonly AmazonS3Config s3Config = new()
        {
            ServiceURL = _configuration["Secrets:S3_SERVICE_URL"] //System.NullReferenceException: 'Object reference not set to an instance of an object.'
        };

        private static AmazonS3Client client = new AmazonS3Client(
            _configuration["Secrects:S3_ACCESS_KEY_ID"], _configuration["Secrets:S3_ACCESS_KEY"], s3Config);

        public async Task<bool?> ObjectExistsAsync(string fileName)
        {
            ...
        }

        public async Task<GetObjectResponse?> GetObjectAsync(string fileName)
        {
            ...
        }

        public async Task<ListObjectsPage?> ListObjectsAsync(int maxObjectsCount, string nextPageCursor)
        {
            ...
        }

        public async Task<bool> UploadObjectAsync(string filePath, string fileName)
        {
            ...
        }
    }
}

Solution

  • First you need to create an interface for the S3Service, then implement the interface in the S3Service and then register your S3Service in the program.cs file like the following:

    1. Create interface

    public interface IS3Service
    {
        public bool UploadFileToS3(string filePath); // Example interface method
    }
    

    2. Implement interface

    public class S3Service : IS3Service // <- Add this 
    {
        private static IConfiguration _configuration;
    }
    
    public S3Service(IConfiguration configuration)
    {
        _configuration = configuration;
    }
    
    public bool UploadFileToS3(string filePath)
    {
        // Upload File to S3 implementation
    }
    

    3. Register the S3Service in the program.cs file

    builder.Services.AddTransient<IS3Service, S3Service>();
    

    With the above in place you should be able to get the configuration values from the secrets.json. Try it out and let me know how it goes.