Sunday, April 12, 2026

Integrating OpenAI / ChatGPT in ASP.NET Core Web API

 This guide shows how to build a production-ready AI API using ASP.NET Core with: Clean Architecture, streaming responses, database storage, and secure configuration.


πŸ—️ Architecture Overview


API Layer → Application Layer → Infrastructure Layer → Database
  • API: Controllers
  • Application: Business logic
  • Infrastructure: OpenAI + DB
  • Database: Chat history

1. Secure Configuration (Environment Variable)


builder.Configuration.AddEnvironmentVariables();

var apiKey = builder.Configuration["OPENAI_API_KEY"];

⚠️ Never store API keys in appsettings.json in production.


2. Database Model (Chat History)


public class ChatMessage
{
    public int Id { get; set; }
    public string UserMessage { get; set; }
    public string BotResponse { get; set; }
    public DateTime CreatedAt { get; set; }
}

3. DbContext (EF Core)


public class AppDbContext : DbContext
{
    public DbSet<ChatMessage> ChatMessages { get; set; }

    public AppDbContext(DbContextOptions<AppDbContext> options)
        : base(options) { }
}

4. OpenAI Service (Production Ready)


public class OpenAIService
{
    private readonly HttpClient _httpClient;
    private readonly IConfiguration _config;

    public OpenAIService(HttpClient httpClient, IConfiguration config)
    {
        _httpClient = httpClient;
        _config = config;
    }

    public async Task<string> GetResponseAsync(string prompt)
    {
        var request = new
        {
            model = "gpt-4o-mini",
            messages = new[]
            {
                new { role = "user", content = prompt }
            }
        };

        _httpClient.DefaultRequestHeaders.Authorization =
            new AuthenticationHeaderValue("Bearer", _config["OPENAI_API_KEY"]);

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

        if (!response.IsSuccessStatusCode)
            throw new Exception("OpenAI API error");

        var result = await response.Content.ReadFromJsonAsync<dynamic>();
        return result.choices[0].message.content;
    }
}

5. Streaming Response (Real-Time)


[HttpPost("stream")]
public async Task Stream([FromBody] string prompt)
{
    Response.ContentType = "text/plain";

    var response = await _service.GetResponseAsync(prompt);

    foreach (var word in response.Split(" "))
    {
        await Response.WriteAsync(word + " ");
        await Response.Body.FlushAsync();
        await Task.Delay(50);
    }
}

✅ Simulates real-time typing (like ChatGPT)


6. Save Chat History


public async Task SaveChat(string userMsg, string botMsg)
{
    var chat = new ChatMessage
    {
        UserMessage = userMsg,
        BotResponse = botMsg,
        CreatedAt = DateTime.UtcNow
    };

    _context.ChatMessages.Add(chat);
    await _context.SaveChangesAsync();
}

7. Controller (Final Version)


[ApiController]
[Route("api/chat")]
public class ChatController : ControllerBase
{
    private readonly OpenAIService _service;
    private readonly AppDbContext _context;

    public ChatController(OpenAIService service, AppDbContext context)
    {
        _service = service;
        _context = context;
    }

    [HttpPost]
    public async Task<IActionResult> Ask(string prompt)
    {
        var response = await _service.GetResponseAsync(prompt);

        await _context.ChatMessages.AddAsync(new ChatMessage
        {
            UserMessage = prompt,
            BotResponse = response,
            CreatedAt = DateTime.UtcNow
        });

        await _context.SaveChangesAsync();

        return Ok(response);
    }
}

8. Logging (Serilog)


builder.Host.UseSerilog((ctx, lc) =>
    lc.WriteTo.Console()
);

9. Rate Limiting


builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("api", opt =>
    {
        opt.PermitLimit = 50;
        opt.Window = TimeSpan.FromMinutes(1);
    });
});

πŸ” Enterprise Best Practices

  • Use Redis for caching responses
  • Store chat history per user
  • Use JWT authentication
  • Add retry policy (Polly)
  • Use Azure Key Vault
  • Implement circuit breaker

πŸ’‘ Real Product Ideas

  • AI Customer Support API
  • WhatsApp Auto Reply Bot
  • AI Code Review Tool
  • Content Generator SaaS

πŸ“Œ Conclusion

You now have a complete enterprise-grade AI API using ASP.NET Core. This can be extended into a scalable SaaS product.

How to Improve API Performance in ASP.NET Core

