Parte 4 — Glossary: C# / ASP.NET Core → Angular
Mapare concept-cu-concept între ASP.NET Core MVC (Lab 1-10) și Angular (Lab 11-12). Multe lucruri din Angular au echivalent direct în ce știți deja — această secțiune face „puntea" ca să nu învățați conceptele de la zero.
Mapping conceptual
| În ASP.NET Core / Razor știți | În Angular se cheamă | Notă |
|---|---|---|
class FooController : Controller |
@Component({...}) export class Foo |
clasa cu metadata via decorator |
[Route("/articles")] pe controller |
{ path: 'articles', component: Foo } în app.routes.ts |
routing declarativ, dar pe client |
services.AddScoped<IArticleService, ArticleService>() în Program.cs |
@Injectable({ providedIn: 'root' }) pe clasă |
DI singleton, înregistrare implicită |
public FooController(IArticleService svc) cu constructor injection |
private svc = inject(ArticleService) ca field |
injecție automată, fără constructor |
Task<List<Article>> async method |
Observable<Article[]> din HttpClient |
stream lazy — pornește la .subscribe(), nu la apel |
await _svc.GetAllAsync() |
this.svc.getAll().subscribe(data => ...) |
sintaxă diferită, același flow |
@if (condition) { ... } în Razor |
*ngIf="condition" sau @if (condition) { } |
la fel; *ngIf e clasic, @if e mai nou (v17+) |
@foreach (var x in list) { ... } |
*ngFor="let x of list" sau @for (x of list; track x.id) { } |
la fel; track în @for e ca un key |
@Html.DisplayFor(m => m.Date) cu formatter |
{{ date | date:'dd MMM yyyy' }} (pipe) |
pipe = transformator pe template, înlănțuibile (| filter1 | filter2) |
[Required, MinLength(5)] pe model property |
Validators.required, Validators.minLength(5) în FormBuilder |
aceeași listă de validatori built-in |
if (ModelState.IsValid) { ... } |
if (this.form.valid) { ... } |
același concept, syntax diferit |
<form asp-action="Create"> + [HttpPost] action |
<form [formGroup]="form" (ngSubmit)="onSubmit()"> |
submit handler explicit, FormGroup binding |
<input asp-for="Email" /> |
<input formControlName="email" /> |
binding la control specific |
<span asp-validation-for="Email"> |
<div *ngIf="form.get('email')?.errors"> |
mesaj de eroare per câmp |
ViewBag.Title = "..." sau Layout = "_Layout" |
proprietate pe component (signal) | template direct, fără bag de runtime |
appsettings.json injectat prin IConfiguration |
environment.ts / environment.development.ts |
build replacement, nu read la runtime |
Middleware app.UseCors() |
authInterceptor: HttpInterceptorFn în app.config.ts |
similar concept, dar pe HTTP client (browser), nu server |
[Authorize] pe action sau controller |
canActivate: [authGuard] pe rută |
guard = decide înainte de a randa componenta |
[Authorize(Roles = "Admin")] |
logică manuală în canModify(article) cu currentUser().roles.includes('Admin') |
nu există decorator pe metode în Angular standard |
_logger.LogInformation("...") |
console.log("...") (pentru lab; producție: Sentry, etc.) |
nu există infrastructură de logging built-in |
IConfiguration["ApiKey"] |
environment.apiKey |
static la build, nu dinamic |
_Layout.cshtml cu @RenderBody() |
app.html cu <router-outlet /> |
shell-ul aplicației, ține header/footer comun |
Url.Action("Edit", "Articles", new { id = 5 }) |
routerLink="/articles/5/edit" sau router.navigate(['/articles', 5, 'edit']) |
navigare declarativă sau programatică |
RedirectToAction("Index") din action |
this.router.navigate(['/articles']) |
navigare după success |
partial views (@Html.Partial(...)) |
sub-componente injectate cu <app-x /> |
reuse de UI |
Conceptul nou — Signals (nu ai echivalent direct în C#)
signal() e singurul concept Angular care nu există în ASP.NET Core standard. Cel mai apropiat echivalent: INotifyPropertyChanged din WPF/MAUI/desktop XAML — „o proprietate care anunță automat când se schimbă, ca UI-ul să se actualizeze". Dar Angular face mult mai puțină ceremonie:
// Creezi:
count = signal(0);
items = signal<string[]>([]);
// Citești (cu paranteze — e o funcție):
this.count(); // returnează valoarea curentă
const len = this.items().length;
// Scrii (notifică automat consumatorii):
this.count.set(5);
this.count.update(v => v + 1);
this.items.update(arr => [...arr, 'nou']);
În template:
<p>Count: {{ count() }}</p>
<div *ngIf="count() > 0">Avem date</div>
Când scrii count() în template, Angular reține: „acest binding depinde de signal-ul count; când se schimbă, re-randez doar partea asta". Identic conceptual cu OnPropertyChanged din WPF, doar că Angular îl tracking-uiește automat — nu scrii cod manual.
Echivalent WPF/MAUI mental model:
// WPF cu INotifyPropertyChanged
private int _count;
public int Count
{
get => _count;
set { _count = value; OnPropertyChanged(nameof(Count)); }
}
vs Angular:
count = signal(0); // toata munca de mai sus, intr-o linie
Table of Contents Angular minimal (10 concepte)
Tot ce ai nevoie să înțelegi din Angular pentru lab 11-12, în 10 puncte:
-
Component — clasă cu template HTML + CSS, decorată cu
@Component({...}). Toate sunt standalone (își declară singureimports-urile). E echivalent cu Controller + View combinat într-un singur loc. -
Service — clasă injectabilă, singleton la nivel de aplicație.
@Injectable({providedIn: 'root'}). Echivalent cu serviciile dinProgram.cscuAddScoped. -
DI cu
inject()— în loc de constructor.private svc = inject(ArticleService)ca field. Same concept, syntax mai concis. -
Signals — primitivul de stare reactivă.
signal(),.set(),.update(), citire cu(). Nu există în C# standard. -
HttpClient — face request-uri, returnează
Observable<T>. Echivalent cuHttpClientdin .NET, dar întoarce stream (Observable) în loc deTask. -
Router — URL → component map, definit în
app.routes.ts.RouterLinkdirective e caasp-actiondin MVC. -
Reactive Forms (
FormBuilder,FormGroup,Validators) — formulare cu validare declarativă în TS. Echivalent cu ModelState + DataAnnotations, dar pe client. -
Pipes (
| date,| async,| slice,| uppercase) — transformări în template. Echivalent cu format providers / display templates din Razor. -
Interceptors funcționali — middleware pe HTTP client (browser side). Atașează automat
Authorization: Bearer <token>la fiecare request, similar conceptual cu middleware-ul dinapp.UseAuthentication()(dar pe client). -
Guards funcționali — middleware pe routing.
canActivate: [authGuard]decide dacă utilizatorul are voie să intre pe rută. Echivalent cu[Authorize]dar pe client (UX guard, nu securitate — backend-ul tot verifică).
Atât. Restul sunt convenții de naming, folder structure, RxJS operators (instrumente pentru manipularea Observable-elor). Conceptele de bază sunt finite — sub 10 piese mari, restul e detail.
Ghid de translatare pentru când scrii cod Angular
Când scrii ceva nou, întreabă-te: „În ASP.NET Core cum aș face asta?" Apoi mapează:
- Am nevoie să afișez ceva pe pagină → component cu template HTML (cu
*ngIf/*ngForca în Razor) - Am nevoie de date de la API → service cu
HttpClient, component îl injectează cuinject() - Am nevoie de form cu validare →
FormBuilderîn component,Validators.X(la fel ca DataAnnotations), template cu[formGroup] - Am nevoie să schimb pagina →
router.navigate(['/...'])(programmatic) saurouterLink="/..."(declarativ) - Am nevoie să restricționez accesul → guard funcțional pe rută (
canActivate: [authGuard]) - Am nevoie să atașez ceva la fiecare request → interceptor funcțional în
app.config.ts - Am nevoie de state care se schimbă și UI-ul să se update-eze →
signal()în component - Am nevoie de configurări per environment →
environment.ts(prod) vsenvironment.development.ts(dev)
Această secțiune e dictionar. Cheatsheet-ul de mai jos (Parte 5) are sintaxă API exactă.