I have 4 .NET 9.0 web sites that I'm trying to get running on Linux; 3 of them run fine, but when I try to run the last one, I get the following error:
Could not load type 'Microsoft.AspNetCore.Server.IIS.IIISEnvironmentFeature' from assembly 'Microsoft.AspNetCore.Server.IIS, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'
It's happening on the host.Run()
line.
public class Program
{
public static void Main(string[] args)
{
var builder = CreateHostBuilder(args);
var host = builder.Build();
host.Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
I can't find any reference to an IIS package or anything like that anywhere in the code. I've compared the program and startup files between the failing site and one that works but I'm not seeing anything obvious that's different between the two that should cause an IIS error. And my launchsettings
profiles are not set to use IIS either.
Here's the launchsettings.json
for the failing site.
{
"profiles": {
"FW": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "home",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
},
"dotnetRunMessages": "true",
"applicationUrl": "https://localhost:7200;http://localhost:5200"
}
}
}
Here is the Startup.cs
file:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
SiteConfigurationSettings.LoadConfiguration(Configuration);
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
var mvcBuilder = services.AddControllersWithViews(options =>
{
// provides model binding for json that doesn't bind to a strongly-typed model
options.ModelBinderProviders.Insert(0, new JsonValueTypeModelBinderProvider());
})
.AddSessionStateTempDataProvider()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
services.AddDataProtection()
.PersistKeysToDbContext<DataProtectionDbContext>()
.SetApplicationName("FW");
// configures session to use SqlServer
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = DataSources.SessionStateSource;
options.SchemaName = DataSources.SessionStateDefaultSchema;
options.TableName = DataSources.FWSessionsTable;
});
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromHours(5);
options.Cookie.Name = "FW.Session";
options.Cookie.IsEssential = true;
});
services.Configure<RazorViewEngineOptions>(options =>
{
var expander = new CustomViewLocationExpander();
options.ViewLocationExpanders.Add(expander);
});
services.Configure<FormOptions>(options =>
{
options.ValueCountLimit = int.MaxValue;
});
services.ConfigureOptions<StaticFilePathResolver>();
services.AddRazorPages();
#if DEBUG
mvcBuilder.AddRazorRuntimeCompilation();
#endif
services.AddSystemWebAdapters();
services.AddHttpLogging();
services.AddHttpContextAccessor();
services.AddDistributedSqlServerCache(x =>
{
x.ConnectionString = DataSources.CacheConnectionString;
x.SchemaName = "dbo";
x.TableName = "CacheData";
});
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var spec = new FWRegistrySpec();
services.RegisterFHServices(spec);
services.InitializeAutoMapper();
services.AddMemoryCache();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use((context, next) =>
{
context.Response.Headers.Add("x-machine-name", Environment.MachineName);
return next.Invoke();
});
app.UseMiddleware(typeof(FHHeadersMiddleware));
app.UseHostFiltering();
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot"))
});
app.UseSession();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Request.EnableBuffering();
await next();
});
app.UseCookiePolicy(
new CookiePolicyOptions
{
Secure = CookieSecurePolicy.Always
});
var startupManager = new PortalStartupManager(app);
app = startupManager.RegisterErrorHandler();
app.UseHsts();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
"default",
"{controller=Login}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
app.UseSystemWebAdapters();
startupManager.Startup();
var scope = app.ApplicationServices.CreateScope();
var security = scope.ServiceProvider.GetService<IFHWareSecurity>();
security?.CreateSecurityCache();
}
}
In one of the other sites that is working, the Program.cs
file is identical and here is the Startup.cs
file:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
SiteConfigurationSettings.LoadConfiguration(Configuration);
}
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(options =>
{
// provides model binding for json that doesn't bind to a strongly-typed model
options.ModelBinderProviders.Insert(0, new JsonValueTypeModelBinderProvider());
})
.AddSessionStateTempDataProvider()
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.PropertyNamingPolicy = null;
});
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
services.Configure<KestrelServerOptions>(options =>
{
options.AllowSynchronousIO = true;
});
services.AddDataProtection()
.PersistKeysToDbContext<DataProtectionDbContext>()
.SetApplicationName("FH.Employees");
// configures session to use SQL Server
services.AddDistributedSqlServerCache(options =>
{
options.ConnectionString = DataSources.SessionStateSource;
options.SchemaName = DataSources.SessionStateDefaultSchema;
options.TableName = DataSources.EmployeesSessionTable;
});
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromHours(5);
options.Cookie.Name = "FH.Employees.Session";
options.Cookie.IsEssential = true;
});
// configures file paths for static web (js, css) assets
services.ConfigureOptions<StaticFilePathResolver>();
services.AddRazorPages();
#if DEBUG
mvcBuilder.AddRazorRuntimeCompilation();
#endif
services.AddHttpContextAccessor();
services.AddDistributedSqlServerCache(x =>
{
x.ConnectionString = DataSources.CacheConnectionString;
x.SchemaName = "dbo";
x.TableName = "CacheData";
});
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
var spec = new EmployeeRegistrySpec(services);
services.RegisterFHServices(spec);
services.InitializeAutoMapper();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseMiddleware(typeof(FHHeadersMiddleware));
app.UseHostFiltering();
app.UseForwardedHeaders();
app.UseHttpsRedirection();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(), "wwwroot"))
});
app.UseSession();
app.Use(async (context, next) => {
context.Request.EnableBuffering();
await next();
});
app.UseCookiePolicy(
new CookiePolicyOptions
{
Secure = CookieSecurePolicy.Always
});
var startupManager = new PortalStartupManager(app);
app = startupManager.RegisterErrorHandler();
app.UseHsts();
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Login}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
startupManager.Startup();
}
}
And this is its launchsettings.json
:
{
"profiles":{
"FH.Employees": {
"commandName": "Project",
"launchBrowser": true,
"launchUrl": "dashboard",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"ASPNETCORE_HOSTINGSTARTUPASSEMBLIES": "Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation"
},
"dotnetRunMessages": "true",
"applicationUrl": "https://localhost:44342;http://localhost:5000"
}
}
}
Update: as requested, here's the project file:
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<LangVersion>13</LangVersion>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EPPlus" Version="8.0.3" />
<PackageReference Include="ExcelDataReader.DataSet" Version="3.6.0" />
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Razor.RuntimeCompilation" Version="9.0.3" />
<PackageReference Include="Microsoft.AspNetCore.SystemWebAdapters.CoreServices" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Caching.SqlServer" Version="9.0.3" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EVerifyAPI\FH.EVerify.csproj" />
<ProjectReference Include="..\FH.Infrastructure\FH.Infrastructure.csproj" />
<ProjectReference Include="..\FH.Web.Shared\FH.Web.Shared.csproj" />
<ProjectReference Include="..\FH\FH.BusinessLogic.Core.csproj" />
<ProjectReference Include="..\FHObjectsStandard\FH.Core.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="Faker.Net.Standard.2.0">
<HintPath>..\packages\Faker.Net.2.0.154\lib\netstandard2.0\Faker.Net.Standard.2.0.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Include="wwwroot\css\Activities\activities-collapsable-list.scss" />
<None Include="wwwroot\scripts\sales\foxhire.pipeline.questionAttachment.js" />
</ItemGroup>
<ItemGroup>
<AdditionalFiles Include="Views\Activity\Dashboard\Partials\ListView\_CollapsableActivityList.cshtml" />
<AdditionalFiles Include="Views\Activity\Dashboard\Partials\ListView\_CollapsableActivityListItem.cshtml" />
</ItemGroup>
</Project>
Copied from the comment
This error occurs because UseSystemWebAdapters
internally depends on Microsoft.AspNetCore.Server.IIS
, which isn't supported on Linux.
To fix it, either remove UseSystemWebAdapters
or conditionally skip it on non-Windows platforms.