Performance is critical for modern APIs. A slow API leads to poor user experience and scalability issues. In this article, we will explore proven techniques to improve API performance in ASP.NET Core with real examples.


1. Use Asynchronous Programming

Always use async/await for I/O operations to avoid blocking threads.


[HttpGet]
public async Task GetUsers()
{
    var users = await _context.Users.ToListAsync();
    return Ok(users);
}

Benefit: Improves scalability and thread utilization.


2. Enable Response Caching

Caching reduces repeated processing and database calls.


[HttpGet]
[ResponseCache(Duration = 60)]
public IActionResult GetData()
{
    return Ok("Cached Data");
}

Also enable in Program.cs:


builder.Services.AddResponseCaching();

app.UseResponseCaching();


3. Use In-Memory Caching


public class UserService
{
    private readonly IMemoryCache _cache;

    public UserService(IMemoryCache cache)
    {
        _cache = cache;
    }

    public async Task> GetUsers()
    {
        if (!_cache.TryGetValue("users", out List users))
        {
            users = await _context.Users.ToListAsync();

            _cache.Set("users", users, TimeSpan.FromMinutes(5));
        }

        return users;
    }
}


4. Optimize Database Queries

Use projection instead of fetching full entities.


var users = await _context.Users
    .Select(u => new { u.Id, u.Name })
    .ToListAsync();

Use AsNoTracking() for read-only queries:


var users = await _context.Users
    .AsNoTracking()
    .ToListAsync();


5. Use Pagination


[HttpGet]
public async Task GetUsers(int page = 1, int pageSize = 10)
{
    var users = await _context.Users
        .Skip((page - 1) * pageSize)
        .Take(pageSize)
        .ToListAsync();

    return Ok(users);
}


6. Enable Compression

Reduces response size.


builder.Services.AddResponseCompression();

app.UseResponseCompression();


7. Use Minimal APIs (Faster Execution)


app.MapGet("/users", async (AppDbContext db) =>
{
    return await db.Users.ToListAsync();
});


8. Avoid Blocking Calls

❌ Bad Practice:

var data = _service.GetData().Result;

✅ Good Practice:

var data = await _service.GetData();

9. Use Connection Pooling

Configured automatically in EF Core, but ensure proper DB connection string usage.


"ConnectionStrings": {
  "DefaultConnection": "Server=.;Database=TestDb;Trusted_Connection=True;Pooling=true;"
}


10. Use Logging & Monitoring

Use tools like Application Insights or Serilog.


builder.Logging.ClearProviders();
builder.Logging.AddConsole();


11. Use Rate Limiting


builder.Services.AddRateLimiter(options =>
{
    options.AddFixedWindowLimiter("fixed", opt =>
    {
        opt.PermitLimit = 100;
        opt.Window = TimeSpan.FromMinutes(1);
    });
});

app.UseRateLimiter();


12. Use Background Tasks for Heavy Work

Offload heavy tasks using background services.


public class BackgroundJob : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // Background work
            await Task.Delay(1000);
        }
    }
}


πŸ“Œ Conclusion

Improving API performance in ASP.NET Core requires a combination of best practices:

  • Use async programming
  • Apply caching strategies
  • Optimize database queries
  • Enable compression
  • Avoid unnecessary data processing

By applying these techniques, you can significantly improve your API speed, scalability, and user experience.

Friday, May 12, 2023

Opps Part 1 : Abstraction

  Abstraction in C# is a fundamental concept of object-oriented programming (OOP) that allows developers to create complex systems by breaking them down into simpler and more manageable parts. Abstraction enables the developer to hide the complexities of the system by creating abstract classes, interfaces, and methods, and exposing only the necessary functionalities to the users.

 using System;  
 abstract class Animal  
 {  
   public abstract void MakeSound();  
 }  
 class Dog : Animal  
 {  
   public override void MakeSound()  
   {  
     Console.WriteLine("Woof!");  
   }  
 }  
 class Cat : Animal  
 {  
   public override void MakeSound()  
   {  
     Console.WriteLine("Meow!");  
   }  
 }  
 class Program  
 {  
   static void Main(string[] args)  
   {  
     Animal myDog = new Dog();  
     Animal myCat = new Cat();  
     myDog.MakeSound(); // Output: Woof!  
     myCat.MakeSound(); // Output: Meow!  
   }  
 }                              

