.net core api not loading connectionString from appsettings in apache (linux)

Phil 166 Reputation points
2022-06-09T08:25:41.903+00:00

Hi there

I have an api that runs locally and on IIS, that is built in .net core 3.1.
I wanted to port it to apache.

I have configured my apache server on ubuntu using the tutorials:
https://ubuntu.com/tutorials/install-and-configure-apache#5-activating-virtualhost-file
https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-6.0
https://www.youtube.com/watch?v=mBhT_MRwGYE

I have published the application using:
Configuration: release
Target FrameWork: netcoreapp3.1
Target Runtime: linux-x64

I am running a ubuntu server with apache.

When doing a basic get request from postman I am able to get a response.
When I try to post data to the server I get an error.

ERROR:Microsoft.AspNetCore.Server.Kestrel[13]
Connection id "0HMI9TOFJRJDT", Request id "0HMI9TOFJRJDT:00000003": An unhandled exception was thrown by the application.
System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString')
at Microsoft.EntityFrameworkCore.Utilities.Check.NotEmpty(String value, String parameterName)
at Microsoft.EntityFrameworkCore.SqlServerDbContextOptionsExtensions.UseSqlServer(DbContextOptionsBuilder optionsBuilder, String connectionString, Action`1 sqlServerOptionsAction)

This sounds like the appsettings.json Connection strings are not being read by the application (I may be wrong).

On IIS this works as expected.

In the appsettings.json I have the connection strings (details starred out).

"ConnectionStrings": {  
    "DB01Connection": "Server=my-server;Database=DB1;User Id=**; Password=****;",  
    "DB02Connection": "Server=my-server;Database=DB2;User Id=**; Password=****;"  
  }  

Program.cs

public class Program  
    {  
        public static void Main(string[] args)  
        {  
            CreateHostBuilder(args).Build().Run();  
        }  
  
        public static IHostBuilder CreateHostBuilder(string[] args) =>  
            Host.CreateDefaultBuilder(args)  
                .ConfigureWebHostDefaults(webBuilder =>  
                {  
                    webBuilder.UseStartup<Startup>();  
                });  
    }  

Startup.cs

 public class Startup  
    {  
        public Startup(IConfiguration configuration)  
        {  
            Configuration = configuration;  
        }  
  
        public IConfiguration Configuration { get; }  
  
        readonly string MyAllowSpecificOrigins = "_myAllowSpecificOrigins";  
  
        // This method gets called by the runtime. Use this method to add services to the container.  
        public void ConfigureServices(IServiceCollection services)  
        {  
            services.AddDbContext<SecureWebApiCore.Models.User.ApplicationDbContext>(options =>  
             options.UseSqlServer(  
                  Configuration.GetConnectionString("DB01Connection")));  
  
            services.AddIdentity<ApplicationUser, IdentityRole>(options => options.SignIn.RequireConfirmedAccount = true)  
                                                                .AddDefaultTokenProviders()  
                                                                .AddPasswordlessLoginTotpTokenProvider()  
                                                                .AddEntityFrameworkStores<ApplicationDbContext>()  
                                                                .AddClaimsPrincipalFactory<Global.Extensions.UserClaimsPrincipalFactory>();  
  
  
  
  
            services.AddRazorPages();  
  
            services.AddLogging();  
  
            services.AddCors(c =>  
            {  
                c.AddPolicy("AllowOrigin", options => options.AllowAnyOrigin());  
            });  
  
            services.AddMvc()  
                .AddNewtonsoftJson();  
  
            services.AddControllers();  
  
            // configure jwt authentication  
            var key = Encoding.ASCII.GetBytes("testtesttesttesttesttesttesttesttesttesttesttesttest");  
            services.AddAuthentication(x =>  
            {  
                x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;  
                x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;  
            })  
            .AddJwtBearer(x =>  
            {  
                x.RequireHttpsMetadata = false;  
                x.SaveToken = true;  
                x.TokenValidationParameters = new TokenValidationParameters  
                {  
                    ValidateIssuerSigningKey = true,  
                    IssuerSigningKey = new SymmetricSecurityKey(key),  
                    ValidateIssuer = false,  
                    ValidateAudience = false  
                };  
            });  
        }  
  
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)  
        {  
            if (env.IsDevelopment())  
            {  
                app.UseDeveloperExceptionPage();  
            }  
  
            app.UseRouting();  
            app.UseCors(options => options.AllowAnyOrigin());  
  
            app.UseAuthentication();  
            app.UseAuthorization();  
  
            app.UseEndpoints(endpoints =>  
            {  
                endpoints.MapControllers();  
            });  
        }  
    }  

IdentityHostingStartup.cs

public class IdentitytHostingStartup : IHostingStartup  
    {  
        public void Configure(IWebHostBuilder builder)  
        {  
            builder.ConfigureServices((context, services) =>  
            {  
                services.AddDbContext<FrameWowContext>(options =>  
                    options.UseSqlServer(  
                        context.Configuration.GetConnectionString("DB01Connection")));  
            });  
        }  
    }  

Ubuntu Apache configuration

<VirtualHost *:*>  
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}  
</VirtualHost>  
  
<VirtualHost *:443>  
 # The ServerName directive sets the request scheme, hostname and port that  
 # the server uses to identify itself. This is used when creating  
 # redirection URLs. In the context of virtual hosts, the ServerName  
 # specifies what hostname must appear in the request's Host: header to  
 # match this virtual host. For the default virtual host (this file) this  
 # value is not decisive as it is used as a last resort host regardless.  
 # However, you must set it for any further virtual host explicitly.  
 #ServerName www.example.com  
  
    Protocols   h2 http/1.1  
    ProxyPreserveHost On  
    ProxyPass / http://127.0.0.1:5000/  
 ProxyPassReverse / http://127.0.0.1:5000/  
 ErrorLog ${APACHE_LOG_DIR}/error-webnix.com.log    
    CustomLog ${APACHE_LOG_DIR}/access-webnix.com.log combined   
    SSLEngine on  
    SSLProtocol           all -SSLv3 -TLSv1 -TLSv1.1  
    SSLHonorCipherOrder   off  
    SSLCompression        off  
    SSLSessionTickets     on  
    SSLUseStapling        off  
    SSLCertificateFile /etc/apache2/certificate/apache-certificate.crt  
    SSLCertificateKeyFile /etc/apache2/certificate/apache.key  
      
      
 ServerAdmin webmaster@localhost  
 ServerName abc.example.uk  
 ServerAlias www.abc.example.uk  
 DocumentRoot /var/www/apacheTest/  
</VirtualHost>  
  
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet  

The api is set up to use SSL and the certificates are valid. It is running over https.
I am not sure if I need to add something to the start up to specify where the appsettings should be loaded in kestral?

Any help would be appreciated
Many thanks

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
2,562 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
6,975 questions
No comments
{count} votes

Accepted answer
  1. Bruce (SqlWork.com) 28,196 Reputation points
    2022-06-09T15:16:38.857+00:00

    Be sure you set working folder in the service file, and the appsettings is in this folder. Once the launchd has started your asp.net core app, you should be able to access it directly with postman.

    No comments

0 additional answers

Sort by: Most helpful