יצירת קובץ Minimal Api
נפריד את הגדרות ה-Minimal Api לקובץ נפרד. נייצר תיקייה בשם EndPoints. בתוכו נייצר class שבו ישבו ProductsEndPoints. את ה-class נגדיר כ-static.
קובץ ProductsEndPoints.cs
public static class ProductsEndPoints
{
}
בתוך ה-class נגדיר extention methods, שזה היכולת להגדיר פונקציה שהיא שייכת ל-class או interface בלי לכתוב אותה בתוכם.
את כל הפעולות שעשינו עד עכשיו עשינו דרך ה-app, שזה web application. אותו אנחנו רוצים להרחיב כדי לאפשר לנו להוסיף את כל הפעולות שיש לנו. נכתוב פונקציה שאליה נעביר את כל הפעולות מקובץ ה-program.
public static class ProductsEndPoints
{
public static void MapProducts(this WebApplication app) {
var productGroup = app.MapGroup("products").WithTags("Products");
productGroup.MapGet("", async Task<Ok<List<Product>>>
(IProductsRepository repo) => {
var result = await repo.GetAllProducts();
return TypedResults.Ok(result);
});
productGroup.MapGet("{id}", async Task<Results<NotFound, Ok<Product>>>
(int id, IProductsRepository repo) => {
var result = await repo.GetProductById(id);
if (result == null) {
return TypedResults.NotFound();
}
return TypedResults.Ok(result);
});
productGroup.MapDelete("{id}", async Task<Results<NotFound, Ok<Product>>>
(int id, IProductsRepository repo) => {
var result = await repo.GetProductById(id);
if (result == null) {
return TypedResults.NotFound();
}
await repo.DeleteProduct(id);
return TypedResults.Ok(result);
});
productGroup.MapPut("{id}", async Task<Results<NotFound, Ok<Product>>>
(int id, Product product, IProductsRepository repo) => {
var result = await repo.GetProductById(id);
if (result == null) {
return TypedResults.NotFound();
}
var productAfterUpdate = await repo.UpdateProduct(id, product);
return TypedResults.Ok(productAfterUpdate);
});
productGroup.MapPost("", async Task<Created<Product>>
(Product product, IProductsRepository repo) => {
Product addProduct = await repo.AddNewProduct(product);
return TypedResults.Created($"api/products/{addProduct.id}", addProduct);
});
}
}
ומה שצריך לעשות ב-program זה לקרוא לפונקציה הזאת.
קובץ program.cs
app.MapProducts();
לכל סט של endpoints שנצטרך ניצור קובץ ונכלול אותו באותה הדרך ב-program.
סידור הפונקציות
לסיום נרצה שהפונקציות בקובץ יהיו ברורות מייד במבט על הקובץ. בשביל זה נכתוב כל פונקציה בנפרד.
במקום:
קובץ ProductsEndPoints.cs
productGroup.MapGet("", async Task<Ok<List<Product>>> (IProductsRepository repo) => {
var result = await repo.GetAllProducts();
return TypedResults.Ok(result);
});
נוציא את התוכן לפונקציה נפרדת:
static async Task<Ok<List<Product>>> GetAllProducts(IProductsRepository repo){
var result = await repo.GetAllProducts();
return TypedResults.Ok(result);
}
ובתוך MapProducts נבקש להפעיל את הפונקציה הזאת.
productGroup.MapGet("", GetAllProducts).WithName(nameof(GetAllProducts));
ההוספה של WithName נותנת את היכולת להוסיף את שם הפונקציה שבה משתמשים כתאור, כך שאם מישהו עובד עם הקוד רוצה להבין מה מהות הפעולה הוא יוכל לעשות את זה.
אחרי שינוי כל הפונקציות הקובץ יראה ברור יותר כשברור לאן שולח כל נתיב.
public static class ProductsEndPoints
{
public static void MapProducts(this WebApplication app) {
var productGroup = app.MapGroup("products").WithTags("Products");
productGroup.MapGet("", GetAllProducts).WithName(nameof(GetAllProducts));
productGroup.MapGet("{id}", GetProductById).WithName(nameof(GetProductById));
productGroup.MapDelete("{id}", DeleteProduct).WithName(nameof(DeleteProduct));
productGroup.MapPut("{id}", UpdateProduct).WithName(nameof(UpdateProduct));
productGroup.MapPost("", AddNewProduct).WithName(nameof(AddNewProduct));
}
static async Task<Ok<List<Product>>> GetAllProducts(IProductsRepository repo){
var result = await repo.GetAllProducts();
return TypedResults.Ok(result);
}
static async Task<Results<NotFound, Ok<Product>>> GetProductById(int id, IProductsRepository repo){
var result = await repo.GetProductById(id);
if (result == null) {
return TypedResults.NotFound();
}
return TypedResults.Ok(result);
}
static async Task<Results<NotFound, Ok<Product>>> DeleteProduct(int id, IProductsRepository repo) {
var result = await repo.GetProductById(id);
if (result == null) {
return TypedResults.NotFound();
}
await repo.DeleteProduct(id);
return TypedResults.Ok(result);
}
static async Task<Results<NotFound, Ok<Product>>> UpdateProduct(int id, Product product, IProductsRepository repo){
var result = await repo.GetProductById(id);
if (result == null) {
return TypedResults.NotFound();
}
var productAfterUpdate = await repo.UpdateProduct(id, product);
return TypedResults.Ok(productAfterUpdate);
}
static async Task<Created<Product>> AddNewProduct(Product product, IProductsRepository repo) {
Product addProduct = await repo.AddNewProduct(product);
return TypedResults.Created($"api/products/{addProduct.id}", addProduct);
}
}