ASP.NET Core  

Building AI-Based Chatbots with ASP.NET Core Backend and Angular Frontend

AI-powered chatbots have become an essential part of modern web applications. They can automate customer support, guide users, and provide personalized recommendations. In this article, we will build a full-stack AI-based chatbot with an Angular frontend and ASP.NET Core backend, integrating with an AI model via API (for example, OpenAI GPT or any other AI service).

We will focus on technical accuracy, clean architecture, scalability, and best practices for production-ready applications.

1. Understanding the Architecture

A chatbot system has three main layers:

  1. Frontend (Angular)

    • Displays chat messages

    • Sends user messages to the backend

    • Shows typing indicators and chatbot responses

  2. Backend (ASP.NET Core Web API)

    • Receives messages from the frontend

    • Sends requests to AI services

    • Stores chat history (optional)

  3. AI Service

    • Handles natural language understanding and generates responses

    • Could be OpenAI GPT API, Microsoft Azure OpenAI, or a custom NLP model

High-Level Flow

User -> Angular Frontend -> ASP.NET Core API -> AI Service
         <- Response <-             <- AI Response

2. Setting Up the ASP.NET Core Backend

Step 1: Create a New ASP.NET Core Web API Project

dotnet new webapi -n ChatbotAPI
cd ChatbotAPI

Step 2: Install Required Packages

For HTTP requests to AI services, install System.Net.Http.Json:

dotnet add package System.Net.Http.Json

Optionally, if you want logging:

dotnet add package Serilog.AspNetCore

Step 3: Define Chat Message Model

Create Models/ChatMessage.cs:

public class ChatMessage
{
    public string User { get; set; } = "user";  // "user" or "bot"
    public string Message { get; set; } = string.Empty;
    public DateTime Timestamp { get; set; } = DateTime.UtcNow;
}

Step 4: AI Service Integration

Create a service to handle AI requests:

using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;

public class AIService
{
    private readonly HttpClient _httpClient;

    public AIService(HttpClient httpClient)
    {
        _httpClient = httpClient;
    }

    public async Task<string> GetResponseAsync(string prompt)
    {
        // Example: calling OpenAI GPT API
        var request = new
        {
            model = "gpt-3.5-turbo",
            messages = new[] { new { role = "user", content = prompt } }
        };

        var response = await _httpClient.PostAsJsonAsync("https://api.openai.com/v1/chat/completions", request);
        response.EnsureSuccessStatusCode();

        var result = await response.Content.ReadFromJsonAsync<dynamic>();
        return result?.choices[0].message.content ?? "Sorry, I did not understand.";
    }
}

In production, keep your API keys in appsettings.json or Azure Key Vault, and never commit secrets.

Step 5: Create Chat Controller

using Microsoft.AspNetCore.Mvc;

[ApiController]
[Route("api/[controller]")]
public class ChatController : ControllerBase
{
    private readonly AIService _aiService;

    public ChatController(AIService aiService)
    {
        _aiService = aiService;
    }

    [HttpPost]
    public async Task<IActionResult> Post([FromBody] ChatMessage message)
    {
        if (string.IsNullOrWhiteSpace(message.Message))
            return BadRequest("Message cannot be empty");

        var botResponse = await _aiService.GetResponseAsync(message.Message);

        var responseMessage = new ChatMessage
        {
            User = "bot",
            Message = botResponse
        };

        return Ok(responseMessage);
    }
}

Step 6: Register AIService in Program.cs

builder.Services.AddHttpClient<AIService>(client =>
{
    client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_API_KEY");
});

This sets up a minimal but production-ready backend API for chatbot messages.

3. Setting Up Angular Frontend

Step 1: Create Angular Project

ng new chatbot-app --routing --style=scss
cd chatbot-app
ng serve

Step 2: Create Chat Models

src/app/models/chat-message.model.ts:

export interface ChatMessage {
  user: 'user' | 'bot';
  message: string;
  timestamp?: string;
}

Step 3: Chat Service

src/app/services/chat.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { ChatMessage } from '../models/chat-message.model';

@Injectable({
  providedIn: 'root'
})
export class ChatService {

  private apiUrl = 'https://localhost:5001/api/chat'; // ASP.NET Core URL

  constructor(private http: HttpClient) { }

