Trudny / egzaminacyjny · lekcja 12
ASP.NET Core jako backend dla Angular — Web API i CORS
Masz już gotowy frontend w Angularze (lekcje 9-11) i wiesz, jak budować backend w ASP.NET Core (lekcje 3, wcześniejsze doświadczenia). Czas je POŁĄCZYĆ. Backend, który komunikuje się z frontendem SPA, nie zwraca gotowego HTML — zwraca WYŁĄCZNIE dane (najczęści...
Zacznij tutaj
Po co się tego uczymy?
Wprowadzenie
Teoria
Kontroler API dziedziczy po ControllerBase (nie po Controller, który dodatkowo obsługuje widoki HTML — Web API ich nie potrzebuje, bo cały interfejs buduje Angular). Atrybut [ApiController] nad klasą włącza automatyczną walidację modelu (jeśli dane są niepoprawne, ASP.NET Core SAM zwraca błąd 400, zanim kod w ogóle wejdzie do metody) i inne usprawnienia typowe dla API.
Atrybuty routingu HTTP — każda akcja jawnie deklaruje metodę HTTP, którą obsługuje:
| Atrybut | Metoda HTTP | Typowe zastosowanie |
|---|---|---|
[HttpGet] | GET | pobranie danych (lista albo pojedynczy element) — wywoływane przez Angular HttpClient.get() |
[HttpPost] | POST | utworzenie nowego zasobu — HttpClient.post() |
[HttpPut("{id}")] | PUT | pełna aktualizacja — HttpClient.put() |
[HttpDelete("{id}")] | DELETE | usunięcie — HttpClient.delete() |
CORS (Cross-Origin Resource Sharing) — dlaczego jest KONIECZNY w tym układzie. Twój Angular działa (podczas developmentu) pod adresem http://localhost:4200, a backend ASP.NET Core pod zupełnie INNYM adresem/portem (np. https://localhost:7042). Przeglądarka ze WZGLĘDÓW BEZPIECZEŃSTWA domyślnie BLOKUJE żądania JavaScript/TypeScript do INNEJ domeny/portu niż ta, z której strona została załadowana — to mechanizm CORS. Backend musi JAWNIE zezwolić na żądania z adresu Angulara: builder.Services.AddCors(opt => opt.AddPolicy("AngularApp", p => p.WithOrigins("http://localhost:4200").AllowAnyMethod().AllowAnyHeader())); oraz app.UseCors("AngularApp");. Bez tej konfiguracji Angular dostanie błąd w konsoli przeglądarki, mimo że backend "działa poprawnie" (bo problem jest po stronie reguł bezpieczeństwa przeglądarki, nie samego API).
Typy zwracane — ActionResult<T>. Ok(dane) (200, z danymi), NotFound() (404), BadRequest("komunikat") (400), CreatedAtAction(...) (201, po udanym POST) — te same kody odpowiedzi HTTP, które sprawdzasz po stronie Angulara w bloku .subscribe() albo try/catch przy async/await.
Konsumpcja API z Angulara — HttpClient. Angular ma wbudowaną usługę HttpClient (wstrzykiwaną przez konstruktor, dokładnie jak serwisy z lekcji 10) do wysyłania żądań HTTP: this.http.get<Produkt[]>('https://localhost:7042/api/produkty') zwraca Observable (strumień danych w czasie — koncepcja z biblioteki RxJS, używanej wewnętrznie przez Angular) — subskrybujesz go metodą .subscribe(dane => { ... }), żeby odebrać dane, gdy faktycznie dotrą z serwera.
Testowanie API narzędziem Postman (z lekcji 2) — zanim frontend Angular zacznie korzystać z Twojego API, warto samodzielnie sprawdzić w Postmanie, czy każdy endpoint zwraca oczekiwane dane.
Zobacz zależności
Schemat
Żądanie GET /api/produkty
│
▼
ProduktyApiController.GetWszystkie() [HttpGet]
│
▼
context.Produkty.ToListAsync()
│
▼
return Ok(produkty); → odpowiedź JSON: [{"id":1,"nazwa":"...","cena":89.99}, ...]
Żądanie POST /api/produkty (treść: JSON nowego produktu)
│
▼
ProduktyApiController.Dodaj(Produkt nowy) [HttpPost]
│
│ [ApiController] AUTOMATYCZNIE waliduje - jeśli błąd, zwraca 400 bez kodu w akcji
▼
context.Produkty.Add(nowy); SaveChangesAsync();
│
▼
return CreatedAtAction(nameof(Pobierz), new { id = nowy.Id }, nowy); → 201 Created
Klient (JavaScript fetch / aplikacja MAUI HttpClient / Postman)
│
▼
odbiera odpowiedź JSON, przetwarza dalej
Połącz z praktyką
Przykład z życia
Aplikacja sklepowa w Angularze wyświetla listę produktów pobraną z Twojego własnego backendu ASP.NET Core — dokładnie ten sam mechanizm REST API, którego aplikacja MAUI używała jako klient w dziale mobilnym (HttpClient po stronie C#), tylko teraz klientem jest Angular (HttpClient po stronie TypeScript), a Ty budujesz OBIE strony tej komunikacji.