C# Academy · Lekcja

Tworzenie pierwszego Minimal API

Utwórz projekt Minimal API, zdefiniuj handlery tras i zwracaj typowane wyniki przy minimalnej ilości kodu pomocniczego.

Lekcja 1 z 413 kroki

Tworzenie pierwszego Minimal API to bezpłatna lekcja C# Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej C# Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs C# Academy zawiera 4 lekcji w sumie.

Czym są Minimal APIs

Minimal APIs, wprowadzone w .NET 6, umożliwiają tworzenie endpointów HTTP przy minimalnej liczbie formalności — bez kontrolerów i atrybutów akcji, z procedurami obsługi tras definiowanymi bezpośrednio w pliku Program.cs. Doskonale nadają się do mikrousług i lekkich interfejsów API.

Najprostsze Minimal API

Kompletne API HTTP w zaledwie kilku wierszach. Metody MapGet, MapPost, MapPut i MapDelete definiują procedury obsługi tras dla poszczególnych metod HTTP.

var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();

app.MapGet("/", () => "Hello, Minimal API!");
app.MapGet("/ping", () => Results.Ok(new { status = "pong" }));

app.Run();
// That's it — no Startup.cs, no controllers

Typowane wyniki dla poprawnych odpowiedzi HTTP

Należy używać Results lub TypedResults, aby zwracać poprawne kody stanu HTTP i typy zawartości. TypedResults jest preferowane w celu automatycznego wnioskowania schematu OpenAPI.

app.MapGet("/products/{id}", async (int id, AppDbContext db) =>
{
    var product = await db.Products.FindAsync(id);
    return product is null
        ? Results.NotFound()
        : Results.Ok(product);
});

app.MapPost("/products", async (Product product, AppDbContext db) =>
{
    db.Products.Add(product);
    await db.SaveChangesAsync();
    return Results.Created($"/products/{product.Id}", product);
});

Parametry tras i ciągi zapytania

Parametry tras są pobierane ze ścieżki URL, parametry ciągu zapytania są automatycznie wiązane z zapytaniem, a treść żądania jest deserializowana z formatu JSON.

// Route param {id} + query param ?includeDeleted
app.MapGet("/orders/{id}", async (
    int id,
    bool includeDeleted = false,
    AppDbContext db) =>
{
    var query = db.Orders.AsQueryable();
    if (!includeDeleted) query = query.Where(o => !o.IsDeleted);
    var order = await query.FirstOrDefaultAsync(o => o.Id == id);
    return order is null ? Results.NotFound() : Results.Ok(order);
});

Wstrzykiwanie zależności w procedurach obsługi tras

Usługi zarejestrowane w kontenerze DI można wstrzykiwać bezpośrednio jako parametry procedur obsługi tras. Platforma automatycznie je rozwiązuje.

builder.Services.AddScoped<ProductService>();

app.MapGet("/products", async (ProductService svc) =>
{
    var products = await svc.GetAllAsync();
    return Results.Ok(products);
});

app.MapDelete("/products/{id}", async (int id, ProductService svc) =>
{
    var deleted = await svc.DeleteAsync(id);
    return deleted ? Results.NoContent() : Results.NotFound();
});

Wiązanie treści żądania

Parametry odpowiadające zarejestrowanym usługom są wstrzykiwane, a wszystkie pozostałe są wiązane z treścią żądania, domyślnie w formacie JSON. W razie potrzeby należy jawnie użyć [FromBody].

record CreateProductRequest(string Name, decimal Price, int Stock);

app.MapPost("/products", async (
    CreateProductRequest req,
    ProductService svc) =>
{
    var product = await svc.CreateAsync(req.Name, req.Price, req.Stock);
    return TypedResults.Created($"/products/{product.Id}", product);
});

Zwracanie różnych kodów stanu

Results udostępnia metody fabrykujące dla wszystkich typowych odpowiedzi HTTP. Należy ich używać, aby tworzyć semantycznie poprawne interfejsy REST API.

app.MapPut("/products/{id}", async (int id, Product update, AppDbContext db) =>
{
    var existing = await db.Products.FindAsync(id);
    if (existing is null) return Results.NotFound();

    existing.Name  = update.Name;
    existing.Price = update.Price;
    await db.SaveChangesAsync();
    return Results.Ok(existing);
});

// Other useful Results:
// Results.BadRequest("message")
// Results.Conflict()
// Results.UnprocessableEntity(errors)
// Results.Accepted()

Dodawanie metadanych za pomocą WithName i WithTags

