Search code examples
nginx.net-coreubuntu-20.04

Dotnet core Configuration bind doesn't work on ubuntu nginx


I've been trying to host dotnet core on ubuntu server with nginx app server. Once all my code worked on DEV machine (windows 11), I published my code to the server. Swagger works but actual API call doesn't, it throws internal server error. Upon logging, I find out that below line doesn't bind the configuration properly in my startup/Program.cs code. However, it works perfectly in my DEV machine and also on windows server using VirtualBox.

    var authorizationOptions = new AuthorizationOptions();
    config.GetSection(AuthorizationOptions.ConfigKey).Bind(authorizationOptions);
    //authorizationOptions has no values post .Bind

AuthorizationOptions.cs

    public class AuthorizationOptions
    {
        public const string ConfigKey = "Authorization";
    
        public string? ActiveProvider { get; set; }
    
        public List<AuthorizationProviderOptions>? Providers { get; set; }
    } 

AuthorizationProviderOptions.cs

    public class AuthorizationProviderOptions
    {
        public string Name { get; set; } = string.Empty;
        public string Domain { get; set; } = string.Empty;
        public string Audience { get; set; } = string.Empty;
        public string SecretKey { get; set; } = string.Empty;
        public string Issuer { get; set; } = string.Empty;
        public string TokenLifetime { get; set; } = string.Empty;
    }

appsettings.json

    {   
        "Authorization": {
            "ActiveProvider": "JWT",
            "Providers": [
                {
                    "Name": "Auth0",
                    "Domain": "XXXXXXXXXXXXXXXXXXXXX",
                    "SecretKey": "",
                    "Issuer": "",
                    "Audience": "XXXXXXXXXXXXXXXXXXXXX",
                    "TokenLifetime": "20"
                },
                {
                    "Name": "JWT",
                    "Domain": "",
                    "SecretKey": "XXXXXXXXXXXXXXXXXXXXX",
                    "Issuer": "XXXXXXXXXXXXXXXXXXXXX",
                    "Audience": "XXXXXXXXXXXXXXXXXXXXX",
                    "TokenLifetime": "20"
                }
            ]
        }
    }

Other details:

.NET Version: 8

Server: Ubuntu 20.04

I'm scratching my head for the past couple of days. Any help would be appreciated, thanks.

Update: From where I'm calling the configuration code:

Program.cs (API project)

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCAAuthentication(builder.Configuration);

AuthorizationInjectorServiceExtension.cs (This file is in a different class library project which is referenced by the API project)

public static class AuthorizationInjectorServiceExtension
{
    public static IServiceCollection AddCAAuthentication(this IServiceCollection services, IConfigurationManager config)
    {
        var authorizationOptions = new AuthorizationOptions();
        config.GetSection(AuthorizationOptions.ConfigKey).Bind(authorizationOptions);

        //do other things based on the values of authorizationOptions
    }    
}

Update 2: After @FolabiAhn's comment, I moved the appsettings.json one folder up and now it's working! However, I'm still unsure why this is so.

Previous directory structure:

/var/www/[mysitename]/html/[site files with appsettings.json]

New directory structure that works:

/var/www/[mysitename]/html/[site files]

/var/www/[mysitename]/appsettings.json

I'm using the html sub folder structure just to follow nginx/ubuntu's style. I can always change it.


Solution

  • This behavior originates from the utilization of WebApplication.CreateBuilder(args). It automatically assigns the ContentRootPath to Directory.GetCurrentDirectory().

    Consequently, when attempting to locate appsettings.json, the current working directory is referenced, rather than necessarily the application's directory. I bet you are executing the application from outside of its designated directory, leading to the inability to locate the .json files.

    To address this, you have a couple of options. Firstly, you can navigate to the path directory of your application using cd and then execute the application from there.

    Second if you intend to run application as a service, you could configure the working directory to match that of the application itself.

    [Unit]
    Description=My Application ...
    [Service]
    WorkingDirectory=/var/www/[mysitename]/html
    ExecStart=/usr/bin/dotnet /var/www/[mysitename]/html/Application.dll
    ...