In this example, we have an abstract class called Animal that contains an abstract method called MakeSound(). The Animal class cannot be instantiated, and any class that derives from it must implement the MakeSound() method.

We then create two classes, Dog and Cat, that inherit from the Animal class and implement the MakeSound() method with their own unique sounds.

Finally, in the Main method, we create objects of the Dog and Cat classes and call their MakeSound() methods, which outputs "Woof!" and "Meow!" respectively.

This is an example of abstraction because we are abstracting away the implementation details of the Animal class, and only exposing the necessary functionality through the MakeSound() method. This allows us to create different types of animals with their own unique sounds, without having to worry about the underlying implementation details.


Abstract Base Class points

There are some important points about Abstract Base Class.

  1. An Abstract Base class cannot be instantiated; it means the object of that class cannot be created.
  2. The class having the abstract keyword with some of its methods (not all) is known as an Abstract Base Class.
  3. The class having the Abstract keyword with all its methods is a pure Abstract Base Class.
  4. The method of the abstract class that has no implementation is known as "operation". It can be defined as an abstract void method ();
  5. An abstract class holds the methods, but the actual implementation is made in the derived class.

Opps part 1 : What is Inheritance?

 Inheritance is a concept in object-oriented programming (OOP) that allows a class (called the "child" or "derived" class) to inherit properties and methods from another class (called the "parent" or "base" class).

Inheritance promotes code reuse and allows developers to create new classes that are similar to existing classes, but with additional or modified functionality. The child class inherits all the public and protected properties and methods of the parent class, and can also add its own properties and methods.

For example, consider a class called "Animal" that has properties and methods for common attributes of all animals, such as "name", "age", and "eat()". A child class called "Cat" could inherit from the "Animal" class and add its own properties and methods, such as "purr()" or "scratch()". The "Cat" class can use the properties and methods of the "Animal" class, without having to rewrite them.

Inheritance is often used in software development to create a hierarchy of related classes that share common properties and behaviors, while also allowing for specialization and customization of each class.

Single Inheritance in C#

// Base class
class Animal
{
public void Eat()
{
Console.WriteLine("Animal is eating.");
}
}
// Derived class

class Dog : Animal
{
public void Bark()
{
Console.WriteLine("Dog is barking.");
}
}
// Example usage

class Program
{
static void Main(string[] args)
{
// Create an instance of the Dog class
Dog myDog = new Dog();
// Call methods from the Dog class

myDog.Bark();
// Call inherited method from the Animal class

myDog.Eat();
}
}

MultiLevel Inheritance in C#


// Base class class Animal { public void Eat() { Console.WriteLine("Animal is eating."); } } // Derived class class Dog : Animal { public void Bark() { Console.WriteLine("Dog is barking."); } } // Derived class class Bulldog : Dog { public void Guard() { Console.WriteLine("Bulldog is guarding."); } } // Example usage class Program { static void Main(string[] args) { // Create an instance of the Bulldog class Bulldog myBulldog = new Bulldog(); // Call methods from the Bulldog class myBulldog.Bark(); myBulldog.Guard(); // Call inherited method from the Dog class myBulldog.Eat(); } }

Hierarchical Inheritance in C#


// Base class class Animal { public void Eat() { Console.WriteLine("Animal is eating."); } } // Derived class class Dog : Animal { public void Bark() { Console.WriteLine("Dog is barking."); } } // Derived class class Cat : Animal { public void Meow() { Console.WriteLine("Cat is meowing."); } } class Program { static void Main(string[] args) { Dog myDog = new Dog(); Cat myCat = new Cat(); myDog.Bark(); myCat.Meow(); myDog.Eat(); myCat.Eat(); } }

Multiple Inheritance in C#

C# does not support multiple Inheritance through classes; a class cannot inherit from more than one base class at the same time.

Note. C# does support multiple inheritances through interfaces.

interface IShape { void Draw(); } interface IColor { void SetColor(string color); } class Square : IShape, IColor { private string color; public void Draw() { Console.WriteLine("Drawing square."); } public void SetColor(string color) { this.color = color; } public void PrintColor() { Console.WriteLine("Color of square is: " + color); } } class Program { static void Main(string[] args) { Square square = new Square(); square.Draw(); square.SetColor("Blue"); square.PrintColor(); } }

 

Integrating OpenAI / ChatGPT in ASP.NET Core Web API

 This guide shows how to build a production-ready AI API using ASP.NET Core with: Clean Architecture, streaming responses, database storage,...