[DependsOn(/* ... */)]
public class QRSPCBaseSetServiceDomainSharedModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<BaseSetServiceResource>("en")
.AddBaseTypes(typeof(AbpValidationResource))
.AddVirtualJson("/Localization/BaseSetService"); // folder with zh-Hans.json etc.
});
}
}
3) The gateway routes /api/abp/application-localization to Administration and no cache inconsistency exists (see next).
4) If dynamic localization is enabled, ensure the Language Management DB contains the resource (initial registration occurs on first start of the resource-owning service). Restarting the service re-registers resources if needed.
Caching considerations for intermittent missing resources
Why the page returns to Home every ~45 minutes
Diagnostics 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.
What you see is expected. When you create an ABP application with Angular UI, the CLI generates:
Those “layers” are the standard ABP solution structure for a modular, maintainable backend. The Angular app consumes the backend APIs from the HttpApi.Host. Even if you don’t touch each C# project directly, they are required for a functional backend and for features like permissions, auditing, data seeding, migrations, etc.
If you want only an Angular front-end without ABP backend projects:
Summary of recommended commands:
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.
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.
Do this:
Add Elsa v3 EF packages to the Host (the app that will expose Elsa endpoints):
Configure Elsa in the Host
using Elsa.EntityFrameworkCore;
using Elsa.EntityFrameworkCore.Extensions;
using Microsoft.EntityFrameworkCore;
[DependsOn(
typeof(Volo.Elsa.Abp.AspNetCore.AbpElsaAspNetCoreModule),
typeof(Volo.Elsa.Abp.Identity.AbpElsaIdentityModule),
typeof(Volo.Elsa.Abp.Application.AbpElsaApplicationModule),
typeof(Volo.Elsa.Abp.Application.Contracts.AbpElsaApplicationContractsModule)
)]
public class MyProjectHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var cs = configuration.GetConnectionString("Default");
context.Services
.AddElsa(elsa => elsa
.UseEntityFrameworkCorePersistence(ef => ef.UseSqlServer(cs))
.UseWorkflowManagement()
.UseWorkflowRuntime(runtime => runtime.UseEntityFrameworkCore(ef => ef.UseSqlServer(cs)))
.UseScheduling()
.UseJavaScript()
.UseHttp(http => configuration.GetSection("Elsa:Http").Bind(http))
.UseWorkflowsApi());
context.Services.AddElsaApiEndpoints();
Configure<AbpAntiForgeryOptions>(o =>
{
// Exclude Elsa API
o.AutoValidateFilter = t => t.Assembly != typeof(Elsa.Server.Api.Endpoints.WorkflowRegistry.Get).Assembly;
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
app.UseHttpActivities();
app.UseConfiguredEndpoints();
}
}
using Elsa.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
public class ElsaContextFactory : IDesignTimeDbContextFactory<ElsaContext>
{
public ElsaContext CreateDbContext(string[] args)
{
var cfg = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile("appsettings.Development.json", optional: true)
.AddEnvironmentVariables()
.Build();
var options = new DbContextOptionsBuilder<ElsaContext>()
.UseSqlServer(cfg.GetConnectionString("Default"))
.Options;
return new ElsaContext(options);
}
}
Create migrations for Elsa’s DbContext (not your app DbContext):
Apply in ABP way (recommended):
Will the Host act as Elsa Server?
Production readiness status
Microservice note (if applicable)
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.
Do this in your host (the application that will expose Elsa endpoints):
Packages (NuGet)
Configure Elsa EF Core persistence In your Host module’s ConfigureServices:
using Elsa.EntityFrameworkCore.Extensions;
using Elsa.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
context.Services
.AddElsa(elsa =>
{
elsa
.UseEntityFrameworkCorePersistence(ef =>
ef.UseSqlServer(configuration.GetConnectionString("Default")))
.AddHttpActivities()
.AddQuartzTemporalActivities();
});
context.Services.AddElsaApiEndpoints();
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
app.UseHttpActivities();
app.UseConfiguredEndpoints();
}
using Elsa.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
public class ElsaContextFactory : IDesignTimeDbContextFactory<ElsaContext>
{
public ElsaContext CreateDbContext(string[] args)
{
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: false)
.AddEnvironmentVariables()
.Build();
var options = new DbContextOptionsBuilder<ElsaContext>()
.UseSqlServer(config.GetConnectionString("Default"))
.Options;
return new ElsaContext(options);
}
}
Clean bin/obj and ensure the project builds before adding the migration.
Will your Host act as “Elsa Server”?
Production readiness
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 you see “empty migration” with Elsa Pro:
How to add Elsa database schema:
Example (simplified):
// In your Host module
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
context.Services.AddElsa(elsa => elsa
.UseEntityFrameworkPersistence(ef => ef.UseSqlServer(configuration.GetConnectionString("Default")))
.AddHttpActivities()
.AddQuartzTemporalActivities()
);
context.Services.AddElsaApiEndpoints();
}
Commands (run from the Host project folder that references Elsa.Persistence.EntityFramework.*):
Notes:
If a migration still comes out empty, clean bin/obj, ensure the Host builds, and verify that UseEntityFrameworkPersistence is executed in design-time factory or the EF tools can discover ElsaContext.
Applying schema vs. seeding: use your solution’s DbMigrator (preferred) to ensure seeding runs; Package Manager Console Update-Database only applies schema.
Does your Host act as Elsa Server?
Production readiness status
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.
Ensure WebSockets are enabled on the host
Confirm SignalR traffic is not blocked by proxy/load balancer
Check that the blazor.server.js and static assets are being served
Verify the app is truly Blazor Server (not Blazor Web App misconfigured)
If hosted as a sub-application (virtual directory), set the base href
IIS-specific quick checklist
Azure App Service quick checklist
If you can’t click the Login button on your public site specifically:
Code snippets (only if you are behind a proxy/load balancer):
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
// ...
app.UseForwardedHeaders(new ForwardedHeadersOptions
{
ForwardedHeaders = Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedFor
| Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedProto
| Microsoft.AspNetCore.HttpOverrides.ForwardedHeaders.XForwardedHost
});
// ...
app.UseConfiguredEndpoints();
}
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 try these definitive checks/fixes:
A) Ensure real email sender is used in production
public override void ConfigureServices(ServiceConfigurationContext context)
{
#if DEBUG
context.Services.Replace(ServiceDescriptor.Singleton<IEmailSender, NullEmailSender>());
#endif
}
B) Prefer MailKit in production
C) Stop using File.ReadAllTextAsync for templates in production
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<YourProjectDomainModule>();
});
public static class MyEmailTemplates
{
public const string UserCreation = "MyEmailTemplates.UserCreation";
public const string ChangePassword = "MyEmailTemplates.ChangePassword";
}
public class EmailTemplateDefinitionProvider : TemplateDefinitionProvider
{
public override void Define(ITemplateDefinitionContext context)
{
context.Add(new TemplateDefinition(MyEmailTemplates.UserCreation)
.WithVirtualFilePath("/Emailing/Templates/UserCreation.tpl", isInlineLocalized: true));
context.Add(new TemplateDefinition(MyEmailTemplates.ChangePassword)
.WithVirtualFilePath("/Emailing/Templates/ChangePassword.tpl", isInlineLocalized: true));
}
}
private async Task<string> RenderEmailBodyAsync(string templateName, object model)
{
var key = templateName.Equals("UserCreation.tpl", StringComparison.OrdinalIgnoreCase)
? MyEmailTemplates.UserCreation
: MyEmailTemplates.ChangePassword;
return await _templateRenderer.RenderAsync(key, model);
}
D) If you want to keep manual replacements
private readonly IVirtualFileProvider _vfs;
public SendGridEmailNotificationAppServiceBase(..., IVirtualFileProvider vfs, ...)
{
_vfs = vfs;
}
private async Task<string> LoadTemplateFromVfsAsync(string virtualPath)
{
var fi = _vfs.GetFileInfo(virtualPath);
if (!fi.Exists) throw new FileNotFoundException($"Template not found: {virtualPath}");
using var s = fi.CreateReadStream();
using var r = new StreamReader(s);
return await r.ReadToEndAsync();
}
E) Verify environment URLs
F) Quick diagnostic to confirm mail path
await _emailSender.SendAsync("you@domain.com", "Test", "Hello", false);
If this arrives, the SMTP configuration is correct and the problem is template loading; move to using VFS/ITemplateRenderer as above.
If you still want to share logs, please look specifically for:
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.
A) Install and reference the correct Elsa (Pro) integration
In your Host module (the service where Elsa will run):
[DependsOn(
typeof(Volo.Elsa.Abp.AspNetCore.AbpElsaAspNetCoreModule),
typeof(Volo.Elsa.Abp.Identity.AbpElsaIdentityModule),
typeof(Volo.Elsa.Abp.Application.AbpElsaApplicationModule),
typeof(Volo.Elsa.Abp.Application.Contracts.AbpElsaApplicationContractsModule)
)]
public class MyProjectHttpApiHostModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
var configuration = context.Services.GetConfiguration();
var elsaSection = configuration.GetSection("Elsa");
context.Services.AddElsa(elsa => elsa
.UseEntityFrameworkPersistence(ef =>
DbContextOptionsBuilderExtensions.UseSqlServer(
ef, configuration.GetConnectionString("Default")))
.AddHttpActivities(elsaSection.GetSection("Server").Bind)
.AddQuartzTemporalActivities()
.AddJavaScriptActivities()
.AddWorkflowsFrom<Startup>() // optional
);
context.Services.AddElsaApiEndpoints();
Configure<AbpAntiForgeryOptions>(options =>
{
options.AutoValidateFilter = type =>
type.Assembly != typeof(Elsa.Server.Api.Endpoints.WorkflowRegistry.Get).Assembly;
});
context.Services.AddCors(cors => cors.AddDefaultPolicy(builder =>
builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()
.WithExposedHeaders("Content-Disposition")));
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
app.UseCors();
app.UseHttpActivities();
app.UseConfiguredEndpoints();
}
}
Add to appsettings.json:
{
"ConnectionStrings": {
"Default": "Server=...;Database=...;Trusted_Connection=False;User Id=...;Password=...;"
},
"Elsa": {
"Http": {
"BaseUrl": "https://localhost:5001"
}
}
}
B) Ensure you are creating migrations from the project that contains Elsa’s DbContext
C) If you use microservices or an external Auth Server, wire identity consistently
D) Use DbMigrator vs package manager console
E) Verify with the official sample
Quick troubleshooting summary for “empty migration”:
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.
A) Make sure job execution is disabled at ConfigureServices (module-level), not only via appsettings
B) Remove/avoid Redis distributed lock provider registration in environments where Redis isn’t available
If you added a custom IDistributedLockProvider registration (Medallion Redis) anywhere (e.g., your HttpApi.Host, Web, or a shared infrastructure module), guard it with environment checks so it’s not registered locally: public override void ConfigureServices(ServiceConfigurationContext context) { var env = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration();
if (!env.IsDevelopment() || !string.IsNullOrEmpty(configuration["Redis:Configuration"]))
{
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var conn = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
return new RedisDistributedSynchronizationProvider(conn.GetDatabase());
});
}
}
If you don’t explicitly register a Redis provider, ABP will fall back to its default in-memory lock (sufficient for single-instance dev and won’t try to connect to Redis).
C) If you do want Redis but want startup to continue when Redis is temporarily down
D) If another module depends on AbpBackgroundJobs and starts workers
Why your “Option B” might not have worked
Minimal 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.