quotes-net / Program.cs
Florin Bobiș
Super fast api
77ebc6a
raw
history blame
7.69 kB
using System.Linq;
using System.Text.Json;
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
builder.WebHost.ConfigureKestrel(serverOptions =>
{
serverOptions.Listen(System.Net.IPAddress.Any, 7860); // Listen on all network interfaces on port 5000
});
builder.Services.AddDbContext<QuoteDbContext>(options =>
options.UseSqlite("Data Source=quotes.db"));
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
var app = builder.Build();
// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
const int MaxPageSize = 100;
app.UseHttpsRedirection();
app.MapGet("/quotes", async (QuoteDbContext db, int pageNumber = 1, int pageSize = 10) =>
{
if (pageNumber < 1) pageNumber = 1;
if (pageSize < 1) pageSize = 10;
pageSize = Math.Min(pageSize, MaxPageSize); // Limit pageSize to MaxPageSize
// var quotes = await db.Quotes
// .Skip((pageNumber - 1) * pageSize)
// .Take(pageSize)
// .ToListAsync();
var quotes = GlobalData.Quotes
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToList();
return Results.Ok(quotes);
});
app.MapGet("/quotes/{id}", async (int id, QuoteDbContext db) =>
await db.Quotes.FindAsync(id) is Quote quote
? Results.Ok(quote)
: Results.NotFound("Quote not found"));
app.MapPost("/quotes", async (Quote newQuote, QuoteDbContext db) =>
{
db.Quotes.Add(newQuote);
await db.SaveChangesAsync();
return Results.Created($"/quotes/{newQuote.Id}", newQuote);
});
app.MapPut("/quotes/{id}", async (int id, Quote updatedQuote, QuoteDbContext db) =>
{
var quote = await db.Quotes.FindAsync(id);
if (quote is null) return Results.NotFound("Quote not found");
quote.Author = updatedQuote.Author;
quote.QuoteText = updatedQuote.QuoteText;
quote.Source = updatedQuote.Source;
quote.Book = updatedQuote.Book;
quote.Categories = updatedQuote.Categories;
quote.Url = updatedQuote.Url;
quote.Isbn = updatedQuote.Isbn;
quote.Language = updatedQuote.Language;
quote.OriginalLanguage = updatedQuote.OriginalLanguage;
await db.SaveChangesAsync();
return Results.NoContent();
});
app.MapDelete("/quotes/{id}", async (int id, QuoteDbContext db) =>
{
var quote = await db.Quotes.FindAsync(id);
if (quote is null) return Results.NotFound("Quote not found");
db.Quotes.Remove(quote);
await db.SaveChangesAsync();
return Results.NoContent();
});
// Random quote endpoint
app.MapGet("/quotes/random", async (QuoteDbContext db) =>
{
var quoteCount = GlobalData.Quotes.Count(); //await db.Quotes.CountAsync();
if (quoteCount == 0)
return Results.NotFound("No quotes available.");
var random = new Random();
var randomIndex = random.Next(quoteCount);
var randomQuote = GlobalData.Quotes[randomIndex]; //await db.Quotes.Skip(randomIndex).Take(1).FirstOrDefaultAsync();
return randomQuote != null ? Results.Ok(randomQuote) : Results.NotFound("No quote found.");
});
// Search quotes by author, categories, book, or quoteText with pagination
app.MapGet("/quotes/search", async (string search, QuoteDbContext db, int pageNumber = 1, int pageSize = 10) =>
{
var query = GlobalData.Quotes.AsQueryable(); //db.Quotes.AsQueryable();
if (!string.IsNullOrWhiteSpace(search))
query = query.Where(q => q.Author.Contains(search));
if (!string.IsNullOrWhiteSpace(search))
query = query.Where(q => q.Categories.Contains(search));
if (!string.IsNullOrWhiteSpace(search))
query = query.Where(q => q.Book.Contains(search));
if (!string.IsNullOrWhiteSpace(search))
query = query.Where(q => q.QuoteText.Contains(search));
if (pageNumber < 1) pageNumber = 1;
if (pageSize < 1) pageSize = 10;
pageSize = Math.Min(pageSize, MaxPageSize); // Limit pageSize to MaxPageSize
var paginatedQuotes = await query
.Skip((pageNumber - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
return paginatedQuotes.Any() ? Results.Ok(paginatedQuotes) : Results.NotFound("No matching quotes found.");
});
app.MapGet("/health", () => Results.Ok(new { Status = "Healthy", Timestamp = DateTime.UtcNow }));
async Task SaveSource1Async(string jsonFilePath, QuoteDbContext db)
{
var path = Path.Combine(Directory.GetCurrentDirectory(), "data", jsonFilePath);
if (!File.Exists(path))
throw new FileNotFoundException("The JSON file for seeding is missing.");
// var jsonString = await File.ReadAllTextAsync(path);
// // Deserialize JSON to a list of dictionaries
// var dictionaryList = JsonSerializer.Deserialize<List<Dictionary<string, object>>>(jsonString);
// if (dictionaryList == null)
// throw new InvalidOperationException("Failed to deserialize JSON into dictionary list.");
// Fields
// ==========
// Quote (string)
// Author (string)
// Tags (list<string>)
// Category (string)
// foreach (var dictionary in dictionaryList)
// {
// var tags = "";
// if(dictionary.TryGetValue("Tags", out var categories)) {
// var list = JsonSerializer.Deserialize<List<string>>(categories.ToString());
// tags = String.Join(",", list.Select(x=> x.Trim().Trim('"')));
// }
// var quote = new Quote
// {
// Author = dictionary.TryGetValue("Author", out var author) ? author.ToString() : null,
// QuoteText = dictionary.TryGetValue("Quote", out var quoteText) ? quoteText.ToString() : null,
// Categories = tags,
// };
// db.Quotes.Add(quote);
// }
// TODO: import data and sanitize relevant fields: Trim and Trim('"')
//save for each seed file
await db.SaveChangesAsync();
}
async Task SaveSource2Async(string jsonFile, QuoteDbContext db)
{
var path = Path.Combine(Directory.GetCurrentDirectory(), "data", jsonFile);
if (!File.Exists(path))
throw new FileNotFoundException("The JSON file for seeding is missing.");
// Fields
// ==========
// content (string)
// author (string)
// tags (list<string>)
// TODO: import data and sanitize relevant fields: Trim and Trim('"')
//save for each seed file
await db.SaveChangesAsync();
}
async Task SaveSource3Async(string csvFile, QuoteDbContext db)
{
var path = Path.Combine(Directory.GetCurrentDirectory(), "data", csvFile);
if (!File.Exists(path))
throw new FileNotFoundException("The CSV file for seeding is missing.");
// Fields
// ==========
// quote (string)
// author (string)
// category (string)
// TODO: import data and sanitize relevant fields: Trim and Trim('"')
//save for each seed file
await db.SaveChangesAsync();
}
// Seed database
async Task SeedDatabase(QuoteDbContext db)
{
if (await db.Quotes.AnyAsync())
return; // Database is already seeded
await SaveSource1Async("source1.json", db);
await SaveSource2Async("source2.json", db);
await SaveSource3Async("source3.csv", db);
}
using (var scope = app.Services.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<QuoteDbContext>();
db.Database.EnsureCreated();
GlobalData.Quotes = await db.Quotes.ToListAsync();
await SeedDatabase(db);
}
app.Run();