<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Asp.Net Core &#8211; Bits of .NET</title>
	<atom:link href="http://blog.ercanopak.com/category/asp-net-core/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ercanopak.com</link>
	<description>Daily micro-tips for C#, SQL, performance, and scalable backend engineering.</description>
	<lastBuildDate>Mon, 30 Mar 2026 17:51:40 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>http://blog.ercanopak.com/wp-content/uploads/2018/06/cropped-EO_LOGO_32-32x32.png</url>
	<title>Asp.Net Core &#8211; Bits of .NET</title>
	<link>http://blog.ercanopak.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>.NET Core: Use Background Services for Long-Running Tasks</title>
		<link>http://blog.ercanopak.com/net-core-use-background-services-for-long-running-tasks/</link>
					<comments>http://blog.ercanopak.com/net-core-use-background-services-for-long-running-tasks/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 17:51:40 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[.NET Tips]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[background jobs]]></category>
		<category><![CDATA[Background Services]]></category>
		<category><![CDATA[Hosted Services]]></category>
		<category><![CDATA[IHostedService]]></category>
		<category><![CDATA[Long Running Tasks]]></category>
		<category><![CDATA[Scheduled Tasks]]></category>
		<category><![CDATA[Worker Service]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-use-background-services-for-long-running-tasks/</guid>

					<description><![CDATA[⏰ Tasks That Run Forever Need to process queue every minute? Send emails in background? Background Services run continuously alongside your ASP.NET app. Perfect for scheduled tasks, workers. Create Background Service public class EmailProcessorService : BackgroundService { private readonly ILogger _logger; private readonly IServiceProvider _serviceProvider; public EmailProcessorService( ILogger logger, IServiceProvider serviceProvider) { _logger = logger; [&#8230;]]]></description>
										<content:encoded><![CDATA[<div style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; padding: 50px 40px; border-radius: 16px; margin: 40px 0; box-shadow: 0 20px 60px rgba(0,0,0,0.3);">
<h2 style="margin: 0 0 20px 0; font-size: 2.8em; font-weight: 800; line-height: 1.2;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/23f0.png" alt="⏰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Tasks That Run Forever</h2>
<p style="font-size: 1.4em; line-height: 1.8; margin: 0; opacity: 0.95;">Need to process queue every minute? Send emails in background? <strong>Background Services</strong> run continuously alongside your ASP.NET app. Perfect for scheduled tasks, workers.</p>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #f5576c; padding-left: 20px;">Create Background Service</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
public class EmailProcessorService : BackgroundService
{
    private readonly ILogger<EmailProcessorService> _logger;
    private readonly IServiceProvider _serviceProvider;

    public EmailProcessorService(
        ILogger<EmailProcessorService> logger,
        IServiceProvider serviceProvider)
    {
        _logger = logger;
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Email Processor Service started");

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // Create scope for scoped services
                using var scope = _serviceProvider.CreateScope();
                var emailService = scope.ServiceProvider.GetRequiredService<IEmailService>();

                // Process pending emails
                await emailService.ProcessPendingEmailsAsync();

                _logger.LogInformation("Processed emails at {Time}", DateTime.UtcNow);

                // Wait 1 minute before next run
                await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing emails");
                await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
            }
        }

        _logger.LogInformation("Email Processor Service stopped");
    }
}

// Register in Program.cs
builder.Services.AddHostedService<EmailProcessorService>();
</pre>
<div style="background: #f8f9fa; padding: 40px; border-radius: 12px; margin: 40px 0; border: 2px solid #f093fb;">
<h4 style="color: #f5576c; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Timed Background Service</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
public class CleanupService : BackgroundService
{
    private readonly ILogger<CleanupService> _logger;
    private readonly IServiceProvider _serviceProvider;
    private Timer? _timer;

    public CleanupService(
        ILogger<CleanupService> logger,
        IServiceProvider serviceProvider)
    {
        _logger = logger;
        _serviceProvider = serviceProvider;
    }

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Cleanup Service started");

        // Run every hour
        _timer = new Timer(
            DoWork,
            null,
            TimeSpan.Zero,  // Start immediately
            TimeSpan.FromHours(1));  // Run every hour

        return Task.CompletedTask;
    }

    private async void DoWork(object? state)
    {
        _logger.LogInformation("Cleanup running at {Time}", DateTime.UtcNow);

        try
        {
            using var scope = _serviceProvider.CreateScope();
            var dbContext = scope.ServiceProvider.GetRequiredService<AppDbContext>();

            // Delete old records
            var cutoffDate = DateTime.UtcNow.AddDays(-30);
            var oldRecords = await dbContext.Logs
                .Where(l => l.CreatedAt < cutoffDate)
                .ToListAsync();

            dbContext.Logs.RemoveRange(oldRecords);
            await dbContext.SaveChangesAsync();

            _logger.LogInformation("Deleted {Count} old records", oldRecords.Count);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "Error during cleanup");
        }
    }

    public override Task StopAsync(CancellationToken cancellationToken)
    {
        _timer?.Change(Timeout.Infinite, 0);
        _logger.LogInformation("Cleanup Service stopped");
        return base.StopAsync(cancellationToken);
    }

    public override void Dispose()
    {
        _timer?.Dispose();
        base.Dispose();
    }
}
</pre>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #667eea; padding-left: 20px;">Queue Processing Service</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
public class OrderProcessingService : BackgroundService
{
    private readonly ILogger<OrderProcessingService> _logger;
    private readonly IServiceProvider _serviceProvider;

    public OrderProcessingService(
        ILogger<OrderProcessingService> logger,
        IServiceProvider serviceProvider)
    {
        _logger = logger;
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                using var scope = _serviceProvider.CreateScope();
                var orderQueue = scope.ServiceProvider.GetRequiredService<IOrderQueue>();
                var orderService = scope.ServiceProvider.GetRequiredService<IOrderService>();

                // Dequeue and process orders
                var order = await orderQueue.DequeueAsync(stoppingToken);

                if (order != null)
                {
                    _logger.LogInformation("Processing order {OrderId}", order.Id);

                    await orderService.ProcessAsync(order);
                    await orderQueue.CompleteAsync(order.Id);

                    _logger.LogInformation("Order {OrderId} processed", order.Id);
                }
                else
                {
                    // No orders in queue, wait a bit
                    await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
                }
            }
            catch (OperationCanceledException)
            {
                // Expected when stopping
                break;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing order");
                await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
            }
        }
    }
}
</pre>
<div style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); color: white; padding: 35px; border-radius: 12px; margin: 40px 0;">
<h4 style="margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4ca.png" alt="📊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Health Check Integration</h4>
<pre style="background: rgba(0,0,0,0.3); color: #fff; padding: 25px; border-radius: 8px; font-size: 1.05em; line-height: 1.8;">
public class MonitoringService : BackgroundService
{
    private readonly ILogger<MonitoringService> _logger;
    private DateTime _lastRunTime = DateTime.MinValue;
    public bool IsHealthy { get; private set; } = true;

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // Do monitoring work
                await MonitorSystemAsync();

                _lastRunTime = DateTime.UtcNow;
                IsHealthy = true;

                await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Monitoring failed");
                IsHealthy = false;
            }
        }
    }

    private async Task MonitorSystemAsync()
    {
        // Check system health
        _logger.LogInformation("System healthy at {Time}", DateTime.UtcNow);
    }
}

// Health check
public class BackgroundServiceHealthCheck : IHealthCheck
{
    private readonly MonitoringService _monitoringService;

