← Back to Blog

ASP.NET Zero

How to Run AI Actions in ASP.NET Zero with Background Jobs and Hangfire

How to Run AI Actions in ASP.NET Zero with Background Jobs and Hangfire

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?

Contents

Why AI Actions Should Not Block the HTTP Request

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.

The ASP.NET Zero Pattern: Queue → Process → Notify

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.

Step 1: Keep the Application Service Thin

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.

Step 2: Carry TenantId and UserId Into the Job

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:

  • Which tenant initiated the operation?
  • Which user initiated it?
  • Which data can that user access?
  • Which permissions should apply?
  • Where should the result be stored?

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.

Step 3: Process the AI Action in the Background

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.

Step 4: Use Hangfire for Reliable Background Processing

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.

Step 5: Tell Angular When the AI Task Finishes

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.

Multi-Tenancy Still Applies to Background Jobs

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:

  • Read Tenant A’s job status
  • Retrieve Tenant A’s AI result
  • Access Tenant A’s documents
  • Subscribe to Tenant A’s notifications
  • Trigger an operation against Tenant A’s data

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.

Don’t Use DisableFilter as a Shortcut

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.

What About AI Agents?

The same architecture becomes even more important when your AI feature evolves from a simple LLM call into an AI agent.

An agent may:

  • Read database records
  • Search documents
  • Call APIs
  • Create records
  • Trigger workflows
  • Send notifications
  • Execute multiple tools

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.

AI Background Job Smoke Test

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.

When Should You Use Background Jobs?

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:

  • Long-running AI inference
  • Multiple LLM calls
  • RAG document processing
  • Large document analysis
  • AI agent tool calls
  • External API dependencies
  • Batch processing
  • Report generation
  • Retryable operations

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.

Frequently Asked Questions

Should every AI call in ASP.NET Zero use Hangfire?

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.

Do I have to couple my AI service to Hangfire APIs?

No. Enqueue through ABP’s IBackgroundJobManager so the job class stays provider-independent. Hangfire, the default store, RabbitMQ, or Quartz can sit underneath.

What must go into the job args?

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.

How does Angular know the AI task finished?

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.

Can Tenant B see Tenant A’s AI result?

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.

Final Takeaway

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.

Need Help Building AI Features in ASP.NET Zero?

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

Ready to start your ASP.NET Zero project?

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.

More from the Blog