Do endpointów można dołączać metadane, aby usprawnić dokumentację i routing. Należy używać WithName, WithTags i WithSummary w celu uporządkowania danych wyjściowych OpenAPI.

app.MapGet("/products/{id}", GetProduct)
   .WithName("GetProductById")
   .WithTags("Products")
   .WithSummary("Retrieves a product by its ID")
   .Produces<Product>()
   .Produces(404);

static async Task<IResult> GetProduct(int id, AppDbContext db)
{
    var p = await db.Products.FindAsync(id);
    return p is null ? Results.NotFound() : Results.Ok(p);
}

Autoryzacja w Minimal APIs

Należy zastosować RequireAuthorization(), aby chronić endpointy, lub użyć AllowAnonymous(), aby wyłączyć wymaganie autoryzacji. Zasady działają tak samo jak w przypadku kontrolerów.

builder.Services.AddAuthentication().AddJwtBearer();
builder.Services.AddAuthorization();

app.UseAuthentication();
app.UseAuthorization();

app.MapGet("/profile", (ClaimsPrincipal user) =>
    Results.Ok(user.Identity!.Name))
   .RequireAuthorization();

app.MapGet("/public", () => "No auth needed")
   .AllowAnonymous();

Organizowanie za pomocą metod statycznych

W przypadku większych interfejsów API należy przenieść handlery tras do metod statycznych lub metod rozszerzających, aby zachować przejrzystość pliku Program.cs i ułatwić nawigację po nim.

// Extension method groups endpoints by feature
public static class ProductEndpoints
{
    public static void MapProductEndpoints(this WebApplication app)
    {
        app.MapGet("/products",    GetAll);
        app.MapGet("/products/{id}", GetById);
        app.MapPost("/products",   Create);
    }

    private static async Task<IResult> GetAll(AppDbContext db)
        => Results.Ok(await db.Products.AsNoTracking().ToListAsync());

    // ... other handlers
}

// In Program.cs:
app.MapProductEndpoints();

Praktyczny przykład: kompletne Minimal API CRUD

Kompletne Minimal API CRUD dla zasobu Todo — zwięzłe, testowalne i gotowe do wdrożenia produkcyjnego.

app.MapGet("/todos", async (AppDbContext db) =>
    Results.Ok(await db.Todos.AsNoTracking().ToListAsync()));

app.MapGet("/todos/{id}", async (int id, AppDbContext db) =>
{
    var todo = await db.Todos.FindAsync(id);
    return todo is null ? Results.NotFound() : Results.Ok(todo);
});

app.MapPost("/todos", async (Todo todo, AppDbContext db) =>
{
    db.Todos.Add(todo);
    await db.SaveChangesAsync();
    return Results.Created($"/todos/{todo.Id}", todo);
});

app.MapDelete("/todos/{id}", async (int id, AppDbContext db) =>
{
    int n = await db.Todos.Where(t => t.Id == id).ExecuteDeleteAsync();
    return n > 0 ? Results.NoContent() : Results.NotFound();
});

Szybkie sprawdzenie

W jaki sposób handler trasy Minimal API otrzymuje zarejestrowaną usługę DI?

Podsumowanie: tworzenie pierwszego Minimal API

Najważniejsze informacje:

  • MapGet/Post/Put/Delete definiują handlery tras bezpośrednio w pliku Program.cs
  • W celu użycia poprawnych kodów statusu HTTP należy stosować Results / TypedResults
  • Parametry trasy, zapytania, treści żądania i DI są automatycznie wiązane
  • Do obsługi autoryzacji należy używać RequireAuthorization() i AllowAnonymous()
  • Duże interfejsy API należy organizować za pomocą metod rozszerzających lub grup tras
Bezpłatny start

Ucz się C# dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
93
Lekcje
346

Często zadawane pytania

Czy lekcja „Tworzenie pierwszego Minimal API” jest bezpłatna?

Tak — pełny tekst „Tworzenie pierwszego Minimal API” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu C# Academy, przejdź na CoddyKit PRO. Kurs C# Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Tworzenie pierwszego Minimal API”?

Utwórz projekt Minimal API, zdefiniuj handlery tras i zwracaj typowane wyniki przy minimalnej ilości kodu pomocniczego. Ćwiczysz C# Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć C# Academy?

Nie wymagamy żadnego doświadczenia. C# Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Tworzenie pierwszego Minimal API”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji C# Academy?

Tak. Każda lekcja C# Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Tworzenie pierwszego Minimal API
  2. Grupy tras, parametry i walidacja
  3. Middleware i filtry w Minimal APIs
  4. OpenAPI, wersjonowanie i wdrażanie
← Powrót do C# Academy