    public BackgroundServiceHealthCheck(MonitoringService monitoringService)
    {
        _monitoringService = monitoringService;
    }

    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        if (_monitoringService.IsHealthy)
        {
            return Task.FromResult(HealthCheckResult.Healthy("Monitoring service running"));
        }

        return Task.FromResult(HealthCheckResult.Unhealthy("Monitoring service failed"));
    }
}

// Register
builder.Services.AddSingleton<MonitoringService>();
builder.Services.AddHostedService(sp => sp.GetRequiredService<MonitoringService>());
builder.Services.AddHealthChecks()
    .AddCheck<BackgroundServiceHealthCheck>("monitoring-service");
</pre>
</p></div>
<div style="background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%); padding: 35px; border-radius: 12px; margin: 40px 0; border-left: 5px solid #28a745;">
<h4 style="color: #155724; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Common Use Cases</h4>
<ul style="color: #155724; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Email queue processing:</strong> Send emails asynchronously</li>
<li><strong>Data cleanup:</strong> Delete old logs, cache entries</li>
<li><strong>Report generation:</strong> Generate daily/weekly reports</li>
<li><strong>Cache warming:</strong> Preload cache on schedule</li>
<li><strong>Health monitoring:</strong> Check external service health</li>
<li><strong>Batch processing:</strong> Process large datasets in background</li>
</ul></div>
<div style="background: linear-gradient(135deg, #fff3cd 0%, #ffe69c 100%); border-left: 5px solid #ffc107; padding: 35px; margin: 50px 0; border-radius: 12px;">
<h4 style="color: #856404; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Best Practices</h4>
<ul style="color: #856404; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Use IServiceProvider:</strong> Create scopes for scoped services</li>
<li><strong>Handle CancellationToken:</strong> Graceful shutdown support</li>
<li><strong>Add error handling:</strong> Don't let exceptions stop service</li>
<li><strong>Log everything:</strong> Track service lifecycle and errors</li>
<li><strong>Use delays, not while(true):</strong> Avoid CPU spinning</li>
<li><strong>Dispose resources:</strong> Override Dispose() when needed</li>
</ul></div>
<blockquote style="background: linear-gradient(to right, #fce4ec, #f8bbd0); border-left: 6px solid #e91e63; padding: 40px; margin: 50px 0; border-radius: 12px;">
<p style="font-size: 1.5em; line-height: 1.9; margin: 0; color: #880e4f; font-style: italic; font-weight: 500;">"Needed to process 100k+ emails daily. Created BackgroundService with queue. Runs 24/7, processes emails in batches. Zero downtime. Easier than setting up separate worker service."</p>
<footer style="margin-top: 20px; color: #ad1457; font-size: 1.15em; font-weight: 600;">— Backend Engineer</footer>
</blockquote>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-use-background-services-for-long-running-tasks/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET Core: Use Minimal APIs for Lightweight HTTP Services</title>
		<link>http://blog.ercanopak.com/net-core-use-minimal-apis-for-lightweight-http-services/</link>
					<comments>http://blog.ercanopak.com/net-core-use-minimal-apis-for-lightweight-http-services/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Mon, 30 Mar 2026 17:51:34 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.NET 6]]></category>
		<category><![CDATA[.NET 7]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[C# Tips]]></category>
		<category><![CDATA[microservices]]></category>
		<category><![CDATA[Minimal APIs]]></category>
		<category><![CDATA[Modern .NET]]></category>
		<category><![CDATA[REST API]]></category>
		<category><![CDATA[Web API]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-use-minimal-apis-for-lightweight-http-services/</guid>

					<description><![CDATA[🚀 APIs in 10 Lines of Code MVC Controllers for simple API? Overkill. Minimal APIs (.NET 6+) create HTTP endpoints with minimal ceremony. Perfect for microservices, simple APIs. Traditional Controller vs Minimal API // ❌ Traditional Controller (verbose) [ApiController] [Route("api/[controller]")] public class UsersController : ControllerBase { private readonly IUserService _userService; public UsersController(IUserService userService) { _userService [&#8230;]]]></description>
										<content:encoded><![CDATA[<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 50px 40px; border-radius: 16px; margin: 40px 0; box-shadow: 0 20px 60px rgba(0,0,0,0.3);">
<h2 style="margin: 0 0 20px 0; font-size: 2.8em; font-weight: 800; line-height: 1.2;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /> APIs in 10 Lines of Code</h2>
<p style="font-size: 1.4em; line-height: 1.8; margin: 0; opacity: 0.95;">MVC Controllers for simple API? Overkill. <strong>Minimal APIs</strong> (.NET 6+) create HTTP endpoints with minimal ceremony. Perfect for microservices, simple APIs.</p>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #764ba2; padding-left: 20px;">Traditional Controller vs Minimal API</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/274c.png" alt="❌" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Traditional Controller (verbose)
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    private readonly IUserService _userService;
    
    public UsersController(IUserService userService)
    {
        _userService = userService;
    }
    
    [HttpGet]
    public async Task<ActionResult<List<User>>> GetUsers()
    {
        var users = await _userService.GetAllAsync();
        return Ok(users);
    }
    
    [HttpGet("{id}")]
    public async Task<ActionResult<User>> GetUser(int id)
    {
        var user = await _userService.GetByIdAsync(id);
        if (user == null) return NotFound();
        return Ok(user);
    }
    
    [HttpPost]
    public async Task<ActionResult<User>> CreateUser(User user)
    {
        var created = await _userService.CreateAsync(user);
        return CreatedAtAction(nameof(GetUser), new { id = created.Id }, created);
    }
}

// Many files, boilerplate code, ceremony
</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Minimal API (concise!)
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IUserService, UserService>();

var app = builder.Build();

app.MapGet("/api/users", async (IUserService service) => 
    await service.GetAllAsync());

app.MapGet("/api/users/{id}", async (int id, IUserService service) =>
{
    var user = await service.GetByIdAsync(id);
    return user is not null ? Results.Ok(user) : Results.NotFound();
});

app.MapPost("/api/users", async (User user, IUserService service) =>
{
    var created = await service.CreateAsync(user);
    return Results.Created($"/api/users/{created.Id}", created);
});

app.Run();

// Everything in Program.cs, minimal code!
</pre>
<div style="background: #f8f9fa; padding: 40px; border-radius: 12px; margin: 40px 0; border: 2px solid #667eea;">
<h4 style="color: #667eea; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Complete CRUD Example</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
var builder = WebApplication.CreateBuilder(args);

// Add services
builder.Services.AddDbContext<AppDbContext>();
builder.Services.AddScoped<IUserRepository, UserRepository>();

var app = builder.Build();

// GET all users
app.MapGet("/api/users", async (IUserRepository repo) =>
{
    var users = await repo.GetAllAsync();
    return Results.Ok(users);
})
.WithName("GetUsers")
.Produces<List<User>>(200);

// GET user by ID
app.MapGet("/api/users/{id:int}", async (int id, IUserRepository repo) =>
{
    var user = await repo.GetByIdAsync(id);
    return user is not null 
        ? Results.Ok(user) 
        : Results.NotFound(new { message = "User not found" });
})
.WithName("GetUser")
.Produces<User>(200)
.Produces(404);

// POST create user
app.MapPost("/api/users", async (User user, IUserRepository repo) =>
{
    if (string.IsNullOrWhiteSpace(user.Name))
        return Results.BadRequest(new { message = "Name is required" });
    
    var created = await repo.CreateAsync(user);
    return Results.CreatedAtRoute("GetUser", new { id = created.Id }, created);
})
.Accepts<User>("application/json")
.Produces<User>(201)
.Produces(400);

// PUT update user
app.MapPut("/api/users/{id:int}", async (int id, User user, IUserRepository repo) =>
{
    var existing = await repo.GetByIdAsync(id);
    if (existing is null)
        return Results.NotFound();
    
    user.Id = id;
    await repo.UpdateAsync(user);
    return Results.NoContent();
})
.Produces(204)
.Produces(404);

// DELETE user
app.MapDelete("/api/users/{id:int}", async (int id, IUserRepository repo) =>
{
    var deleted = await repo.DeleteAsync(id);
    return deleted 
        ? Results.NoContent() 
        : Results.NotFound();
})
.Produces(204)
.Produces(404);

app.Run();
</pre>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #f39c12; padding-left: 20px;">Dependency Injection</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// Services automatically injected from DI
app.MapGet("/api/products", async (
    IProductService productService,  // Injected
    ILogger<Program> logger,          // Injected
    HttpContext context) =>           // Also available
{
    logger.LogInformation("Getting products for user {User}", context.User.Identity?.Name);
    return await productService.GetAllAsync();
});

// Multiple services
app.MapPost("/api/orders", async (
    Order order,
    IOrderService orderService,
    IInventoryService inventoryService,
    IEmailService emailService) =>
{
    var created = await orderService.CreateAsync(order);
    await inventoryService.UpdateStockAsync(order.Items);
    await emailService.SendOrderConfirmationAsync(created);
    return Results.Created($"/api/orders/{created.Id}", created);
});
</pre>
<div style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); color: white; padding: 35px; border-radius: 12px; margin: 40px 0;">
<h4 style="margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f510.png" alt="🔐" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Authentication &#038; Authorization</h4>
<pre style="background: rgba(0,0,0,0.3); color: #fff; padding: 25px; border-radius: 8px; font-size: 1.05em; line-height: 1.8;">
// Add auth services
builder.Services.AddAuthentication()
    .AddJwtBearer();
builder.Services.AddAuthorization();

var app = builder.Build();

app.UseAuthentication();
app.UseAuthorization();

// Require authentication
app.MapGet("/api/profile", async (HttpContext context) =>
{
    return Results.Ok(new { user = context.User.Identity?.Name });
})
.RequireAuthorization();  // Requires authenticated user

// Require specific role
app.MapDelete("/api/users/{id}", async (int id, IUserRepository repo) =>
{
    await repo.DeleteAsync(id);
    return Results.NoContent();
})
.RequireAuthorization("AdminOnly");

// Require policy
app.MapPost("/api/admin/config", async (Config config) =>
{
    // Admin action
})
.RequireAuthorization(policy => policy.RequireRole("Admin"));
</pre>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #27ae60; padding-left: 20px;">Validation &#038; Error Handling</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// Install: FluentValidation.AspNetCore
builder.Services.AddValidatorsFromAssemblyContaining<Program>();

// Validator
public class CreateUserValidator : AbstractValidator<CreateUserDto>
{
    public CreateUserValidator()
    {
        RuleFor(x => x.Email).NotEmpty().EmailAddress();
        RuleFor(x => x.Name).NotEmpty().MaximumLength(100);
        RuleFor(x => x.Age).GreaterThan(0).LessThan(150);
    }
}

// Endpoint with validation
app.MapPost("/api/users", async (
    CreateUserDto dto,
    IValidator<CreateUserDto> validator,
    IUserService service) =>
{
    var validationResult = await validator.ValidateAsync(dto);
    if (!validationResult.IsValid)
    {
        return Results.ValidationProblem(validationResult.ToDictionary());
    }
    
    var user = await service.CreateAsync(dto);
    return Results.Created($"/api/users/{user.Id}", user);
});

// Global exception handler
app.UseExceptionHandler(exceptionHandlerApp =>
{
    exceptionHandlerApp.Run(async context =>
    {
        context.Response.StatusCode = 500;
        context.Response.ContentType = "application/json";
        
        var error = context.Features.Get<IExceptionHandlerFeature>();
        if (error != null)
        {
            await context.Response.WriteAsJsonAsync(new
            {
                error = "An error occurred",
                detail = error.Error.Message
            });
        }
    });
});
</pre>
<div style="background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%); padding: 35px; border-radius: 12px; margin: 40px 0; border-left: 5px solid #28a745;">
<h4 style="color: #155724; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Benefits of Minimal APIs</h4>
<ul style="color: #155724; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Less code:</strong> 50-70% less boilerplate than controllers</li>
<li><strong>Faster startup:</strong> Reduced overhead</li>
<li><strong>Easy to understand:</strong> Everything in one place</li>
<li><strong>Perfect for microservices:</strong> Lightweight, focused</li>
<li><strong>Modern C# features:</strong> Top-level statements, implicit usings</li>
</ul></div>
<div style="background: linear-gradient(135deg, #fff3cd 0%, #ffe69c 100%); border-left: 5px solid #ffc107; padding: 35px; margin: 50px 0; border-radius: 12px;">
<h4 style="color: #856404; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Pro Tips</h4>
<ul style="color: #856404; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Use route groups:</strong> Group related endpoints</li>
<li><strong>Add Swagger:</strong> builder.Services.AddEndpointsApiExplorer()</li>
<li><strong>Organize endpoints:</strong> Use extension methods for large apps</li>
<li><strong>Add filters:</strong> .AddEndpointFilter() for cross-cutting concerns</li>
<li><strong>Use Results:</strong> Results.Ok(), Results.NotFound() for typed responses</li>
</ul></div>
<div style="background: #f8f9fa; padding: 40px; border-radius: 12px; margin: 40px 0; border: 2px solid #667eea;">
<h4 style="color: #667eea; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> When to Use Minimal APIs</h4>
<table style="width: 100%; border-collapse: collapse; margin: 20px 0;">
<tr style="background: #667eea; color: white;">
<th style="padding: 15px; text-align: left;">Use Minimal APIs</th>
<th style="padding: 15px; text-align: left;">Use Controllers</th>
</tr>
<tr>
<td style="padding: 12px; border-bottom: 1px solid #ddd;">Microservices</td>
<td style="padding: 12px; border-bottom: 1px solid #ddd;">Large monolithic apps</td>
</tr>
<tr style="background: #f8f9fa;">
<td style="padding: 12px; border-bottom: 1px solid #ddd;">Simple CRUD APIs</td>
<td style="padding: 12px; border-bottom: 1px solid #ddd;">Complex business logic</td>
</tr>
<tr>
<td style="padding: 12px; border-bottom: 1px solid #ddd;">Prototypes, POCs</td>
<td style="padding: 12px; border-bottom: 1px solid #ddd;">Team prefers MVC patterns</td>
</tr>
<tr style="background: #f8f9fa;">
<td style="padding: 12px; border-bottom: 1px solid #ddd;">Serverless functions</td>
<td style="padding: 12px; border-bottom: 1px solid #ddd;">Need attribute routing features</td>
</tr>
<tr>
<td style="padding: 12px;">Quick HTTP services</td>
<td style="padding: 12px;">Established codebase with controllers</td>
</tr>
</table></div>
<blockquote style="background: linear-gradient(to right, #e8eaf6, #c5cae9); border-left: 6px solid #5c6bc0; padding: 40px; margin: 50px 0; border-radius: 12px;">
<p style="font-size: 1.5em; line-height: 1.9; margin: 0; color: #1a237e; font-style: italic; font-weight: 500;">&#8220;Rewrote microservice API from MVC to Minimal APIs. Code reduced from 500 lines across 5 files to 150 lines in Program.cs. Startup time halved. Easier for juniors to understand.&#8221;</p>
<footer style="margin-top: 20px; color: #283593; font-size: 1.15em; font-weight: 600;">— .NET Architect</footer>
</blockquote>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-use-minimal-apis-for-lightweight-http-services/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET Core: Add Health Checks to Monitor Application Status</title>
		<link>http://blog.ercanopak.com/net-core-add-health-checks-to-monitor-application-status/</link>
					<comments>http://blog.ercanopak.com/net-core-add-health-checks-to-monitor-application-status/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Sun, 22 Mar 2026 09:05:08 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[.NET Tips]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[Health Checks]]></category>
		<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[Load Balancing]]></category>
		<category><![CDATA[microservices]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[reliability]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-add-health-checks-to-monitor-application-status/</guid>

					<description><![CDATA[💓 Know When Your App Is Sick Load balancer needs to know: is app healthy? Database connected? Redis available? Health checks provide instant status. Basic Health Check Setup // Program.cs var builder = WebApplication.CreateBuilder(args); // Add health checks builder.Services.AddHealthChecks(); var app = builder.Build(); // Map health check endpoint app.MapHealthChecks("/health"); app.Run(); // GET /health // Response: [&#8230;]]]></description>
										<content:encoded><![CDATA[<div style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; padding: 50px 40px; border-radius: 16px; margin: 40px 0; box-shadow: 0 20px 60px rgba(0,0,0,0.3);">
<h2 style="margin: 0 0 20px 0; font-size: 2.8em; font-weight: 800; line-height: 1.2;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f493.png" alt="💓" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Know When Your App Is Sick</h2>
<p style="font-size: 1.4em; line-height: 1.8; margin: 0; opacity: 0.95;">Load balancer needs to know: is app healthy? Database connected? Redis available? <strong>Health checks</strong> provide instant status.</p>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #f5576c; padding-left: 20px;">Basic Health Check Setup</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// Program.cs
var builder = WebApplication.CreateBuilder(args);

// Add health checks
builder.Services.AddHealthChecks();

var app = builder.Build();

// Map health check endpoint
app.MapHealthChecks("/health");

app.Run();

// GET /health
// Response: Healthy (200 OK)
</pre>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #667eea; padding-left: 20px;">Database Health Check</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// Install package
// dotnet add package AspNetCore.HealthChecks.SqlServer

// Program.cs
builder.Services.AddHealthChecks()
    .AddSqlServer(
        connectionString: builder.Configuration.GetConnectionString("DefaultConnection"),
        name: "sql-server",
        failureStatus: HealthStatus.Degraded,
        tags: new[] { "db", "sql" }
    );

// GET /health
// If DB down: Unhealthy (503)
// If DB slow: Degraded (200)
// If DB OK: Healthy (200)
</pre>
<div style="background: #f8f9fa; padding: 40px; border-radius: 12px; margin: 40px 0; border: 2px solid #f093fb;">
<h4 style="color: #f5576c; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Multiple Dependencies</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// Install packages
// dotnet add package AspNetCore.HealthChecks.Redis
// dotnet add package AspNetCore.HealthChecks.Npgsql
// dotnet add package AspNetCore.HealthChecks.Rabbitmq

builder.Services.AddHealthChecks()
    .AddSqlServer(
        connectionString: config["ConnectionStrings:DefaultConnection"],
        name: "database")
    .AddRedis(
        redisConnectionString: config["Redis:ConnectionString"],
        name: "redis-cache")
    .AddRabbitMQ(
        rabbitConnectionString: config["RabbitMQ:ConnectionString"],
        name: "message-queue")
    .AddUrlGroup(
        uri: new Uri("https://api.external-service.com/health"),
        name: "external-api");

// Separate endpoints for different checks
app.MapHealthChecks("/health/live", new HealthCheckOptions
{
    Predicate = _ => false // Just check if app is running
});

app.MapHealthChecks("/health/ready", new HealthCheckOptions
{
    Predicate = check => check.Tags.Contains("ready")
});
</pre>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #f39c12; padding-left: 20px;">Custom Health Check</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
public class DiskSpaceHealthCheck : IHealthCheck
{
    public Task<HealthCheckResult> CheckHealthAsync(
        HealthCheckContext context,
        CancellationToken cancellationToken = default)
    {
        var drive = DriveInfo.GetDrives().First();
        var freeSpaceGB = drive.AvailableFreeSpace / 1024 / 1024 / 1024;

        if (freeSpaceGB < 1)
        {
            return Task.FromResult(
                HealthCheckResult.Unhealthy(
                    $"Low disk space: {freeSpaceGB}GB remaining"));
        }

        if (freeSpaceGB < 5)
        {
            return Task.FromResult(
                HealthCheckResult.Degraded(
                    $"Disk space getting low: {freeSpaceGB}GB remaining"));
        }

        return Task.FromResult(
            HealthCheckResult.Healthy(
                $"Disk space OK: {freeSpaceGB}GB remaining"));
    }
}

// Register
builder.Services.AddHealthChecks()
    .AddCheck<DiskSpaceHealthCheck>("disk-space");
</pre>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #00f2fe; padding-left: 20px;">Detailed JSON Response</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
app.MapHealthChecks("/health", new HealthCheckOptions
{
    ResponseWriter = async (context, report) =>
    {
        context.Response.ContentType = "application/json";
        
        var result = JsonSerializer.Serialize(new
        {
            status = report.Status.ToString(),
            checks = report.Entries.Select(e => new
            {
                name = e.Key,
                status = e.Value.Status.ToString(),
                description = e.Value.Description,
                duration = e.Value.Duration.TotalMilliseconds
            }),
            totalDuration = report.TotalDuration.TotalMilliseconds
        });

        await context.Response.WriteAsync(result);
    }
});

// GET /health
// {
//   "status": "Healthy",
//   "checks": [
//     {
//       "name": "database",
//       "status": "Healthy",
//       "description": "SQL Server is responsive",
//       "duration": 25.3
//     },
//     {
//       "name": "redis-cache",
//       "status": "Healthy",
//       "description": null,
//       "duration": 8.1
//     }
//   ],
//   "totalDuration": 45.7
// }
</pre>
<div style="background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%); padding: 35px; border-radius: 12px; margin: 40px 0; border-left: 5px solid #28a745;">
<h4 style="color: #155724; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Kubernetes Integration</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="yaml">
# Kubernetes deployment.yaml
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        livenessProbe:
          httpGet:
            path: /health/live
            port: 80
          initialDelaySeconds: 10
          periodSeconds: 30
        readinessProbe:
          httpGet:
            path: /health/ready
            port: 80
          initialDelaySeconds: 5
          periodSeconds: 10
</pre>
<p style="color: #155724; font-size: 1.1em; margin: 15px 0;"><strong>Liveness:</strong> Is app running? (Restart if fails)</p>
<p style="color: #155724; font-size: 1.1em; margin: 15px 0;"><strong>Readiness:</strong> Can app serve traffic? (Remove from load balancer if fails)</p>
</p></div>
<div style="background: linear-gradient(135deg, #fff3cd 0%, #ffe69c 100%); border-left: 5px solid #ffc107; padding: 35px; margin: 50px 0; border-radius: 12px;">
<h4 style="color: #856404; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Best Practices</h4>
<ul style="color: #856404; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Keep checks fast:</strong> < 1 second, don't do heavy operations</li>
<li><strong>Use tags:</strong> Group related checks (db, cache, external)</li>
<li><strong>Separate endpoints:</strong> /health/live vs /health/ready</li>
<li><strong>Monitor metrics:</strong> Track health check failures over time</li>
<li><strong>Secure endpoints:</strong> Don&#8217;t expose sensitive info in health responses</li>
</ul></div>
<blockquote style="background: linear-gradient(to right, #fce4ec, #f8bbd0); border-left: 6px solid #e91e63; padding: 40px; margin: 50px 0; border-radius: 12px;">
<p style="font-size: 1.5em; line-height: 1.9; margin: 0; color: #880e4f; font-style: italic; font-weight: 500;">&#8220;Added health checks to all microservices. Kubernetes auto-restarts unhealthy pods. Database connection issues detected instantly. Load balancer removes sick instances. Zero manual intervention. Self-healing infrastructure.&#8221;</p>
<footer style="margin-top: 20px; color: #ad1457; font-size: 1.15em; font-weight: 600;">— Platform Engineer</footer>
</blockquote>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-add-health-checks-to-monitor-application-status/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET Core: Use IHostedService for Background Tasks</title>
		<link>http://blog.ercanopak.com/net-core-use-ihostedservice-for-background-tasks/</link>
					<comments>http://blog.ercanopak.com/net-core-use-ihostedservice-for-background-tasks/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Sun, 22 Mar 2026 09:05:01 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[.NET Tips]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[background jobs]]></category>
		<category><![CDATA[Background Services]]></category>
		<category><![CDATA[BackgroundService]]></category>
		<category><![CDATA[Email Queue]]></category>
		<category><![CDATA[IHostedService]]></category>
		<category><![CDATA[Long Running Tasks]]></category>
		<category><![CDATA[Scheduled Tasks]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-use-ihostedservice-for-background-tasks/</guid>

					<description><![CDATA[⏰ Long-Running Tasks in ASP.NET Core Need scheduled jobs? Background processing? Email queue? IHostedService runs tasks in background without blocking requests. Basic Background Service public class EmailQueueService : BackgroundService { private readonly ILogger _logger; private readonly IServiceProvider _services; public EmailQueueService( ILogger logger, IServiceProvider services) { _logger = logger; _services = services; } protected override async [&#8230;]]]></description>
										<content:encoded><![CDATA[<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 50px 40px; border-radius: 16px; margin: 40px 0; box-shadow: 0 20px 60px rgba(0,0,0,0.3);">
<h2 style="margin: 0 0 20px 0; font-size: 2.8em; font-weight: 800; line-height: 1.2;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/23f0.png" alt="⏰" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Long-Running Tasks in ASP.NET Core</h2>
<p style="font-size: 1.4em; line-height: 1.8; margin: 0; opacity: 0.95;">Need scheduled jobs? Background processing? Email queue? <strong>IHostedService</strong> runs tasks in background without blocking requests.</p>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #764ba2; padding-left: 20px;">Basic Background Service</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
public class EmailQueueService : BackgroundService
{
    private readonly ILogger<EmailQueueService> _logger;
    private readonly IServiceProvider _services;

    public EmailQueueService(
        ILogger<EmailQueueService> logger,
        IServiceProvider services)
    {
        _logger = logger;
        _services = services;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Email Queue Service started");

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                // Create scope for scoped services
                using var scope = _services.CreateScope();
                var emailService = scope.ServiceProvider
                    .GetRequiredService<IEmailService>();

                // Process emails
                await emailService.ProcessQueueAsync();

                // Wait 30 seconds before next run
                await Task.Delay(TimeSpan.FromSeconds(30), stoppingToken);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error processing email queue");
            }
        }

        _logger.LogInformation("Email Queue Service stopped");
    }
}

// Program.cs - Register service
builder.Services.AddHostedService<EmailQueueService>();
</pre>
<div style="background: #f8f9fa; padding: 40px; border-radius: 12px; margin: 40px 0; border: 2px solid #667eea;">
<h4 style="color: #667eea; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Scheduled Task Example</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
public class DailyReportService : BackgroundService
{
    private readonly ILogger<DailyReportService> _logger;
    private readonly IServiceProvider _services;

    public DailyReportService(
        ILogger<DailyReportService> logger,
        IServiceProvider services)
    {
        _logger = logger;
        _services = services;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // Calculate time until next 9 AM
            var now = DateTime.Now;
            var nextRun = DateTime.Today.AddHours(9);
            
            if (now > nextRun)
            {
                nextRun = nextRun.AddDays(1);
            }

            var delay = nextRun - now;
            
            _logger.LogInformation($"Next report at {nextRun}");
            
            // Wait until 9 AM
            await Task.Delay(delay, stoppingToken);

            // Generate report
            using var scope = _services.CreateScope();
            var reportService = scope.ServiceProvider
                .GetRequiredService<IReportService>();
            
            await reportService.GenerateDailyReportAsync();
        }
    }
}
</pre>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #f39c12; padding-left: 20px;">IHostedService vs BackgroundService</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 25px; margin: 40px 0;">
<div style="background: white; padding: 30px; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); border-top: 4px solid #667eea;">
<h4 style="color: #667eea; margin-top: 0; font-size: 1.5em; font-weight: 700;">IHostedService</h4>
<pre style="font-size: 0.9em; background: #f8f9fa; padding: 15px; border-radius: 6px; overflow-x: auto;">// Manual implementation
public class MyService : IHostedService
{
    public Task StartAsync(
        CancellationToken ct)
    {
        // Start logic
        return Task.CompletedTask;
    }

    public Task StopAsync(
        CancellationToken ct)
    {
        // Cleanup
        return Task.CompletedTask;
    }
}</pre>
<p style="margin-top: 15px; color: #34495e;"><strong>Use when:</strong> Need full control</p>
</p></div>
<div style="background: white; padding: 30px; border-radius: 12px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); border-top: 4px solid #27ae60;">
<h4 style="color: #27ae60; margin-top: 0; font-size: 1.5em; font-weight: 700;">BackgroundService</h4>
<pre style="font-size: 0.9em; background: #f8f9fa; padding: 15px; border-radius: 6px; overflow-x: auto;">// Easier implementation
public class MyService 
    : BackgroundService
{
    protected override async Task
        ExecuteAsync(
            CancellationToken ct)
    {
        // Long-running work
        while (!ct.IsCancellationRequested)
        {
            await DoWorkAsync();
            await Task.Delay(1000, ct);
        }
    }
}</pre>
<p style="margin-top: 15px; color: #34495e;"><strong>Use when:</strong> Long-running loops</p>
</p></div>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #00f2fe; padding-left: 20px;">Real-World Use Cases</h3>
<div style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); color: white; padding: 35px; border-radius: 12px; margin: 40px 0;">
<h4 style="margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4e7.png" alt="📧" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Email Queue Processor</h4>
<ul style="font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li>Checks database for pending emails every 30 seconds</li>
<li>Sends emails in background</li>
<li>Marks as sent/failed in database</li>
<li>Doesn&#8217;t block web requests</li>
</ul></div>
<div style="background: linear-gradient(135deg, #fa709a 0%, #fee140 100%); color: white; padding: 35px; border-radius: 12px; margin: 40px 0;">
<h4 style="margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f5d1.png" alt="🗑" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Cleanup Service</h4>
<ul style="font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li>Runs every night at 2 AM</li>
<li>Deletes old temp files</li>
<li>Archives old database records</li>
<li>Clears expired cache entries</li>
</ul></div>
<div style="background: linear-gradient(135deg, #56ab2f 0%, #a8e063 100%); color: white; padding: 35px; border-radius: 12px; margin: 40px 0;">
<h4 style="margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4ca.png" alt="📊" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Data Sync Service</h4>
<ul style="font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li>Polls external API every 5 minutes</li>
<li>Syncs data to local database</li>
<li>Updates cache</li>
<li>Notifies connected clients via SignalR</li>
</ul></div>
<div style="background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%); padding: 35px; border-radius: 12px; margin: 40px 0; border-left: 5px solid #28a745;">
<h4 style="color: #155724; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4a1.png" alt="💡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Best Practices</h4>
<ul style="color: #155724; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Use scopes for DI:</strong> Hosted services are singletons, create scopes for scoped services</li>
<li><strong>Handle exceptions:</strong> Wrap work in try-catch, log errors</li>
<li><strong>Respect cancellation:</strong> Check <code>stoppingToken.IsCancellationRequested</code></li>
<li><strong>Graceful shutdown:</strong> Clean up resources in StopAsync</li>
<li><strong>Don&#8217;t block startup:</strong> Long initialization? Do it async in ExecuteAsync</li>
</ul></div>
<div style="background: linear-gradient(135deg, #fff3cd 0%, #ffe69c 100%); border-left: 5px solid #ffc107; padding: 35px; margin: 50px 0; border-radius: 12px;">
<h4 style="color: #856404; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Important Notes</h4>
<ul style="color: #856404; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Not for heavy work:</strong> For CPU-intensive tasks, use separate worker service</li>
<li><strong>No guaranteed execution:</strong> App restart = service stops</li>
<li><strong>Consider Hangfire/Quartz:</strong> For complex scheduling, use dedicated libraries</li>
<li><strong>Health checks:</strong> Add health check endpoint to monitor service status</li>
</ul></div>
<blockquote style="background: linear-gradient(to right, #e8eaf6, #c5cae9); border-left: 6px solid #5c6bc0; padding: 40px; margin: 50px 0; border-radius: 12px;">
<p style="font-size: 1.5em; line-height: 1.9; margin: 0; color: #1a237e; font-style: italic; font-weight: 500;">&#8220;Moved email sending to background service. API responses instant now. Emails send reliably in background. Added retry logic. Zero impact on user experience. Should&#8217;ve done this years ago.&#8221;</p>
<footer style="margin-top: 20px; color: #283593; font-size: 1.15em; font-weight: 600;">— Backend Developer</footer>
</blockquote>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-use-ihostedservice-for-background-tasks/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET Core: Use Result Pattern Instead of Throwing Exceptions</title>
		<link>http://blog.ercanopak.com/net-core-use-result-pattern-instead-of-throwing-exceptions/</link>
					<comments>http://blog.ercanopak.com/net-core-use-result-pattern-instead-of-throwing-exceptions/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 20:29:11 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[.NET Tips]]></category>
		<category><![CDATA[C# Patterns]]></category>
		<category><![CDATA[Clean Code]]></category>
		<category><![CDATA[Error Handling]]></category>
		<category><![CDATA[Functional Programming]]></category>
		<category><![CDATA[No Exceptions]]></category>
		<category><![CDATA[Result Pattern]]></category>
		<category><![CDATA[Type Safety]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-use-result-pattern-instead-of-throwing-exceptions/</guid>

					<description><![CDATA[🎯 Explicit Error Handling Exceptions for control flow? Expensive. Hidden. Result pattern makes errors explicit and performant. Traditional Exception Way public User GetUser(int id) { var user = _db.Users.Find(id); if (user == null) throw new NotFoundException("User not found"); if (!user.IsActive) throw new InvalidOperationException("User inactive"); return user; } // Caller has no idea what exceptions to [&#8230;]]]></description>
										<content:encoded><![CDATA[<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 50px 40px; border-radius: 16px; margin: 40px 0; box-shadow: 0 20px 60px rgba(0,0,0,0.3);">
<h2 style="margin: 0 0 20px 0; font-size: 2.8em; font-weight: 800; line-height: 1.2;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Explicit Error Handling</h2>
<p style="font-size: 1.4em; line-height: 1.8; margin: 0; opacity: 0.95;">Exceptions for control flow? Expensive. Hidden. <strong>Result pattern</strong> makes errors explicit and performant.</p>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #764ba2; padding-left: 20px;">Traditional Exception Way</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
public User GetUser(int id)
{
    var user = _db.Users.Find(id);
    if (user == null)
        throw new NotFoundException("User not found");
    
    if (!user.IsActive)
        throw new InvalidOperationException("User inactive");
    
    return user;
}

// Caller has no idea what exceptions to catch
try
{
    var user = GetUser(123);
}
catch (Exception ex) // Too broad!
{
    // What went wrong?
}
</pre>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #27ae60; padding-left: 20px;">Result Pattern Way</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// Result class
public class Result<T>
{
    public bool IsSuccess { get; }
    public T Value { get; }
    public string Error { get; }
    
    private Result(T value)
    {
        IsSuccess = true;
        Value = value;
    }
    
    private Result(string error)
    {
        IsSuccess = false;
        Error = error;
    }
    
    public static Result<T> Success(T value) => new(value);
    public static Result<T> Failure(string error) => new(error);
}

// Usage
public Result<User> GetUser(int id)
{
    var user = _db.Users.Find(id);
    if (user == null)
        return Result<User>.Failure("User not found");
    
    if (!user.IsActive)
        return Result<User>.Failure("User inactive");
    
    return Result<User>.Success(user);
}

// Caller knows exactly what to check
var result = GetUser(123);
if (result.IsSuccess)
{
    var user = result.Value;
    // Success path
}
else
{
    // Handle error
    Console.WriteLine(result.Error);
}
</pre>
<div style="background: #f8f9fa; padding: 40px; border-radius: 12px; margin: 40px 0; border: 2px solid #667eea;">
<h4 style="color: #667eea; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> API Controller Integration</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
[HttpGet("{id}")]
public IActionResult GetUser(int id)
{
    var result = _userService.GetUser(id);
    
    return result.IsSuccess
        ? Ok(result.Value)
        : NotFound(new { error = result.Error });
}

// Clean, explicit, no exceptions
</pre>
</p></div>
<div style="background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%); padding: 35px; border-radius: 12px; margin: 40px 0; border-left: 5px solid #28a745;">
<h4 style="color: #155724; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Benefits</h4>
<ul style="color: #155724; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Performance:</strong> No exception stack trace generation</li>
<li><strong>Explicit:</strong> Caller must handle success/failure</li>
<li><strong>Type-safe:</strong> Compiler enforces error handling</li>
<li><strong>Testable:</strong> Easy to test both paths</li>
</ul></div>
<blockquote style="background: linear-gradient(to right, #e8eaf6, #c5cae9); border-left: 6px solid #5c6bc0; padding: 40px; margin: 50px 0; border-radius: 12px;">
<p style="font-size: 1.5em; line-height: 1.9; margin: 0; color: #1a237e; font-style: italic; font-weight: 500;">&#8220;Switched from exceptions to Result pattern in hot path. Performance improved 40%. Error handling became explicit. Code reviews caught missing error checks at compile time.&#8221;</p>
<footer style="margin-top: 20px; color: #283593; font-size: 1.15em; font-weight: 600;">— Principal Engineer</footer>
</blockquote>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-use-result-pattern-instead-of-throwing-exceptions/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET Core: Use Minimal APIs for Lightweight Endpoints</title>
		<link>http://blog.ercanopak.com/net-core-use-minimal-apis-for-lightweight-endpoints/</link>
					<comments>http://blog.ercanopak.com/net-core-use-minimal-apis-for-lightweight-endpoints/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 20:29:03 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.NET 6]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[.NET Tips]]></category>
		<category><![CDATA[API Development]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[Lightweight APIs]]></category>
		<category><![CDATA[microservices]]></category>
		<category><![CDATA[Minimal APIs]]></category>
		<category><![CDATA[Modern .NET]]></category>
		<category><![CDATA[Simplified Code]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-use-minimal-apis-for-lightweight-endpoints/</guid>

					<description><![CDATA[⚡ Build APIs in 5 Lines of Code Skip controllers, routing, Startup.cs. Minimal APIs (.NET 6+) make simple endpoints incredibly simple. Traditional Controller Way // Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddControllers(); } public void Configure(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => endpoints.MapControllers()); } // UsersController.cs [ApiController] [Route("api/[controller]")] public class UsersController : ControllerBase { [HttpGet] public [&#8230;]]]></description>
										<content:encoded><![CDATA[<div style="background: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); color: white; padding: 50px 40px; border-radius: 16px; margin: 40px 0; box-shadow: 0 20px 60px rgba(0,0,0,0.3);">
<h2 style="margin: 0 0 20px 0; font-size: 2.8em; font-weight: 800; line-height: 1.2;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a1.png" alt="⚡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Build APIs in 5 Lines of Code</h2>
<p style="font-size: 1.4em; line-height: 1.8; margin: 0; opacity: 0.95;">Skip controllers, routing, Startup.cs. <strong>Minimal APIs</strong> (.NET 6+) make simple endpoints incredibly simple.</p>
</p></div>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #00f2fe; padding-left: 20px;">Traditional Controller Way</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// Startup.cs
public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
}

public void Configure(IApplicationBuilder app)
{
    app.UseRouting();
    app.UseEndpoints(endpoints => endpoints.MapControllers());
}

// UsersController.cs
[ApiController]
[Route("api/[controller]")]
public class UsersController : ControllerBase
{
    [HttpGet]
    public IActionResult Get() => Ok(new[] { "Alice", "Bob" });
}

// 20+ lines for simple endpoint
</pre>
<h3 style="color: #2c3e50; font-size: 2.2em; margin: 50px 0 30px 0; font-weight: 700; border-left: 5px solid #27ae60; padding-left: 20px;">Minimal API Way</h3>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
// Program.cs - That's it!
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/api/users", () => new[] { "Alice", "Bob" });

app.Run();

// 5 lines total <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2728.png" alt="✨" class="wp-smiley" style="height: 1em; max-height: 1em;" />
</pre>
<div style="background: #f8f9fa; padding: 40px; border-radius: 12px; margin: 40px 0; border: 2px solid #4facfe;">
<h4 style="color: #00f2fe; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3af.png" alt="🎯" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Real-World Example</h4>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">
var builder = WebApplication.CreateBuilder(args);

// Add services
builder.Services.AddDbContext<AppDbContext>();
builder.Services.AddScoped<IUserService, UserService>();

var app = builder.Build();

// GET endpoint
app.MapGet("/api/users", async (AppDbContext db) =>
    await db.Users.ToListAsync());

// GET with route parameter
app.MapGet("/api/users/{id}", async (int id, AppDbContext db) =>
    await db.Users.FindAsync(id) is User user
        ? Results.Ok(user)
        : Results.NotFound());

// POST endpoint
app.MapPost("/api/users", async (User user, AppDbContext db) =>
{
    db.Users.Add(user);
    await db.SaveChangesAsync();
    return Results.Created($"/api/users/{user.Id}", user);
});

// PUT endpoint
app.MapPut("/api/users/{id}", async (int id, User updated, AppDbContext db) =>
{
    var user = await db.Users.FindAsync(id);
    if (user is null) return Results.NotFound();
    
    user.Name = updated.Name;
    await db.SaveChangesAsync();
    return Results.Ok(user);
});

// DELETE endpoint
app.MapDelete("/api/users/{id}", async (int id, AppDbContext db) =>
{
    var user = await db.Users.FindAsync(id);
    if (user is null) return Results.NotFound();
    
    db.Users.Remove(user);
    await db.SaveChangesAsync();
    return Results.NoContent();
});

app.Run();
</pre>
</p></div>
<div style="background: linear-gradient(135deg, #d4edda 0%, #c3e6cb 100%); padding: 35px; border-radius: 12px; margin: 40px 0; border-left: 5px solid #28a745;">
<h4 style="color: #155724; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2705.png" alt="✅" class="wp-smiley" style="height: 1em; max-height: 1em;" /> When to Use Minimal APIs</h4>
<ul style="color: #155724; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Microservices:</strong> Small, focused services</li>
<li><strong>Prototypes:</strong> Quick MVP development</li>
<li><strong>Simple APIs:</strong> 5-10 endpoints max</li>
<li><strong>Serverless:</strong> Azure Functions, AWS Lambda</li>
</ul></div>
<div style="background: linear-gradient(135deg, #f8d7da 0%, #f5c6cb 100%); padding: 35px; border-radius: 12px; margin: 40px 0; border-left: 5px solid #dc3545;">
<h4 style="color: #721c24; margin-top: 0; font-size: 1.7em; font-weight: 700;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> When to Use Controllers</h4>
<ul style="color: #721c24; font-size: 1.15em; line-height: 2.2; margin: 20px 0;">
<li><strong>Large APIs:</strong> 50+ endpoints</li>
<li><strong>Complex routing:</strong> Attribute routing, versioning</li>
<li><strong>Filters:</strong> Heavy use of action filters</li>
<li><strong>Team preference:</strong> Team familiar with MVC pattern</li>
</ul></div>
<blockquote style="background: linear-gradient(to right, #e0f7fa, #b2ebf2); border-left: 6px solid #00bcd4; padding: 40px; margin: 50px 0; border-radius: 12px;">
<p style="font-size: 1.5em; line-height: 1.9; margin: 0; color: #006064; font-style: italic; font-weight: 500;">&#8220;Migrated webhook receiver from controller to Minimal API. 40 lines became 8. Performance identical. Startup time 30% faster. Perfect for small services.&#8221;</p>
<footer style="margin-top: 20px; color: #00838f; font-size: 1.15em; font-weight: 600;">— Backend Engineer</footer>
</blockquote>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-use-minimal-apis-for-lightweight-endpoints/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET Core: Use Health Checks for Monitoring</title>
		<link>http://blog.ercanopak.com/net-core-use-health-checks-for-monitoring/</link>
					<comments>http://blog.ercanopak.com/net-core-use-health-checks-for-monitoring/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 20:08:13 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[.NET Tips]]></category>
		<category><![CDATA[API Health]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[devops]]></category>
		<category><![CDATA[Health Checks]]></category>
		<category><![CDATA[kubernetes]]></category>
		<category><![CDATA[Monitoring]]></category>
		<category><![CDATA[reliability]]></category>
		<category><![CDATA[System Monitoring]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-use-health-checks-for-monitoring/</guid>

					<description><![CDATA[How do you know if your API is healthy? Database connected? Redis alive? // Program.cs builder.Services.AddHealthChecks() .AddDbContextCheck() .AddRedis("localhost:6379"); app.MapHealthChecks("/health"); // Visit /health // Response: Healthy or Unhealthy + details Custom Check: public class ApiHealthCheck : IHealthCheck { public async Task CheckHealthAsync(...) { var isHealthy = await CheckExternalApiAsync(); return isHealthy ? HealthCheckResult.Healthy() : HealthCheckResult.Unhealthy("API down"); } [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>How do you know if your API is healthy? Database connected? Redis alive?</p>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">// Program.cs
builder.Services.AddHealthChecks()
    .AddDbContextCheck()
    .AddRedis("localhost:6379");

app.MapHealthChecks("/health");

// Visit /health
// Response: Healthy or Unhealthy + details
</pre>
<p><strong>Custom Check:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">public class ApiHealthCheck : IHealthCheck
{
    public async Task CheckHealthAsync(...)
    {
        var isHealthy = await CheckExternalApiAsync();
        return isHealthy 
            ? HealthCheckResult.Healthy()
            : HealthCheckResult.Unhealthy("API down");
    }
}
</pre>
<p><strong>Use With:</strong> Kubernetes liveness probes, monitoring tools.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-use-health-checks-for-monitoring/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET Core: Use Response Caching Middleware for Static APIs</title>
		<link>http://blog.ercanopak.com/net-core-use-response-caching-middleware-for-static-apis/</link>
					<comments>http://blog.ercanopak.com/net-core-use-response-caching-middleware-for-static-apis/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 20:08:06 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[.NET Tips]]></category>
		<category><![CDATA[API Caching]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[Cache-Control]]></category>
		<category><![CDATA[HTTP Caching]]></category>
		<category><![CDATA[middleware]]></category>
		<category><![CDATA[Response Caching]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-use-response-caching-middleware-for-static-apis/</guid>

					<description><![CDATA[API returns same data for 10 minutes. Still hitting database every request. // Program.cs builder.Services.AddResponseCaching(); var app = builder.Build(); app.UseResponseCaching(); // Controller [ResponseCache(Duration = 600)] // 10 minutes public IActionResult GetProducts() { return Ok(_db.Products.ToList()); } Headers: Sets Cache-Control headers automatically. Browser + server cache. Vary: Cache different responses per user: VaryByHeader = "Authorization" Disable: [ResponseCache(NoStore [&#8230;]]]></description>
										<content:encoded><![CDATA[<p>API returns same data for 10 minutes. Still hitting database every request.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">// Program.cs
builder.Services.AddResponseCaching();

var app = builder.Build();
app.UseResponseCaching();

// Controller
[ResponseCache(Duration = 600)] // 10 minutes
public IActionResult GetProducts()
{
    return Ok(_db.Products.ToList());
}
</pre>
<p><strong>Headers:</strong> Sets Cache-Control headers automatically. Browser + server cache.</p>
<p><strong>Vary:</strong> Cache different responses per user: <code>VaryByHeader = "Authorization"</code></p>
<p><strong>Disable:</strong> <code>[ResponseCache(NoStore = true)]</code> for dynamic data.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-use-response-caching-middleware-for-static-apis/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET Core: Use IHostedService for Startup/Shutdown Logic</title>
		<link>http://blog.ercanopak.com/net-core-use-ihostedservice-for-startup-shutdown-logic/</link>
					<comments>http://blog.ercanopak.com/net-core-use-ihostedservice-for-startup-shutdown-logic/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 19:32:03 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[.NET Tips]]></category>
		<category><![CDATA[App Initialization]]></category>
		<category><![CDATA[Application Lifecycle]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[Background Tasks]]></category>
		<category><![CDATA[cleanup]]></category>
		<category><![CDATA[Graceful Shutdown]]></category>
		<category><![CDATA[IHostedService]]></category>
		<category><![CDATA[Startup Logic]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-use-ihostedservice-for-startup-shutdown-logic/</guid>

					<description><![CDATA[🎬 Lifecycle Hooks Run code on app start/stop. Warm cache, close connections cleanly. public class StartupService : IHostedService { public async Task StartAsync(CancellationToken cancellationToken) { // Runs when app starts await WarmCacheAsync(); await CheckDatabaseConnectionAsync(); } public async Task StopAsync(CancellationToken cancellationToken) { // Runs when app stops (graceful shutdown) await FlushLogsAsync(); await CloseConnectionsAsync(); } } // [&#8230;]]]></description>
										<content:encoded><![CDATA[<div style="background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); color: white; padding: 40px; border-radius: 12px; margin: 25px 0;">
<h2 style="margin-top: 0; font-size: 2.2em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f3ac.png" alt="🎬" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Lifecycle Hooks</h2>
<p style="font-size: 1.3em; line-height: 1.8;">Run code on app start/stop. Warm cache, close connections cleanly.</p>
</div>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">public class StartupService : IHostedService
{
    public async Task StartAsync(CancellationToken cancellationToken)
    {
        // Runs when app starts
        await WarmCacheAsync();
        await CheckDatabaseConnectionAsync();
    }

    public async Task StopAsync(CancellationToken cancellationToken)
    {
        // Runs when app stops (graceful shutdown)
        await FlushLogsAsync();
        await CloseConnectionsAsync();
    }
}

// Register
services.AddHostedService();
</pre>
<p><strong>Use Cases:</strong> Cache warming, health checks, cleanup tasks, connection pooling.</p>
<p><strong>Execution Order:</strong> StartAsync runs before app accepts requests. StopAsync during graceful shutdown.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-use-ihostedservice-for-startup-shutdown-logic/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>.NET Core: Use IMemoryCache for In-Memory Caching Without Redis</title>
		<link>http://blog.ercanopak.com/net-core-use-imemorycache-for-in-memory-caching-without-redis/</link>
					<comments>http://blog.ercanopak.com/net-core-use-imemorycache-for-in-memory-caching-without-redis/#respond</comments>
		
		<dc:creator><![CDATA[ErcanOPAK]]></dc:creator>
		<pubDate>Thu, 19 Mar 2026 19:31:54 +0000</pubDate>
				<category><![CDATA[Asp.Net Core]]></category>
		<category><![CDATA[.Net Core]]></category>
		<category><![CDATA[.NET Tips]]></category>
		<category><![CDATA[ASP.NET Core]]></category>
		<category><![CDATA[Built-in Features]]></category>
		<category><![CDATA[Cache Strategy]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[IMemoryCache]]></category>
		<category><![CDATA[In-Memory Cache]]></category>
		<category><![CDATA[Performance Optimization]]></category>
		<guid isPermaLink="false">http://blog.ercanopak.com/net-core-use-imemorycache-for-in-memory-caching-without-redis/</guid>

					<description><![CDATA[⚡ Built-in Cache Redis overkill for small apps. IMemoryCache built into .NET. Zero config. // Startup services.AddMemoryCache(); // Usage public class UserService { private readonly IMemoryCache _cache; public async Task GetUserAsync(int id) { return await _cache.GetOrCreateAsync( $"user-{id}", async entry =&#62; { entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5); return await _db.Users.FindAsync(id); } ); } } When It&#8217;s Enough: Single [&#8230;]]]></description>
										<content:encoded><![CDATA[<div style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 40px; border-radius: 12px; margin: 25px 0;">
<h2 style="margin-top: 0; font-size: 2.2em;"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a1.png" alt="⚡" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Built-in Cache</h2>
<p style="font-size: 1.3em; line-height: 1.8;">Redis overkill for small apps. IMemoryCache built into .NET. Zero config.</p>
</div>
<pre class="EnlighterJSRAW" data-enlighter-language="csharp">// Startup
services.AddMemoryCache();

// Usage
public class UserService
{
    private readonly IMemoryCache _cache;
    
    public async Task GetUserAsync(int id)
    {
        return await _cache.GetOrCreateAsync(
            $"user-{id}",
            async entry =&gt;
            {
                entry.AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(5);
                return await _db.Users.FindAsync(id);
            }
        );
    }
}
</pre>
<p><strong>When It&#8217;s Enough:</strong> Single server, moderate traffic, &lt;10GB cache needs.</p>
<p><strong>Upgrade Path:</strong> Later swap to Redis. Same IDistributedCache interface.</p>
]]></content:encoded>
					
					<wfw:commentRss>http://blog.ercanopak.com/net-core-use-imemorycache-for-in-memory-caching-without-redis/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