  sendMessage(message: string): Observable<ChatMessage> {
    return this.http.post<ChatMessage>(this.apiUrl, { user: 'user', message });
  }
}

Step 4: Chat Component

src/app/components/chat/chat.component.ts:

import { Component } from '@angular/core';
import { ChatService } from '../../services/chat.service';
import { ChatMessage } from '../../models/chat-message.model';

@Component({
  selector: 'app-chat',
  templateUrl: './chat.component.html',
  styleUrls: ['./chat.component.scss']
})
export class ChatComponent {
  messages: ChatMessage[] = [];
  userInput: string = '';
  loading: boolean = false;

  constructor(private chatService: ChatService) { }

  sendMessage() {
    if (!this.userInput.trim()) return;

    const userMessage: ChatMessage = {
      user: 'user',
      message: this.userInput,
      timestamp: new Date().toISOString()
    };

    this.messages.push(userMessage);
    this.loading = true;

    this.chatService.sendMessage(this.userInput).subscribe({
      next: (botMessage) => {
        this.messages.push(botMessage);
        this.loading = false;
      },
      error: () => {
        this.messages.push({ user: 'bot', message: 'Sorry, something went wrong.' });
        this.loading = false;
      }
    });

    this.userInput = '';
  }
}

Step 5: Chat Component Template

chat.component.html:

<div class="chat-container">
  <div class="messages">
    <div *ngFor="let msg of messages" [ngClass]="msg.user">
      <strong>{{ msg.user }}:</strong> {{ msg.message }}
    </div>
    <div *ngIf="loading" class="bot-loading">Bot is typing...</div>
  </div>

  <div class="input-container">
    <input [(ngModel)]="userInput" placeholder="Type a message" (keyup.enter)="sendMessage()"/>
    <button (click)="sendMessage()">Send</button>
  </div>
</div>

Step 6: Add Styling

chat.component.scss:

.chat-container {
  display: flex;
  flex-direction: column;
  height: 500px;
  border: 1px solid #ccc;
  padding: 10px;
}

.messages {
  flex: 1;
  overflow-y: auto;
  margin-bottom: 10px;

  .user { text-align: right; color: blue; }
  .bot { text-align: left; color: green; }
  .bot-loading { font-style: italic; color: gray; }
}

.input-container {
  display: flex;

  input {
    flex: 1;
    padding: 5px;
  }

  button {
    margin-left: 5px;
  }
}

4. Handling Best Practices

  1. Security: Never expose API keys in Angular. Keep them in ASP.NET Core backend.

  2. Async Handling: Use Observables and BehaviorSubject for state management if chatbot UI becomes complex.

  3. Error Handling: Always handle API errors gracefully.

  4. Persistence: Store chat history in a database for returning users.

  5. Scalability: Backend can use queue-based systems if AI API requests increase.

  6. Typing Indicators: Use loading flags for better UX.

  7. Rate Limiting: Protect backend to avoid hitting AI API limits.

  8. Deployment: Use HTTPS in production for secure communication.

5. Optional Enhancements

  • WebSocket Integration: For real-time chat updates instead of polling.

  • AI Fine-Tuning: Provide context for better responses.

  • Widget-Based Chat: Embed chatbot as a draggable widget on dashboards.

  • Multi-Language Support: Localize frontend and provide multi-language AI prompts.

  • Bot Analytics: Track common questions, failed responses, and usage stats.

6. Folder Structure

chatbot-app/
  src/app/
    components/
      chat/
        chat.component.ts
        chat.component.html
        chat.component.scss
    models/
      chat-message.model.ts
    services/
      chat.service.ts
ChatbotAPI/
  Controllers/
    ChatController.cs
  Models/
    ChatMessage.cs
  Services/
    AIService.cs
Program.cs
appsettings.json

7. Conclusion

By combining Angular frontend and ASP.NET Core backend, we can build a full-featured AI chatbot that is scalable, production-ready, and easy to extend.

Key takeaways

  • Use dynamic state management for chat messages.

  • Keep AI API calls backend-only for security.

  • Implement error handling, persistence, and UX improvements for production readiness.

  • Optional enhancements like WebSocket, analytics, and multi-language support make the chatbot more professional.

With this architecture, you can now integrate AI chatbots in enterprise dashboards, SaaS products, customer support portals, or learning platforms efficiently.