Root cause: HealthChecks.UI (Xabaril) internally uses IdentityModel for some scenarios (e.g., OAuth2 discovery, client credentials). In certain dependency graphs, IdentityModel isn’t copied to the output when it’s only a transitive dependency. Then the HealthChecks UI background collector fails with “Could not load file or assembly 'IdentityModel, Version=5.2.0.0'”.
Quick fix (per project failing at runtime, e.g., *.Web and *.ApiHost):
<ItemGroup>
<PackageReference Include="IdentityModel" Version="5.2.0" />
</ItemGroup>
services
.AddHealthChecks()
.AddCheck<MyProjectNameDatabaseCheck>("Database");
services.AddHealthChecksUI(settings =>
{
settings.AddHealthCheckEndpoint("Self", "/health-status"); // or your configured URL
})
.AddInMemoryStorage();
settings.AddHealthCheckEndpoint("Self", $"http://{System.Net.Dns.GetHostName()}/health-status");
Otherwise keep using the configured healthCheckUrl string.
Why this is safe: The IdentityModel package is a pure client library (no side effects if unused at runtime) and matches the HealthChecks UI’s transitive expectation. Adding it explicitly pins the assembly and avoids loader failures.
Optional: Align HealthChecks packages
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
Why it happens
Fix step-by-step
public class SaasFeaturesDefinitionProvider : FeatureDefinitionProvider
{
public override void Define(IFeatureDefinitionContext context)
{
var group = context.GetGroupOrNull(ModulesFeatures.Main)
?? context.AddGroup(ModulesFeatures.Main, L("MainFeatures"));
group.AddFeature(
SaasFeatures.Saas,
defaultValue: "true",
displayName: L(SaasFeatures.Saas),
isVisibleToClients: true // critical for WASM menu visibility
);
}
private static LocalizableString L(string name)
=> LocalizableString.Create<PlatformResource>("Features:" + name);
}
[DependsOn(
typeof(AbpFeaturesModule),
typeof(Payhas.Common.FeaturesModule) // your package/module that defines groups & features
)]
public class PlatformDomainModule : AbpModule
{
}
var saas = context.Menu.GetMenuItem(SaasHostMenus.GroupName);
saas.RequireFeatures(SaasFeatures.Saas);
The client reads features from the Application Configuration endpoint, which is cached by default on the client side. Reloading the page after changing features is typically enough; server-side feature store uses distributed cache. Ensure your distributed cache (e.g., Redis) is correctly configured in all services that participate.
Expected outcome
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
Setup steps (MVC):
private void ConfigureBlobStoring(IConfiguration configuration)
{
Configure<AbpBlobStoringOptions>(options =>
{
options.Containers.Configure<FileManagementContainer>(c =>
{
c.UseFileSystem(fs =>
{
fs.BasePath = configuration["FileManagement:BasePath"]; // e.g. "D:\\abp-files"
});
// You can alternatively use Database or Azure providers.
});
});
}
[DependsOn(
typeof(FileManagementWebModule) // plus other module deps
)]
public class YourProjectWebModule : AbpModule
{ }
Key points:
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
Fix/checklist:
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.Modularity;
[DependsOn(
typeof(AbpAspNetCoreMvcModule),
typeof(AmlReportServiceApplicationModule) // your app module
)]
public class AmlReportServiceHttpApiModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpAspNetCoreMvcOptions>(options =>
{
options.ConventionalControllers.Create(typeof(AmlReportServiceApplicationModule).Assembly);
});
}
}
If CustomStaticDataTypeAppService resides in a different assembly, pass that assembly instead.
[RemoteService(true)]
public class CustomStaticDataTypeAppService : StaticDataTypeAppService, ICustomStaticDataTypeAppService
{
// ...
}
Verify the remote service name/group for your controller so the JS proxy endpoint includes it. If you changed the controller name with [RemoteService(Name = "AmlReportService")] or ApiExplorerGroupName, ensure you request the correct group from the ServiceProxyScript if you are filtering by module. For example:
If you are in a tiered setup, ensure the MVC/UI application points to and loads the ServiceProxyScript from the AMLReportService HttpApi host that actually exposes the controllers. Load and inspect:
Use only async methods in app services. JS proxies are generated for the HTTP endpoints created from async methods (Task/Task<T>) on IApplicationService. Your signatures already look async; keep that.
Clear caches/restart and re-check: since ServiceProxyScript is generated on request, restart the HttpApi host after code changes and hard-refresh the browser to avoid caching.
Quick verification flow:
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
// In YourProjectNameEfCoreEntityExtensionMappings.Configure()
ObjectExtensionManager.Instance
.MapEfCoreProperty<IdentityUser, string>(
MyConsts.MyPropertyName,
(entityBuilder, propertyBuilder) =>
{
propertyBuilder.HasMaxLength(128);
// optional: propertyBuilder.HasDefaultValue("");
// optional: add index/unique/etc.
}
);
- Ensure this mapping executes before DbContext model building (use the generated EfCoreEntityExtensionMappings class).
- Add a migration and update the database.
ObjectExtensionManager.Instance.Modules().ConfigureIdentity(identity =>
{
identity.ConfigureUser(user =>
{
user.AddOrUpdateProperty<Guid?>(
MyConsts.MyPropertyName,
options =>
{
options.DefaultValue = null;
options.UI.OnTable.IsVisible = true;
options.UI.OnCreateForm.IsVisible = false;
// optionally:
// options.UI.OnEditForm.IsVisible = true;
}
);
});
});
Notes:
End-to-end checklist for your case (ABP 9.1.3, Blazor Server, SQL Server)
// Domain.EfCore project
public static class YourProjectEfCoreEntityExtensionMappings
{
private static readonly OneTimeRunner OneTimeRunner = new OneTimeRunner();
public static void Configure()
{
OneTimeRunner.Run(() =>
{
ObjectExtensionManager.Instance
.MapEfCoreProperty<IdentityUser, string>(
MyConsts.MyPropertyName,
(_, p) =>
{
p.HasMaxLength(128);
}
);
});
}
}
- Call YourProjectEfCoreEntityExtensionMappings.Configure() during pre-DbContext configuration (usually in your EntityFrameworkCore module’s ConfigureServices).
- Run Add-Migration and Update-Database.
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
Root cause
What to do
public class SaasFeaturesDefinitionProvider : FeatureDefinitionProvider
{
public override void Define(IFeatureDefinitionContext context)
{
var group = context.GetGroupOrNull(ModulesFeatures.Main)
?? context.AddGroup(ModulesFeatures.Main, L("MainFeatures"));
group.AddFeature(
SaasFeatures.Saas,
defaultValue: "true",
displayName: L(SaasFeatures.Saas),
isVisibleToClients: true // <<< important
);
}
private static LocalizableString L(string name)
=> LocalizableString.Create<PlatformResource>("Features:" + name);
}
[DependsOn(
typeof(AbpFeaturesModule)
// + your package/module that contains the FeatureDefinitionProvider
)]
public class PlatformDomainModule : AbpModule
{
}
var saas = context.Menu.GetMenuItem(SaasHostMenus.GroupName);
saas.RequireFeatures(SaasFeatures.Saas);
defaultValue: "true" is used only if there is no stored value. If you manage the feature in UI, the database value takes precedence.
Ensure the tenant/host you are testing has the feature enabled in the Features modal.
Quick checklist
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
Follow these steps:
Determine your Auth Server base URL
Create or confirm a client that allows the password flow
Postman request to get the token (password grant)
Important multi-tenancy notes
Use the token in JMeter
Example curl (equivalent to Postman) curl -X POST "https://localhost:44322/connect/token" ^ -H "Content-Type: application/x-www-form-urlencoded" ^ -H "Abp-TenantId: 11111111-1111-1111-1111-111111111111" ^ --data-urlencode "grant_type=password" ^ --data-urlencode "username=admin@mytenant.com" ^ --data-urlencode "password=1q2w3E*" ^ --data-urlencode "client_id=MyAngular_App" ^ --data-urlencode "client_secret=1q2w3e*" ^ --data-urlencode "scope=openid profile email roles offline_access MyProjectName"
If you prefer client credentials (app-to-app, no user), use:
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
Please contact us at https://abp.io/contact.
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.
[maliming] said: hi
We plan to release 9.3.7 this week.
Thanks.
Solution
Sources
This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.