Web Hosting Configuration - Skills Guide¶
Skill Type: Web Application & UI Configuration
Technology Stack: .NET, ABP Framework, ASP.NET Core MVC, Valkey, OpenIddict
Complexity Level: Intermediate
Last Updated: 2025
📋 Overview¶
This guide covers configuring the web hosting project in a layered ABP application, including Valkey caching, virtual file system, NPM packages, remote services, branding, and AuthServer integration.
Configuration Areas¶
- ✅ Valkey/Redis distributed caching & locking
- ✅ Virtual file system configuration
- ✅ NPM package management
- ✅ Remote services endpoints
- ✅ Branding customization
- ✅ AuthServer integration
📦 Step 1: Configure Caching with Valkey¶
- Replace
Volo.Abp.Caching.StackExchangeRediswithGridLab.Abp.Caching.StackExchangeValkeymodule.
Remove:
<ItemGroup>
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="X.Y.Z" />
</ItemGroup>
Add:
<ItemGroup>
<PackageReference Include="GridLab.Abp.Caching.StackExchangeValkey" Version="X.Y.Z" />
</ItemGroup>
Replace package at GMSSAuthServerModule.cs
[DependsOn(
typeof(GMSSEntityFrameworkCoreModule)
//...other dependencies
~~typeof(AbpStackExchangeRedisModule),~~
typeof(AbpGridLabStackExchangeValkeyModule),
//...other dependencies
)]
public class GMSSAuthServerModule : AbpModule
{
}
Add ConfigureCache, ConfigureDataProtection and ConfigureDistributedLocking methods for handling cache connections.
private void ConfigureCache(IConfiguration configuration)
{
Configure<AbpDistributedCacheOptions>(options =>
{
options.KeyPrefix = "GMSS:";
});
}
Use AbpValkeyConfigurationHelper.CreateConfigurationOptions helper method to create connection.
private void ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration,
IWebHostEnvironment hostingEnvironment)
{
if (AbpStudioAnalyzeHelper.IsInAnalyzeMode)
{
return;
}
var dataProtectionBuilder = context.Services.AddDataProtection().SetGMSS("GMSS");
if (!hostingEnvironment.IsDevelopment())
{
var certificateProvider = context.Services.GetCertificateProvider();
var certificateValidator = context.Services.GetCertificateValidator();
var options = configuration
.GetSection(AbpGridLabValkeyOptions.ServiceName)
.Get<AbpGridLabValkeyOptions>() ?? new AbpGridLabValkeyOptions();
var configurationOptions = AbpValkeyConfigurationHelper.CreateConfigurationOptions(
serviceOptions: options,
certificateProvider: certificateProvider,
certificateValidator: certificateValidator
);
var redis = ConnectionMultiplexer.Connect(configurationOptions);
dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "GMSS-Protection-Keys");
}
}
private void ConfigureDistributedLocking(ServiceConfigurationContext context, IConfiguration configuration)
{
if (AbpStudioAnalyzeHelper.IsInAnalyzeMode)
{
return;
}
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var certificateProvider = context.Services.GetCertificateProvider();
var certificateValidator = context.Services.GetCertificateValidator();
var options = configuration
.GetSection(AbpGridLabValkeyOptions.ServiceName)
.Get<AbpGridLabValkeyOptions>() ?? new AbpGridLabValkeyOptions();
var configurationOptions = AbpValkeyConfigurationHelper.CreateConfigurationOptions(
serviceOptions: options,
certificateProvider: certificateProvider,
certificateValidator: certificateValidator
);
var connection = ConnectionMultiplexer.Connect(configurationOptions);
return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
});
}
Add a new section for caching to application configuration settings.
"Valkey": {
"Enabled": true,
"Configuration": {
"Configuration": "127.0.0.1"
},
"Ssl": {
"Enabled": false
},
"Connection": {
"ConnectTimeout": 30,
"ConnectRetry": 3
}
},
📁 Step 2: Configure Virtual File System¶
- Verify virtual file system path values match module and folder names at
GMSSWebHostModule.cs:
private void ConfigureVirtualFileSystem(IWebHostEnvironment hostingEnvironment)
{
if (hostingEnvironment.IsDevelopment())
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.ReplaceEmbeddedByPhysical<GMSSDomainSharedModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}GridLab.Gmss.Domain.Shared", Path.DirectorySeparatorChar)));
options.FileSets.ReplaceEmbeddedByPhysical<GMSSApplicationContractsModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}GridLab.Gmss.Application.Contracts", Path.DirectorySeparatorChar)));
options.FileSets.ReplaceEmbeddedByPhysical<GMSSWebModule>(Path.Combine(hostingEnvironment.ContentRootPath, string.Format("..{0}..{0}src{0}GridLab.Gmss.Web", Path.DirectorySeparatorChar)));
});
}
}
📦 Step 3: Verify NPM Packages¶
- Check npm package versions in
package.json:
{
"version": "1.0.0",
"name": "my-app",
"private": true,
"dependencies": {
"@volo/abp.aspnetcore.mvc.ui.theme.lepton": "~8.2.0",
"@volo/saas": "~8.2.0",
"@volo/identity": "~8.2.0",
"@volo/account": "~8.2.0"
}
}
🌐 Step 4: Configure Remote Services¶
- Configure remote service endpoints in
appsettings.json:
{
"RemoteServices": {
"Default": {
"BaseUrl": "http://localhost:53929" // Note port number needs to adjusted according to project requirement
},
"GMSS": {
"BaseUrl": "https://localhost:44338" // Note port number needs to adjusted according to project requirement
}
}
}
🎨 Step 5: Update Branding Provider¶
- Update
GMSSBrandingProvider.csatGridLab.Gmss.WebHostproject root.
Copy the wwwroot folder from the template to host/GridLab.Gmss.WebHost. Delete existing logo-dark.png and logo-light.png logos.
[Dependency(ReplaceServices = true)]
public class GMSSBrandingProvider : DefaultBrandingProvider
{
private IStringLocalizer<GMSSResource> _localizer;
public GMSSBrandingProvider(IStringLocalizer<GMSSResource> localizer)
{
_localizer = localizer;
}
public override string AppName => "GMSS Auth Server";
public override string LogoUrl => "/images/logo/leptonx/logo-light.png";
public override string LogoReverseUrl => "/images/logo/leptonx/logo-dark.png";
}
📝 Step 6: Update Program.cs Logging¶
- Enable console logging in release configuration:
public async static Task<int> Main(string[] args)
{
Log.Logger = new LoggerConfiguration()
#if DEBUG
.MinimumLevel.Debug()
#else
.MinimumLevel.Information()
#endif
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
.Enrich.FromLogContext()
.WriteTo.Async(c => c.File("Logs/logs.txt"))
.WriteTo.Async(c => c.Console())
.CreateLogger();
//....
}
🔐 Step 7: Configure AuthServer Settings¶
- Extend AuthServer configuration in
appsettings.json:
"AuthServer": {
"Authority": "https://localhost:44324",
"RequireHttpsMetadata": "true",
"MetadataAddress": "https://localhost:44324",
"IsOnK8s": "false",
"ClientId": "GMSS_Web", // Update according module name
"ClientSecret": "1q2w3e*"
}