Search code examples
asp.net-mvciisdeploymentasp.net-core-6.0

An issue with ConnectionString being secrets.json while deploying to an IIS ASP.NET CORE6


EDIT: The Issue lies with the secrets.json connection string. Since it is in secrets.json which is not a part of the app's folder it is thusly unreachable by the whatever IIS's component which runs the app. Now I wneed an advice if there is a way to make the whole ConnectionString in secrets.json work in a production environment. It is not the best practise solution I know, but for the current use it is acceptable.

End of an edit

I have deployed my ASP.NET CORE 6 app to a folder as per many online guides. After few tries and errors I have made it work. For further explanation, I am talking about running the app as follows: I start this exe.

enter image description here

Then I put localhsot:5000 into my browser and the app runs.

BUT! It used to have an error like this:

Error. An error occurred while processing your request.

After checking EventLog I have discovered my app upon being deployed fails to find ConnectionString. Fair enough, mine is hidden in a secret.json. I had to put this line of code into program.cs

if (!(builder.Environment.IsDevelopment()))
{
    builder.Configuration.AddUserSecrets<Program>();
}

Then it started working and the error was no more.

What I need is to make the app run from IIS environment like this:

  1. I start IIS app.
  2. Locate my web site in the left-hand panel.
  3. Click on the "browse web" link in the right-side panel.

This loads the app in my browser. But Lo and behold! The good old error with unreachable ConnectionString is back!

Few notes here. I have everything deployed uptodate. Physical path in my web is directed towards the file with the already working and previously mentioned exe. file. The event log error is provided at the end of this question.

My whole program.cs code is as follows:

using Microsoft.AspNetCore.Authentication.Negotiate;
using Microsoft.EntityFrameworkCore;
using AktualniSchemaHfEditor.Data;
using System.Configuration;
using AktualniSchemaHfEditor.Models;
using System;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.Authorization;
using System.Net;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddControllersWithViews();

builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme)
   .AddNegotiate();

builder.Services.AddAuthorization(options =>
{
    // By default, all incoming requests will be authorized according to the default policy.
    options.FallbackPolicy = options.DefaultPolicy;
});
builder.Services.AddRazorPages();

if (builder.Environment.IsProduction())
{
    builder.Configuration.AddUserSecrets<Program>();
}

builder.Services.AddDbContext<AktualniSchemaHfEditor.Data.ModelContext>(options =>
        options.UseOracle(builder.Configuration.GetConnectionString("Default")));

var users = File.ReadAllLines("D:\\Users\\992960t\\source\\repos\\AktualniSchemaHfEditor\\AllowedUsers\\AllowedUsersList.txt");

builder.Services.AddMvc(config =>
{
    var policy = new AuthorizationPolicyBuilder()
                   .RequireAssertion(x =>
                         users.Any(
                             u => u.Equals(
                                 x.User.Identity!.Name, StringComparison.OrdinalIgnoreCase
                             )
                         )
                    )
                   .Build();
    config.Filters.Add(new AuthorizeFilter(policy));
});


//Následující kód je alternativa k ověřování uživatelů výše. Akorát jde o konkrétní výčet nikoliv čtení ze složky.

//builder.Services.AddMvc(config =>
//{
//    var policy = new AuthorizationPolicyBuilder()
//                   .RequireAssertion(x =>
//                         x.User.Identity!.Name == "VSSKB\\992960t" ||
//                         x.User.Identity!.Name == "VSSKB\\990967y"
//                         )
//                   .Build();
//    config.Filters.Add(new AuthorizeFilter(policy));
//});

var app = builder.Build();

// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Home/Error");
    // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller=Home}/{action=Index}/{RowId?}");

app.Run();

Please help me and have a great day.

Event log error:

Category: Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware EventId: 1 SpanId: 474bc069eae9db4e TraceId: 436cb73eb448c3c5ab5b85befc99d45b ParentId: 0000000000000000 RequestId: 8000000f-0002-fd00-b63f-84710c7967bb RequestPath: /AktualniSchemaHf/Index An unhandled exception has occurred while executing the request. Exception: System.ArgumentNullException: Value cannot be null. (Parameter 'connectionString') at Oracle.EntityFrameworkCore.Utilities.Check.NotEmpty(String value, String parameterName) at Microsoft.EntityFrameworkCore.OracleDbContextOptionsExtensions.UseOracle(DbContextOptionsBuilder optionsBuilder, String connectionString, Action1 oracleOptionsAction) at Program.<>c__DisplayClass0_0.<<Main>$>b__1(DbContextOptionsBuilder options) in D:\Users\992960t\source\repos\AktualniSchemaHfEditor\Program.cs:line 28 at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass1_02.b__0(IServiceProvider _, DbContextOptionsBuilder b) at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.CreateDbContextOptions[TContext](IServiceProvider applicationServiceProvider, Action2 optionsAction) at Microsoft.Extensions.DependencyInjection.EntityFrameworkServiceCollectionExtensions.<>c__DisplayClass17_01.b__0(IServiceProvider p) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitFactory(FactoryCallSite factoryCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitConstructor(ConstructorCallSite constructorCallSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSiteMain(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitCache(ServiceCallSite callSite, RuntimeResolverContext context, ServiceProviderEngineScope serviceProviderEngine, RuntimeResolverLock lockType) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.VisitScopeCache(ServiceCallSite callSite, RuntimeResolverContext context) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteVisitor2.VisitCallSite(ServiceCallSite callSite, TArgument argument) at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteRuntimeResolver.Resolve(ServiceCallSite callSite, ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.DynamicServiceProviderEngine.<>c__DisplayClass2_0.b__0(ServiceProviderEngineScope scope) at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType, ServiceProviderEngineScope serviceProviderEngineScope) at Microsoft.Extensions.DependencyInjection.ServiceLookup.ServiceProviderEngineScope.GetService(Type serviceType) at Microsoft.Extensions.DependencyInjection.ActivatorUtilities.GetService(IServiceProvider sp, Type type, Type requiredBy, Boolean isDefaultParameterRequired) at lambda_method19(Closure , IServiceProvider , Object[] ) at Microsoft.AspNetCore.Mvc.Controllers.ControllerActivatorProvider.<>c__DisplayClass7_0.b__0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass6_0.g__CreateController|0(ControllerContext controllerContext) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope) at Microsoft.AspNetCore.Routing.EndpointMiddleware.g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Authorization.Policy.AuthorizationMiddlewareResultHandler.HandleAsync(RequestDelegate next, HttpContext context, AuthorizationPolicy policy, PolicyAuthorizationResult authorizeResult) at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context) at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.g__Awaited|6_0(ExceptionHandlerMiddleware middleware, HttpContext context, Task task)


Solution

  • secret.json cannot be used for ConnectionString storage in production while app is deployed on IIS since it is not part of the root folder of the app. Making it so would defeat the secresy purpose. Thusly, different ,methods are used to store ConnectionString in production. For example Environment Variables. These have to be set up on the server. In IIS manager you right-click your site, go to the configuration manager, change the path to system.webServer/aspNetCore and find a row with EV. There you set up the name and the content of saif variable. Other options are Azure KeyValut, but with that I have not worked as of yet.