
How to Use Copilot on ASP.NET Zero Without Inventing Login
How to use Copilot on ASP.NET Zero without inventing login: v15.2 AI skills, tenant filters, and a Tenant B smoke test. Fast code still has to pass your permissions.
Read more →
AI can generate an answer in seconds. Your HTTP request shouldn’t have to wait for it.
When an AI feature takes several seconds to process, putting the entire operation inside an ASP.NET Core request can create a poor user experience and unnecessary pressure on your application.
For an ASP.NET Zero application, there is already a better pattern.
Queue the work as a background job, process the AI operation asynchronously, preserve the tenant and user context, and notify the Angular client when the result is ready.
This guide explains how to build that pattern using ASP.NET Zero background jobs, Hangfire, authorization, multi-tenancy, and SignalR. Last week we covered Copilot on ASP.NET Zero. This week is the production path for a long-running AI action: authorize, queue, restore context, then notify the UI. The ChatGPT-specific sibling is How to Add ChatGPT to ASP.NET Core. The user-facing version of the wait is Why Is My Chatbot So Slow?
A simple AI endpoint often looks like this:
[AbpAuthorize]
public async Task<AiResultDto> ExecuteAsync(AiRequestDto input)
{
return await _aiService.GenerateAsync(input.Prompt);
}
It works.
Until the model takes 10 seconds.
Or 30 seconds.
Or the user sends several requests at the same time.
Now the browser is waiting, the request is still open, and your application is spending resources keeping that HTTP connection alive.
The problem becomes more obvious when AI operations involve more than one model call, tool invocation, document retrieval, or external API.
AI workloads are often better treated as background work than as ordinary CRUD requests.
ABP’s background-job architecture is specifically designed for tasks that should execute asynchronously without forcing users to wait for completion. Hangfire can be used as the background-job provider while keeping the application code independent of the underlying job implementation.
For an AI action, think of the workflow as four stages:
1. Authorize the request
The user calls the Application Service.
[AbpAuthorize] validates that the operation is allowed.
2. Queue the AI task
Instead of calling the model immediately, create a background job containing the information required to process it.
3. Process the job
Hangfire executes the job outside the original HTTP request.
4. Notify the UI
When processing finishes, use ASP.NET Zero SignalR or a tenant-scoped status endpoint to let the Angular application know that the result is ready.
The browser doesn’t need to sit there waiting for the model.
The Application Service should validate the request, authorize the user, and enqueue the job.
It should not become the AI orchestration engine.
[AbpAuthorize]
public async Task<string> StartAiActionAsync(
StartAiActionInput input)
{
var jobId = Guid.NewGuid().ToString();
await _backgroundJobManager.EnqueueAsync(
new ProcessAiActionArgs
{
JobId = jobId,
TenantId = AbpSession.TenantId,
UserId = AbpSession.UserId,
Prompt = input.Prompt
});
return jobId;
}
The important part isn’t the exact implementation.
The architectural boundary is.
The HTTP request starts the work. It does not perform all the work.
This is where AI background jobs become different from a simple queue.
Leaving the HTTP request does not mean your security model disappears.
Your job still needs to know:
For a multi-tenant ASP.NET Zero application, tenant context must remain part of the job’s design.
A useful job argument might look like:
public class ProcessAiActionArgs
{
public string JobId { get; set; }
public int? TenantId { get; set; }
public long UserId { get; set; }
public string Prompt { get; set; }
}
The exact session restoration mechanism depends on your ASP.NET Zero/ABP version and job implementation.
The principle does not change:
Never turn a user-initiated AI job into an anonymous background operation.
The background job can now perform the expensive operation.
public class ProcessAiActionJob
: AsyncBackgroundJob<ProcessAiActionArgs>,
ITransientDependency
{
private readonly IAiService _aiService;
public ProcessAiActionJob(
IAiService aiService)
{
_aiService = aiService;
}
public override async Task ExecuteAsync(
ProcessAiActionArgs args)
{
// Restore the appropriate tenant/user context
// Retrieve authorized data
// Execute AI operation
// Persist the result
// Notify the client
}
}
The job should retrieve data through the application’s normal repository and authorization boundaries.
Do not create a special “AI path” that bypasses your existing security architecture.
This is especially important when AI features use RAG, tools, or agents that can access business data. The broader architecture for that is in Building AI-Native Features in ASP.NET Zero.
ASP.NET Zero Hangfire integration gives your application a mature mechanism for processing background jobs.
Hangfire can persist jobs, execute them outside the HTTP request, and provide retry and scheduling capabilities.
Official ASP.NET Zero docs note that Hangfire NuGet packages are included but disabled by default: the template uses its own background-job system until you enable Hangfire (for example via WebConsts.HangfireDashboardEnabled). That is useful when you run more than one instance of the web app, because Hangfire can execute a job once instead of once per instance. See ASP.NET Zero Hangfire integration.
ABP’s architecture allows the application to use a common background-job abstraction while changing the underlying provider. Current ABP documentation lists Hangfire alongside the default background-job implementation and other integrations such as RabbitMQ and Quartz.
This means your AI service doesn’t need to become tightly coupled to Hangfire-specific APIs.
That’s useful if your infrastructure evolves later. The Hangfire-specific install steps live in ABP’s Hangfire background job manager docs.
Queuing the job solves the HTTP problem.
But users still need feedback.
This is where ASP.NET Zero SignalR becomes useful. SignalR is already configured in the startup template for real-time notifications and chat, so you can use the same stack for AI completion events.
Instead of:
User clicks → browser waits → AI completes → response returns
you can use:
User clicks → job created → response returns → AI processes → SignalR notification → UI updates
For example:
User
↓
Angular
↓
Application Service
↓
Background Job
↓
Hangfire
↓
AI Service
↓
Database
↓
SignalR
↓
Angular
ASP.NET Zero already includes real-time functionality through SignalR and a background-job system with Hangfire integration, so you don’t necessarily need to introduce another infrastructure layer just to implement this pattern.
This is the part developers sometimes overlook.
Moving an AI operation into Hangfire does not remove tenant isolation.
If Tenant A starts an AI document analysis job, the resulting job and its output must remain associated with Tenant A.
Tenant B should not be able to:
The background worker needs the same tenant-aware architecture as the original request.
Moving code to the background does not move it outside your security model.
A particularly dangerous pattern is disabling ABP’s data filters because the background job cannot find the expected records.
For example:
using (CurrentUnitOfWork.DisableFilter(
AbpDataFilters.MayHaveTenant))
{
// ...
}
If you genuinely need cross-tenant access, such as a carefully controlled host-level reporting operation, that should be an explicit architectural decision.
Don’t disable tenant filtering simply because your AI job isn’t retrieving the expected data.
The correct question is:
“Why can’t this job see the data it is supposed to see?”
Not:
“How can I make the filter disappear?”
ABP’s data-filter docs are still the law here. We made the same point for generated CRUD in How to Use ASP.NET Zero Power Tools Without Breaking Multi-Tenancy.
The same architecture becomes even more important when your AI feature evolves from a simple LLM call into an AI agent.
An agent may:
ABP Framework’s current AI integration supports Microsoft’s AI ecosystem, including Microsoft.Extensions.AI, Microsoft Agent Framework, and Semantic Kernel. Current ABP documentation recommends Microsoft Agent Framework for application-level agent scenarios while retaining support for other integrations.
As agent capabilities increase, the background-job architecture becomes more valuable.
The more work an agent can perform, the less appropriate it becomes to treat the entire workflow as a single synchronous HTTP request.
Before shipping an AI action, test the complete workflow.
| Test | Expected Result |
|---|---|
| HTTP request starts AI action | Returns quickly |
| Job created | Job ID is returned |
| Tenant A starts job | Tenant A owns the job |
| Tenant B checks job | No access |
| AI processing fails | Job can retry/fail safely |
| Application restarts | Job remains recoverable |
| Tenant A receives result | Yes |
| Tenant B receives result | No |
| SignalR notification | Tenant-scoped |
| Session restoration fails | AI operation does not continue |
If any of these fail, the AI feature isn’t ready for production.
Not every AI request needs Hangfire.
A very fast operation that reliably completes within the normal request lifecycle may be perfectly suitable for a synchronous API call.
Background jobs become particularly useful when the operation involves:
The goal isn’t to put every AI request into a queue.
The goal is to avoid making the HTTP request responsible for work that doesn’t belong there.
No. Use a background job when the model, tools, or document work would keep the HTTP request open. A fast classification that always finishes inside a normal request can stay synchronous.
No. Enqueue through ABP’s IBackgroundJobManager so the job class stays provider-independent. Hangfire, the default store, RabbitMQ, or Quartz can sit underneath.
At minimum: a correlation/job ID, TenantId, UserId, and the payload needed to run the action. Do not reconstruct those from an empty background session.
Return the job ID immediately, then push completion (or a tenant-scoped status) over ASP.NET Zero SignalR. Don’t leave the browser waiting on the original POST.
No. Job status, stored output, documents, and SignalR notifications must stay tenant-scoped. If Tenant B can read Tenant A, the feature is not ready.
AI makes it easy to add intelligent features to an ASP.NET Zero application.
But production AI isn’t just about calling a model.
It’s about deciding:
Where does the work execute?
Who authorized it?
Which tenant owns it?
What happens if it fails?
How does the UI know when it finishes?
For long-running AI operations, a clean architecture is:
Authorize → Queue → Restore Context → Execute → Persist → Notify
Use ASP.NET Zero background jobs, Hangfire, and SignalR where they fit instead of keeping the browser waiting for the model.
And remember:
The HTTP request should start the AI action. It shouldn’t have to wait for it.
AI integration becomes significantly more complex when agents need access to tenant data, business workflows, permissions, and existing enterprise infrastructure.
A team experienced with ASP.NET Zero development, ABP Framework, AI integration, background jobs, and multi-tenant SaaS architecture can help design the architecture before those concerns become production problems.
Explore our ASP.NET Zero dedicated development team or contact our dedicated development team to discuss your application. For greenfield work, start with Development from Zero.
Sources: ASP.NET Zero, Hangfire integration accessed 2026-09-21; ABP, Background jobs accessed 2026-09-21; ABP, Hangfire background job manager accessed 2026-09-21; ASP.NET Zero, SignalR integration accessed 2026-09-21; ABP, Data filters accessed 2026-09-21.
Get In Touch
Hire ASP.Net Zero Application Developers that will provide the perfect solution to your business issues. Our technical experts will provide you with a free consultation.

How to use Copilot on ASP.NET Zero without inventing login: v15.2 AI skills, tenant filters, and a Tenant B smoke test. Fast code still has to pass your permissions.
Read more →
How to use ASP.NET Zero Power Tools without leaking tenants: what the generator creates, IMustHaveTenant, ABP data filters, and a Tenant B smoke test.
Read more →
How to upgrade ASP.NET Zero is a git merge, not a NuGet click. New vs existing projects, aspnetzero branch, conflict checklist, and what v15 / .NET 10 changed.
Read more →