Showing posts with label TypeScript. Show all posts
Showing posts with label TypeScript. Show all posts

Wednesday, 24 December 2025

The Full Stack Guide: Connecting Angular with a .NET Backend

Full Stack Banner
The Full Stack Guide: Connecting Angular with .NET

Bridging the frontend and backend for a seamless application

The combination of Angular on the frontend and ASP.NET Core on the backend is a classic enterprise stack. It offers type safety across the board (TypeScript & C#), high performance, and robust tooling. But how do you connect them effectively beyond a simple "Hello World"?

In this guide, we will walk through the full lifecycle: Authentication, CRUD operations, and Handling Errors gracefully.

1. Secure Communication: JWT Authentication

Stateful sessions are out; Stateless Tokens are in. JSON Web Tokens (JWT) are the standard for securing Single Page Applications (SPAs).

JWT Flow Diagram

The Handshake: Login once, access everywhere.

The Interceptor Pattern

Instead of manually adding the `Authorization` header to every single HTTP request, use an Angular Interceptor to attach the token automatically.

// auth.interceptor.ts
export const authInterceptor: HttpInterceptorFn = (req, next) => {
  const token = localStorage.getItem('auth_token');
  
  if (token) {
    const cloned = req.clone({
      setHeaders: { Authorization: `Bearer ${token}` }
    });
    return next(cloned);
  }
  
  return next(req);
};

2. Sending Data: The POST Request

Fetching data is easy, but sending it requires validation. Here is how to handle a form submission with error handling.

// product.service.ts
createProduct(product: Product): Observable<Product> {
  return this.http.post<Product>(this.apiUrl, product).pipe(
    catchError(this.handleError)
  );
}

On the backend, your Controller action returns a CreatedAtAction result to follow REST standards:

// ProductsController.cs
[HttpPost]
public async Task<ActionResult<Product>> Create(ProductDto dto) {
    var product = await _service.AddAsync(dto);
    return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}

Step 3: Global Error Handling

When the backend explodes, the frontend shouldn't freeze. You need a centralized way to catch errors and show notifications.

Error Handling Flow

Graceful Degradation: Turning crashes into user-friendly alerts.

// error.interceptor.ts
export const errorInterceptor: HttpInterceptorFn = (req, next) => {
  const toastService = inject(ToastService);
  
  return next(req).pipe(
    catchError((error: HttpErrorResponse) => {
      if (error.status === 401) {
        toastService.error('Session expired. Please login again.');
      } else {
        toastService.error('Something went wrong. Try again later.');
      }
      return throwError(() => error);
    })
  );
};

Conclusion

Connecting Angular and .NET is about more than just fetching JSON. By implementing Interceptors for Auth and Errors, and following REST standards for CRUD, you build a robust "Full Stack" ecosystem that is secure and scalable.

Getting Started with Angular 17+: Signals & Standalone Components

Angular 17+ Banner
Getting Started with Angular 17+: Signals & Standalone Components

Master the modern Angular renaissance with Signals and Standalone APIs

Angular has been reborn. With version 17 and beyond, the framework has introduced its most significant changes in years. Gone are the days of mandatory NgModules and complex change detection zones. Enter Signals for reactive state management and Standalone Components for a lighter, faster architecture.

This renaissance isn't just a syntax polish—it's a fundamental shift in how we build web applications. In this comprehensive guide, we will explore:

  • Why Signals are replacing Zone.js for change detection.
  • How to migrate from modules to Standalone Components.
  • The new built-in Control Flow syntax.
  • How to use Deferrable Views for instant performance wins.

1. The Rise of Standalone Components

For years, Angular developers had to bundle everything into NgModules. While powerful, it added boilerplate and made the learning curve steep. Standalone components remove this layer, allowing components to manage their own dependencies directly.

Migration to Standalone

From Monoliths to Modular Bricks: Breaking dependencies free.

How to Create a Standalone Component

import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';

@Component({
  selector: 'app-user-profile',
  standalone: true,
  imports: [CommonModule], // Import what you need, right here.
  template: `
    <div class="profile">
      <h1>User Profile</h1>
    </div>
  `
})
export class UserProfileComponent {}

💡 Migration Tip: You don't have to rewrite everything overnight. Angular allows you to mix Standalone Components with existing NgModules, enabling a gradual "strangler fig" migration pattern.

2. Signals: A New Era of Reactivity

Signals are Angular's new reactive primitive. They provide granular tracking of state changes, which enables Angular to update only exactly what changed, potentially removing the need for Zone.js in the future.

Angular Signals Diagram

The Reactive Graph: Signals propagate changes instantly and efficiently.

Why Signals? (Vs RxJS)

RxJS is powerful but complex. Signals are synchronous and glitch-free by design. They are perfect for managing local component state, while RxJS remains the king of asynchronous events (like HTTP requests).

Basic Signal Usage

import { Component, signal, computed, effect } from '@angular/core';

@Component({ ... })
export class CounterComponent {
  // 1. Writable Signal
  count = signal(0);

  // 2. Computed Signal (Updates automatically when 'count' changes)
  doubleCount = computed(() => this.count() * 2);

  constructor() {
    // 3. Effect (Runs whenever dependencies change)
    effect(() => {
      console.log(`The current count is: ${this.count()}`);
    });
  }

  increment() {
    // Update the signal
    this.count.update(val => val + 1);
  }
}

In your template, you access the value by calling the signal as a function: {{ count() }}. This function call tells Angular exactly where this data is used, allowing for fine-grained updates.

3. New Control Flow Syntax

Angular 17 also introduced a built-in control flow syntax that replaces the directives *ngIf and *ngFor. It's more intuitive, requires less boilerplate, and improves type checking.

Old vs. New

<!-- Old Way (Directives) -->
<div *ngIf="isLoggedIn; else loginTemplate">
  Welcome User!
</div>
<ng-template #loginTemplate>Please Login</ng-template>

<!-- New Way (Built-in Syntax) -->
@if (isLoggedIn) {
  <div>Welcome User!</div>
} @else {
  <div>Please Login</div>
}

4. Deferrable Views (@defer)

One of the coolest new performance features is @defer. It allows you to lazy-load a chunk of your template without complex routing configurations.

@defer (on viewport) {
  <app-heavy-chart />
} @placeholder {
  <div>Loading chart...</div>
}

In this example, the code for <app-heavy-chart> isn't even downloaded until the user scrolls down and sees the placeholder. This can dramatically improve initial load times.

Conclusion

Angular 17+ represents a massive leap forward in developer experience. By adopting Standalone Components and Signals, you can write cleaner, more performant applications with less boilerplate code. The future of Angular is bright, reactive, and zone-less!

The Full Stack Guide: Connecting Angular with a .NET Backend

The Full Stack Guide: Connecting Angular with .NET ...