1. Can you explain the key differences between ASP.NET MVC and ASP.NET Core?
Answer: ASP.NET MVC and ASP.NET Core are both frameworks for building web applications, but they have some key differences:
- Platform Support: ASP.NET MVC is part of the .NET Framework and is primarily designed for Windows-based applications. ASP.NET Core is cross-platform, meaning it can run on Windows, Linux, and macOS.
- Modularity: ASP.NET Core is more modular compared to ASP.NET MVC. It has a more lightweight, flexible framework with built-in dependency injection, and developers can include only the components they need.
- Performance: ASP.NET Core has been designed with performance in mind and generally offers better performance than ASP.NET MVC due to its optimizations and improvements.
- Hosting: ASP.NET Core applications can be hosted on IIS, Kestrel, or self-hosted, providing greater flexibility. ASP.NET MVC applications are primarily hosted on IIS.
- Configuration: ASP.NET Core uses a more modern configuration system, including JSON-based configuration files and environment-specific settings, whereas ASP.NET MVC traditionally uses XML-based
web.config
files.
2. How does dependency injection work in ASP.NET Core?
Answer: Dependency Injection (DI) is a design pattern used to implement Inversion of Control (IoC), allowing objects to be injected into a class rather than the class creating the objects. ASP.NET Core has built-in support for DI, which simplifies and standardizes the process.
- Registration: Services are registered in the
ConfigureServices
method ofStartup.cs
. You can register services with different lifetimes (Transient, Scoped, Singleton).csharpCopy codepublic void ConfigureServices(IServiceCollection services) { services.AddTransient<IMyService, MyService>(); services.AddScoped<IOtherService, OtherService>(); services.AddSingleton<ISingletonService, SingletonService>(); }
- Injection: Services are injected into controllers, middlewares, or other classes via constructor injection.csharpCopy code
public class MyController : Controller { private readonly IMyService _myService; public MyController(IMyService myService) { _myService = myService; } public IActionResult Index() { // Use _myService } }
- Lifetime Management:
- Transient: Created each time they are requested.
- Scoped: Created once per request.
- Singleton: Created once and shared throughout the application’s lifetime.
3. What are some key features of Angular that make it suitable for building single-page applications (SPAs)?
Answer: Angular offers several features that make it a powerful framework for building SPAs:
- Two-Way Data Binding: Angular’s two-way data binding ensures that changes in the UI automatically update the underlying data model and vice versa, streamlining the development of dynamic UIs.
- Component-Based Architecture: Angular’s component-based architecture helps in building modular, reusable UI components that can be easily managed and tested.
- Routing: Angular’s built-in routing module allows developers to create a SPA with multiple views and navigation without requiring a full-page reload.
- Dependency Injection: Angular’s DI system simplifies the management of dependencies and promotes code modularity and testability.
- RxJS: Angular uses RxJS for reactive programming, enabling developers to work with asynchronous data streams effectively.
- Angular CLI: The Angular Command Line Interface (CLI) provides tools for generating components, services, and other elements, as well as for managing the build process.
4. How do you handle error handling in an Angular application?
Answer: Error handling in Angular involves several strategies:
- Component-Level Error Handling: Use
try-catch
blocks within component methods to catch and handle errors that occur during the execution of functions.typescriptCopy codesomeMethod() { try { // Code that might throw an error } catch (error) { // Handle error } }
- Service-Level Error Handling: In Angular services, you can use RxJS operators such as
catchError
to handle errors from HTTP requests.typescriptCopy codeimport { catchError } from 'rxjs/operators'; import { throwError } from 'rxjs'; getData() { return this.http.get('api/data').pipe( catchError(error => { console.error('Error occurred:', error); return throwError(error); }) ); }
- Global Error Handling: Implement an
ErrorHandler
class to handle errors globally across the application.typescriptCopy codeimport { ErrorHandler } from '@angular/core'; export class GlobalErrorHandler implements ErrorHandler { handleError(error: any): void { console.error('Global error occurred:', error); // Log error to an external server or service } }
Register the global error handler inAppModule
:typescriptCopy codeimport { NgModule } from '@angular/core'; @NgModule({ providers: [{ provide: ErrorHandler, useClass: GlobalErrorHandler }] }) export class AppModule {}
5. What is the purpose of ngOnInit
in Angular?
Answer: ngOnInit
is a lifecycle hook in Angular that is called after Angular has initialized all data-bound properties of a directive or component. It is used for component initialization and is a good place to perform setup tasks such as fetching data, initializing properties, or setting up subscriptions.
typescriptCopy codeimport { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-example',
templateUrl: './example.component.html'
})
export class ExampleComponent implements OnInit {
data: any;
constructor(private dataService: DataService) {}
ngOnInit(): void {
this.dataService.getData().subscribe(result => {
this.data = result;
});
}
}
6. How do you implement form validation in Angular?
Answer: Angular provides robust support for form validation through both template-driven and reactive forms:
- Template-Driven Forms: Use Angular’s built-in validators within template-driven forms by adding validation attributes to form controls.htmlCopy code
<form #form="ngForm"> <input name="username" ngModel required minlength="4"> <div *ngIf="form.submitted && form.controls.username.errors?.required"> Username is required. </div> <button type="submit">Submit</button> </form>
- Reactive Forms: Use
FormGroup
,FormControl
, andValidators
from@angular/forms
to build and manage forms programmatically.typescriptCopy codeimport { FormBuilder, FormGroup, Validators } from '@angular/forms'; export class MyComponent implements OnInit { myForm: FormGroup; constructor(private fb: FormBuilder) {} ngOnInit(): void { this.myForm = this.fb.group({ username: ['', [Validators.required, Validators.minLength(4)]] }); } onSubmit(): void { if (this.myForm.valid) { // Handle form submission } } }
7. How would you handle asynchronous operations in Angular?
Answer: Asynchronous operations in Angular are typically handled using RxJS observables. Here’s how you can manage asynchronous tasks:
- HTTP Requests: Use Angular’s
HttpClient
to perform asynchronous HTTP operations.typescriptCopy codeimport { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; export class DataService { constructor(private http: HttpClient) {} getData(): Observable<Data> { return this.http.get<Data>('api/data'); } }
- Subscriptions: Subscribe to observables to handle the response and manage asynchronous data.typescriptCopy code
import { Component, OnInit } from '@angular/core'; import { DataService } from './data.service'; @Component({ selector: 'app-data', templateUrl: './data.component.html' }) export class DataComponent implements OnInit { data: any; constructor(private dataService: DataService) {} ngOnInit(): void { this.dataService.getData().subscribe(result => { this.data = result; }); } }
- Async Pipe: Use Angular’s
async
pipe in templates to automatically subscribe to observables and manage the subscription lifecycle.htmlCopy code<div *ngIf="dataService.getData() | async as data"> {{ data | json }} </div>
These questions and answers cover a range of important topics for a developer working with ASP.NET, C#, and Angular, and they should help in preparing for interviews or deepening your understanding of these technologies.