update introducery sessions notes
This commit is contained in:
@@ -1,47 +1,291 @@
|
||||
# Part 1: Basics of a Webpage
|
||||
# Session 0: Controllers, Routing, and Return Types
|
||||
|
||||
**Topics Covered:**
|
||||
## 📝 Overview
|
||||
|
||||
- **HTML:** Learn how to structure your webpage using HTML, the backbone of all web pages.
|
||||
https://www.w3schools.com/html/default.asp
|
||||
- **CSS:** Understand how to style your webpage with CSS to make it visually appealing.
|
||||
https://www.w3schools.com/css/default.asp
|
||||
- JavaScript
|
||||
https://www.w3schools.com/js/default.asp
|
||||
In this session, we’ll cover the following concepts:
|
||||
|
||||
![[Pasted image 20241022115013.png]]
|
||||
- MVC pattern in ASP.NET Core
|
||||
- Controllers and their structure
|
||||
- Default and attribute-based routing
|
||||
- Handling various HTTP requests (GET, POST, DELETE)
|
||||
- Return types from controllers
|
||||
- Building a real-world Product flow
|
||||
- Mini project assignment
|
||||
|
||||
## 📚 Topics Covered
|
||||
|
||||
### ✅ MVC Architecture
|
||||
|
||||
> Learn how the Model-View-Controller (MVC) architecture separates concerns in a web application.
|
||||
> 🔗 [Microsoft Docs - MVC Pattern](https://learn.microsoft.com/en-us/aspnet/core/mvc/overview)
|
||||
|
||||
### ✅ Controllers and Actions
|
||||
|
||||
> Understand how to create controllers and action methods, follow naming conventions, and return data to views.
|
||||
> 🔗 [w3schools - MVC Controllers](https://www.w3schools.com/asp/asp_net_mvc_intro.asp)
|
||||
|
||||
### ✅ Routing in ASP.NET Core
|
||||
|
||||
> Understand how ASP.NET Core maps incoming requests to the appropriate controller and action using default and custom routing.
|
||||
> 🔗 [Microsoft Docs - Routing](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing)
|
||||
|
||||
### ✅ HTTP Methods in MVC
|
||||
|
||||
> Learn how to respond to different types of HTTP requests using attributes like `[HttpGet]`, `[HttpPost]`.
|
||||
> 🔗 [HTTP Methods - MDN](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods)
|
||||
|
||||
### ✅ Return Types
|
||||
|
||||
> Explore different return types like `ViewResult`, `JsonResult`, and more, and know when to use each one.
|
||||
> 🔗 [Action Results in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/actions)
|
||||
|
||||
## 📌 Notes
|
||||
|
||||
> _Collected from various sources including W3Schools, Microsoft Docs, and ChatGPT_
|
||||
|
||||
---
|
||||
|
||||
# Part 2: Introduction to .NET and `C#`
|
||||
https://www.w3schools.com/cs/cs_properties.php
|
||||
### **1. Start with the Basics: Understanding MVC Architecture**
|
||||
|
||||
**Topics Covered:**
|
||||
**Goal**: Give a quick overview of the MVC pattern, focusing on the role of controllers.
|
||||
|
||||
- **Understanding .NET:** Explore the .NET framework and its role in modern web development.
|
||||
- **C# Basics:** Get hands-on experience with the C# language, its syntax, and structure.
|
||||
- ✅ **Explain MVC**:
|
||||
|
||||
**Explaining Properties in C#:** Properties are a key part of working with models in C#. They act as accessors to the class's data. You’ll learn how to use properties to get and set values in a way that maintains encapsulation.
|
||||
- **Model**: Manages data and business logic.
|
||||
- **View**: Handles UI.
|
||||
- **Controller**: Acts as the intermediary, processing requests and returning responses.
|
||||
|
||||
Example:
|
||||
- ✅ **Controller’s Role**:
|
||||
Handles incoming HTTP requests, decides which logic to execute, and returns the appropriate result (usually a view or data).
|
||||
|
||||
```c#
|
||||
public class Product
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
- ✅ **Activity**:
|
||||
Create a “Hello World” ASP.NET Core MVC app and show the default routing behavior (`HomeController` with `Index` action).
|
||||
|
||||
---
|
||||
|
||||
### **2. Controllers: Structure, Naming, and Basics**
|
||||
|
||||
**Goal**: Help students understand how to structure and create controllers, and introduce them to actions.
|
||||
|
||||
- ✅ **Creating a Simple Controller**:
|
||||
|
||||
- Use Visual Studio to add a new controller.
|
||||
- Controller classes must:
|
||||
- Be `public`
|
||||
- Inherit from `Controller`
|
||||
- Have `Controller` as a suffix in their name (e.g., `ProductController`).
|
||||
|
||||
- ✅ **Basic Action Methods**:
|
||||
- Action methods must be `public`.
|
||||
- Default return type is usually `IActionResult`.
|
||||
|
||||
````csharp
|
||||
public class ProductController : Controller {
|
||||
public IActionResult Index() {
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Details(int id) {
|
||||
var product = new Product { Id = id, Name = "Sample Product", Price = 25.00m };
|
||||
return View(product);
|
||||
}
|
||||
}
|
||||
|
||||
- ✅ **Activity**:
|
||||
Create your own `CustomerController` with an `Index` and a `Details` action.
|
||||
|
||||
|
||||
---
|
||||
|
||||
### **3. Routing Basics: Default Routing and Attribute-Based Routing**
|
||||
|
||||
**Goal**: Teach students how routing works in ASP.NET Core, from default routing to custom attribute routing.
|
||||
|
||||
- ✅ **Default Route Configuration**:
|
||||
Defined in `Program.cs`:
|
||||
|
||||
|
||||
```csharp
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
````
|
||||
|
||||
- `{controller=Home}`: Default controller
|
||||
- `{action=Index}`: Default action
|
||||
- `{id?}`: Optional parameter
|
||||
- ✅ **Customizing Routes**:
|
||||
- You can modify the pattern in `Program.cs`.
|
||||
- Example: Use `"{controller=Product}/{action=List}/{id?}"` to change defaults.
|
||||
- ✅ **Attribute-Based Routing**:
|
||||
- Useful for APIs or when you want specific paths.
|
||||
|
||||
```csharp
|
||||
[Route("product")]
|
||||
public class ProductController : Controller {
|
||||
[HttpGet("list")]
|
||||
public IActionResult List() {
|
||||
return View();
|
||||
}
|
||||
|
||||
[HttpGet("{id:int}")]
|
||||
public IActionResult Details(int id) {
|
||||
return View();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- 🔲 **Activity**:
|
||||
Add routes to your `CustomerController`:
|
||||
- `[HttpGet("all")]` to show all customers
|
||||
- `[HttpGet("{id}")]` to show customer details
|
||||
|
||||
---
|
||||
|
||||
# Part 3: Basics of MVC Architecture
|
||||
### **4. Controllers and Actions: Handling Different HTTP Requests**
|
||||
|
||||
**Goal**: Show how controllers handle various HTTP methods.
|
||||
|
||||
https://www.geeksforgeeks.org/mvc-design-pattern/
|
||||
**What is MVC?** MVC (Model-View-Controller) is a design pattern used for developing web applications. It separates the application into three interconnected components
|
||||
- ✅ **HTTP Verbs**:
|
||||
- **GET**: Retrieve data
|
||||
- **POST**: Submit data
|
||||
- **PUT**: Update data
|
||||
- **DELETE**: Remove data
|
||||
- ✅ **HTTP-Specific Attributes**:
|
||||
- Use `[HttpGet]`, `[HttpPost]`, `[HttpPut]`, `[HttpDelete]` to restrict access.
|
||||
|
||||
1. **Model:** Represents the data and the business logic.
|
||||
2. **View:** Handles the display of information (HTML, CSS, Razor Pages).
|
||||
3. **Controller:** Handles user interaction and updates both the model and view.
|
||||
![[Pasted image 20241022113251.png]]
|
||||
```csharp
|
||||
public class ProductController : Controller {
|
||||
[HttpGet]
|
||||
public IActionResult List() { return View(); }
|
||||
|
||||
[HttpPost]
|
||||
public IActionResult Create(Product product) {
|
||||
// Save to DB
|
||||
return RedirectToAction("List");
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
public IActionResult Delete(int id) {
|
||||
// Remove from DB
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- 🔲 **Activity**:
|
||||
Add full CRUD actions to `CustomerController`, using appropriate HTTP verbs and routing.
|
||||
|
||||
---
|
||||
|
||||
### **5. Return Types: Exploring Different Return Options in Controllers**
|
||||
|
||||
**Goal**: Familiarize students with different return types in ASP.NET Core.
|
||||
|
||||
- ✅ **Basic Return Types**:
|
||||
- `ViewResult` → `return View();`
|
||||
- `JsonResult` → `return Json(data);`
|
||||
- `ContentResult` → `return Content("Text");`
|
||||
- ✅ **When to Use**:
|
||||
- Use `View()` when rendering pages.
|
||||
- Use `Json()` for APIs or AJAX.
|
||||
- Use `Content()` for simple text/plain responses.
|
||||
|
||||
```csharp
|
||||
public class ProductController : Controller {
|
||||
public IActionResult Index() => View();
|
||||
|
||||
public JsonResult GetProductJson(int id) => Json(new { id, name = "Product" });
|
||||
|
||||
public ContentResult GetMessage() => Content("This is a simple text message.");
|
||||
}
|
||||
```
|
||||
|
||||
- ✅ **Advanced Return Types**:
|
||||
- `RedirectToAction("Index")`: Navigate to another action.
|
||||
- `StatusCode(404)`: Return HTTP status codes.
|
||||
- `File()`: Return downloadable content (e.g., PDF, image).
|
||||
- 🔲 **Activity**:
|
||||
Add:
|
||||
- One action returning JSON
|
||||
- One returning text
|
||||
- One redirecting to another action
|
||||
|
||||
---
|
||||
|
||||
### **6. Real-World Application: Creating a Full Flow**
|
||||
|
||||
**Goal**: Connect controllers, models, and views to build something meaningful.
|
||||
|
||||
- ✅ **Create a Model**:
|
||||
|
||||
```csharp
|
||||
public class Product {
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
- ✅ **Controller-Model Interaction**:
|
||||
|
||||
```csharp
|
||||
public IActionResult Details(int id) {
|
||||
var product = new Product {
|
||||
Id = id,
|
||||
Name = "Laptop",
|
||||
Price = 1200.00m
|
||||
};
|
||||
return View(product);
|
||||
}
|
||||
```
|
||||
|
||||
- ✅ **Pass Data to View**:
|
||||
- Use a strongly typed view (`@model Product`)
|
||||
- Display `@Model.Name`, `@Model.Price`, etc.
|
||||
- 🔲 **Activity**:
|
||||
- Create `Product` model
|
||||
- Create `Details` and `List` actions
|
||||
- Create strongly-typed Razor views
|
||||
|
||||
---
|
||||
|
||||
### **7. Practice and Review: Small Project Assignment**
|
||||
|
||||
**Goal**: Reinforce everything learned.
|
||||
|
||||
- ✅ **Project: Product Management App**
|
||||
- CRUD: Create, Read, Update, Delete products
|
||||
- Use default and attribute routing
|
||||
- Return different types (View, JSON, Redirect)
|
||||
- Include HTTP verb handling
|
||||
- ✅ **Suggested Workflow**:
|
||||
1. Create the `Product` model
|
||||
2. Build controller actions
|
||||
3. Set up routing
|
||||
4. Implement Razor views
|
||||
5. Test everything end-to-end
|
||||
- ✅ **Encourage Discussion**:
|
||||
- Why return JSON instead of HTML?
|
||||
- When to use attribute routing?
|
||||
- What's the benefit of redirecting?
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Practice
|
||||
|
||||
- Create a basic MVC Hello World app
|
||||
- Add `ProductController` with sample actions
|
||||
- Use `[Route]` and `[HttpGet]` in `CustomerController`
|
||||
- Implement full CRUD for customers or products
|
||||
- Add JSON, Content, and Redirect examples
|
||||
- Build a simple Product Detail View
|
||||
- Complete mini-project: Product Management App
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
Sources:
|
||||
|
||||
- [w3schools.com](https://www.w3schools.com/)
|
||||
- [Microsoft Learn](https://learn.microsoft.com/en-us/aspnet/core/)
|
||||
- ChatGPT conversations (2025 sessions)
|
||||
|
||||
@@ -1,144 +1,199 @@
|
||||
# Part 0: Roadmap of this Session
|
||||
# Session 1: Working with Models and MVC Basics in ASP.NET Core
|
||||
|
||||
## Getting Started with MVC Projects
|
||||
- [x] Directory Structure: Detailed explanation of the MVC directory
|
||||
- [x] (Controllers, Views, Models, wwwroot) and the role of Program.cs in configuration.
|
||||
- [x] Routing and Controllers: Custom routing, attribute routing, and handling various HTTP requests.
|
||||
- [x] Actions in Controllers: Exploring different return types and handling different HTTP requests.
|
||||
## Controllers and Routing
|
||||
- [x] Routing Basics: Attribute-based routing and custom route parameters.
|
||||
- [x] Controller Actions: How to handle different return types like JSON, HTML, and redirect results.
|
||||
- [x] The address can contain static parts
|
||||
- [ ] How to set the Default Page in ASP
|
||||
## 📝 Overview
|
||||
|
||||
In this session, we’ll cover the following concepts:
|
||||
|
||||
- MVC project structure and configuration
|
||||
- Controllers and routing (including static segments and default page setting)
|
||||
- Introduction to Models in ASP.NET Core
|
||||
- C# OOP essentials: properties, encapsulation, and access modifiers
|
||||
- Passing models (single and list) from controllers to views
|
||||
- Strongly-typed Razor views
|
||||
|
||||
## 📚 Topics Covered
|
||||
|
||||
### ✅ MVC Project Structure & Routing
|
||||
|
||||
> Learn how ASP.NET Core organizes files and configures routes for handling web requests.
|
||||
> 🔗 [Microsoft Docs - MVC Introduction](https://learn.microsoft.com/en-us/aspnet/core/mvc/overview)
|
||||
|
||||
### ✅ C# Properties & OOP Essentials
|
||||
|
||||
> Explore object-oriented programming basics in C#, including properties and encapsulation.
|
||||
> 🔗 [C# OOP Overview](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/tutorials/oop)
|
||||
|
||||
### ✅ Models and Views
|
||||
|
||||
> Understand how to define models and pass them to views in ASP.NET Core MVC.
|
||||
> 🔗 [Microsoft Docs - Work with Data in MVC](https://learn.microsoft.com/en-us/aspnet/core/mvc/models/)
|
||||
|
||||
## 📌 Notes
|
||||
|
||||
> _Collected from various sources including W3Schools, Microsoft Docs, and ChatGPT_
|
||||
|
||||
---
|
||||
|
||||
# Part 1: Understanding Models in ASP.NET Core MVC
|
||||
### 📍 Part 0: Roadmap of This Session
|
||||
|
||||
Models are a fundamental part of the MVC architecture, representing the data structure and logic of your application. They interact with the database and contain properties that hold data and methods that implement business logic.
|
||||
#### ✅ Getting Started with MVC Projects
|
||||
|
||||
### **Model Structure and Purpose**
|
||||
- [x] **Directory Structure**:
|
||||
Learn about the standard folders: `Controllers`, `Views`, `Models`, and `wwwroot`. Understand the role of `Program.cs` in bootstrapping and routing.
|
||||
|
||||
- **Data Representation**: Models define the structure of data (often aligning with database tables).
|
||||
- **Data Handling**: Models encapsulate data manipulation logic, like validation and relationships.
|
||||
- **Data Transport**: Models pass data between the controller and the view.
|
||||
- [x] **Routing and Controllers**:
|
||||
|
||||
In ASP.NET Core MVC, models are typically located in a **Models** folder, and each model represents a specific data entity, like `Product`, `Customer`, or `Order`.
|
||||
- Custom routing using templates like `{controller}/{action}/{id?}`
|
||||
- Attribute routing using `[Route]`, `[HttpGet]`, etc.
|
||||
- Static segments in routes:
|
||||
Example: `[Route("products/all")]` creates `/products/all`.
|
||||
|
||||
- [x] **Actions in Controllers**:
|
||||
|
||||
- Return types like `ViewResult`, `JsonResult`, `ContentResult`
|
||||
- Handle multiple HTTP methods (GET, POST, etc.)
|
||||
|
||||
- 🔲 **How to Set Default Page in ASP.NET Core**
|
||||
_(To do: Discuss how to change the default route in `Program.cs`, e.g. set controller = Products, action = List)_
|
||||
|
||||
---
|
||||
|
||||
# 2. Properties in Models and Object-Oriented Programming (OOP) in `C#`
|
||||
### 📍 Part 1: Understanding Models in ASP.NET Core MVC
|
||||
|
||||
To understand how models work, let’s cover key OOP concepts in C#, which is essential for defining and managing models in ASP.NET Core MVC.
|
||||
Models are a fundamental part of the MVC architecture, representing the **data structure and logic** of your application. They interact with the database and contain properties that hold data and methods that implement business logic.
|
||||
|
||||
### **Properties in C#**
|
||||
#### 🧠 Model Structure and Purpose
|
||||
|
||||
Properties in C# provide a flexible way to access and modify the fields of a class. They use `get` and `set` accessors to control how data is read or assigned.
|
||||
- **Data Representation**: Models reflect real-world data structures, often aligning with database tables.
|
||||
- **Data Handling**: Models encapsulate validation, relationships, and business logic.
|
||||
- **Data Transport**: Used to transfer data between controllers and views.
|
||||
|
||||
Here’s an example of a basic `Product` model with properties:
|
||||
In ASP.NET Core MVC, models are typically stored in a `Models` folder, with one class per entity (`Product`, `Customer`, `Order`, etc.).
|
||||
|
||||
---
|
||||
|
||||
```c#
|
||||
### 📍 Part 2: Properties in Models & C# OOP Concepts
|
||||
|
||||
#### ✅ Properties in C#
|
||||
|
||||
Properties in C# provide a controlled way to access and modify private fields using `get` and `set`.
|
||||
|
||||
````csharp
|
||||
public class Product {
|
||||
|
||||
public int Id { get; set; }
|
||||
// Auto-implemented property
|
||||
public decimal Price { get; set; }
|
||||
public int Id { get; set; } // Auto-property
|
||||
public decimal Price { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
- **Auto-implemented properties** (`Price`): Define a property without explicit backing fields, useful when no custom logic is needed.
|
||||
- **Auto-Implemented Properties**:
|
||||
Simplify property declarations when no extra logic is needed.
|
||||
|
||||
|
||||
### **Encapsulation and Access Modifiers**
|
||||
#### ✅ Encapsulation and Access Modifiers
|
||||
|
||||
Encapsulation in OOP hides the internal state of an object and restricts access to its properties and methods. C# provides access modifiers like `public`, `private`, `protected`, and `internal` to control access.
|
||||
Encapsulation hides the internal workings of a class from the outside world.
|
||||
|
||||
In ASP.NET Core MVC, models typically use **public properties** for easy access from other parts of the application (like controllers and views).
|
||||
- **Access Modifiers**:
|
||||
|
||||
- `public`: Accessible from anywhere
|
||||
|
||||
- `private`: Only inside the class
|
||||
|
||||
- `protected`: Inside the class and derived classes
|
||||
|
||||
- `internal`: Only within the current assembly
|
||||
|
||||
|
||||
**MVC models typically use public properties** so they can be accessed in views and controllers.
|
||||
|
||||
---
|
||||
|
||||
# 3. Passing a Model to a View
|
||||
### 📍 Part 3: Passing a Model to a View
|
||||
|
||||
In ASP.NET Core MVC, data is passed from the controller to the view using models. You can pass a single model, a list of models, or even multiple models in complex scenarios.
|
||||
#### ✅ Step 1: Define the Model
|
||||
|
||||
### **Steps to Pass a Model from Controller to View**
|
||||
|
||||
1. **Define the Model** First, define the model class. Let’s use the `Product` model as our example.
|
||||
|
||||
```c#
|
||||
public class Product
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
```csharp
|
||||
public class Product {
|
||||
public int Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public decimal Price { get; set; }
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
1. **Create a Controller Action** In your controller, create an action that will pass the model data to the view.
|
||||
|
||||
```c#
|
||||
#### ✅ Step 2: Create a Controller Action
|
||||
|
||||
```csharp
|
||||
public class ProductsController : Controller {
|
||||
public IActionResult Details()
|
||||
{
|
||||
var product = new Product{
|
||||
Id = 1,
|
||||
Name = "Laptop",
|
||||
Price = 1500.00m
|
||||
};
|
||||
// Pass the model to the view
|
||||
return View(product);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this example, the `Details` action creates an instance of `Product` and passes it to the view using `View(product);`.
|
||||
|
||||
3. **Strongly-Typed Views** When passing a model to a view, it’s common to make the view "strongly typed" to enable IntelliSense and compile-time checking.
|
||||
|
||||
- Open or create a view for your action (like `Details.cshtml`).
|
||||
|
||||
- At the top of the view, specify the model type with the `@model` directive.
|
||||
|
||||
```
|
||||
@model Product <h2>Product Details</h2> <p>Product Name: @Model.Name</p> <p>Price: @Model.Price</p>
|
||||
```
|
||||
|
||||
|
||||
In this example:
|
||||
|
||||
- `@model Product` specifies that the view expects a `Product` model.
|
||||
- `@Model.Name` and `@Model.Price` retrieve properties of the `Product` instance.
|
||||
|
||||
### **Passing a List of Models**
|
||||
|
||||
To pass a collection of models, define the controller action to return a list and set the view model type accordingly.
|
||||
|
||||
|
||||
```c#
|
||||
public IActionResult List() {
|
||||
var products = new List<Product> {
|
||||
new Product { Id = 1, Name = "Laptop", Price = 1500.00m }, new Product { Id = 2, Name = "Smartphone", Price = 800.00m }
|
||||
};
|
||||
return View(products); }
|
||||
```
|
||||
|
||||
In the `List.cshtml` view:
|
||||
|
||||
|
||||
```c#
|
||||
@model IEnumerable<Product>
|
||||
<h2>Product List</h2>
|
||||
<ul>
|
||||
@foreach (var product in Model)
|
||||
{
|
||||
<li>@product.Name - @product.Price</li>
|
||||
public IActionResult Details() {
|
||||
var product = new Product {
|
||||
Id = 1,
|
||||
Name = "Laptop",
|
||||
Price = 1500.00m
|
||||
};
|
||||
return View(product); // Passing model to view
|
||||
}
|
||||
</ul>
|
||||
}
|
||||
```
|
||||
|
||||
This example uses `IEnumerable<Product>` as the model type to handle a list of `Product` objects.
|
||||
#### ✅ Step 3: Strongly-Typed View (`Details.cshtml`)
|
||||
|
||||
```cshtml
|
||||
@model Product
|
||||
|
||||
<h2>Product Details</h2>
|
||||
<p>Product Name: @Model.Name</p>
|
||||
<p>Price: @Model.Price</p>
|
||||
```
|
||||
|
||||
- `@model` tells Razor this view receives a `Product`
|
||||
- `@Model` gives access to passed data
|
||||
|
||||
---
|
||||
|
||||
### 📍 Passing a List of Models to the View
|
||||
|
||||
#### ✅ Controller Action:
|
||||
|
||||
```csharp
|
||||
public IActionResult List() {
|
||||
var products = new List<Product> {
|
||||
new Product { Id = 1, Name = "Laptop", Price = 1500.00m },
|
||||
new Product { Id = 2, Name = "Smartphone", Price = 800.00m }
|
||||
};
|
||||
return View(products);
|
||||
}
|
||||
```
|
||||
|
||||
#### ✅ View (`List.cshtml`):
|
||||
|
||||
```cshtml
|
||||
@model IEnumerable<Product>
|
||||
|
||||
<h2>Product List</h2>
|
||||
<ul>
|
||||
@foreach (var product in Model) {
|
||||
<li>@product.Name - @product.Price</li>
|
||||
}
|
||||
</ul>
|
||||
```
|
||||
|
||||
- Use `IEnumerable<Product>` to pass lists
|
||||
- Razor supports `foreach` directly on the `Model`
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Practice
|
||||
|
||||
- Explore and explain the MVC folder structure
|
||||
- Create a model class `Product`
|
||||
- Build a controller that returns a single model to a view
|
||||
- Create a strongly-typed Razor view using `@model`
|
||||
- Return a list of `Product` models and display them in a loop
|
||||
- Show how to set the default controller and action in `Program.cs`
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
Sources:
|
||||
|
||||
- [w3schools.com](https://www.w3schools.com/)
|
||||
- [Microsoft Learn](https://learn.microsoft.com/en-us/aspnet/core/)
|
||||
- ChatGPT sessions (2025)
|
||||
|
||||
@@ -1,125 +1,226 @@
|
||||
# Session 2: Middleware, Routing, and Controllers in ASP.NET Core MVC
|
||||
|
||||
## **0. Middleware and Request Pipeline**
|
||||
![[Pasted image 20241105101014.png]]
|
||||
![[Pasted image 20241105111037.png]]
|
||||
## 📝 Overview
|
||||
|
||||
![[Pasted image 20241105111022.png]]
|
||||
In this session, we’ll cover the following concepts:
|
||||
|
||||
## **1. Routing in ASP.NET Core MVC**
|
||||
- Middleware and the ASP.NET Core request pipeline
|
||||
- Routing structure: default, attribute-based, constraints, SEO-friendly
|
||||
- Creating and structuring controllers
|
||||
- Handling HTTP methods
|
||||
- Dependency Injection in controllers
|
||||
- Model binding and action parameters
|
||||
|
||||
Routing is a mechanism to map incoming HTTP requests to specific controller actions. Understanding routing is crucial for managing URL patterns and making your app user-friendly and SEO-optimized.
|
||||
## 📚 Topics Covered
|
||||
|
||||
### **Basic Routing Structure**
|
||||
### ✅ Middleware and Request Pipeline
|
||||
|
||||
Routes in ASP.NET Core are configured in `Program.cs` (or `Startup.cs` in earlier versions) using the `app.MapControllerRoute` method, which defines how URLs map to controllers and actions.
|
||||
> Visual understanding of the middleware flow and pipeline order
|
||||
> 🖼️ _See diagrams in original session notes_
|
||||
|
||||
### **Steps and Key Concepts in Routing**
|
||||
🔗 [ASP.NET Core Middleware Overview](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware/)
|
||||
|
||||
1. **Define a Default Route** The default route defines the basic URL pattern that ASP.NET Core will follow.
|
||||
|
||||
```c#
|
||||
app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
```
|
||||
- **Pattern**:
|
||||
- `{controller=Home}/{action=Index}/{id?}`:
|
||||
- `{controller=Home}`: Specifies the controller, defaulting to `Home`.
|
||||
- `{action=Index}`: Specifies the action method, defaulting to `Index`.
|
||||
- `{id?}`: Optional parameter for passing an `id`.
|
||||
1. **Attribute Routing** Define routes directly within the controller using attributes. This is useful when each action needs a unique route.
|
||||
|
||||
```c#
|
||||
[Route("products")]
|
||||
public class ProductsController : Controller
|
||||
{
|
||||
[HttpGet("all")]
|
||||
public IActionResult GetAllProducts() { /*...*/ }
|
||||
### ✅ Routing in ASP.NET Core
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public IActionResult GetProductById(int id) { /*...*/ }
|
||||
}
|
||||
```
|
||||
1. **Custom Route Parameters and Constraints** You can add custom parameters and enforce constraints directly in the route to manage data types and URL patterns.
|
||||
|
||||
```c#
|
||||
app.MapControllerRoute(name: "custom", pattern: "{controller=Products}/{action=List}/{id:int:min(1)}");
|
||||
```
|
||||
> Learn how incoming requests map to controller actions through routing.
|
||||
> 🔗 [ASP.NET Core Routing Docs](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/routing)
|
||||
|
||||
- **Constraints**: `{id:int:min(1)}` ensures `id` is an integer greater than or equal to 1.
|
||||
- Other constraints include `bool`, `datetime`, `guid`, `minlength(x)`, `maxlength(x)`, and custom regular expressions.
|
||||
### ✅ Controllers
|
||||
|
||||
1. **Setting Default Actions Based on Controller** To give specific controllers a unique default action, create additional routes before the default route.
|
||||
|
||||
```c#
|
||||
app.MapControllerRoute(name: "gallery", pattern: "Gallery/{action=Main}/{id?}",defaults: new { controller = "Gallery" });
|
||||
> Understand how to structure controllers and handle requests with actions.
|
||||
> 🔗 [ASP.NET Core Controllers](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/actions)
|
||||
|
||||
app.MapControllerRoute(name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");
|
||||
```
|
||||
|
||||
1. **SEO-Friendly and Readable URLs** For user-friendly URLs, use meaningful route names instead of parameters. This is particularly useful for e-commerce or content-heavy sites.
|
||||
```c#
|
||||
app.MapControllerRoute(name: "productDetail", pattern: "products/details/{id:int}/{name}");
|
||||
```
|
||||
## 📌 Notes
|
||||
|
||||
This structure allows URLs like `/products/details/10/laptop`, which is clear and keyword-rich.
|
||||
> _Collected from various sources including Microsoft Docs and ChatGPT_
|
||||
|
||||
---
|
||||
|
||||
## **2. Controllers in ASP.NET Core MVC**
|
||||
## 📍 Part 0: Middleware and Request Pipeline
|
||||
|
||||
Controllers are central in ASP.NET Core MVC and handle requests, retrieve data, and determine how it’s returned to the client.
|
||||
🖼️ **Diagrams**:
|
||||
|
||||
### **Controller Basics**
|
||||
- ![[Pasted image 20241105101014.png]]
|
||||
- ![[Pasted image 20241105111037.png]]
|
||||
- ![[Pasted image 20241105111022.png]]
|
||||
|
||||
- **Controller Naming**: Controllers usually end with "Controller" (e.g., `HomeController`, `ProductController`).
|
||||
- **Actions**: Methods within controllers are called action methods, typically returning a response to the user.
|
||||
---
|
||||
|
||||
### **Steps and Key Concepts in Controllers**
|
||||
## 📍 Part 1: Routing in ASP.NET Core MVC
|
||||
|
||||
1. **Creating a Basic Controller** A controller inherits from the `Controller` base class and contains action methods.
|
||||
|
||||
```c#
|
||||
public class HomeController : Controller
|
||||
{
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
```
|
||||
Routing maps incoming HTTP requests to controller actions.
|
||||
|
||||
1. **Handling HTTP Methods with Attributes** Controllers use HTTP attributes like `[HttpGet]`, `[HttpPost]`, `[HttpPut]`, and `[HttpDelete]` to specify which HTTP methods they handle.
|
||||
|
||||
```c#
|
||||
[HttpPost]
|
||||
public IActionResult CreateProduct(Product product)
|
||||
{
|
||||
//Handle POST request
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
```
|
||||
|
||||
3. **Using Dependency Injection in Controllers** Dependency injection is commonly used in ASP.NET Core to inject services (like a repository) into controllers, supporting clean code and testability.
|
||||
|
||||
```c#
|
||||
public class ProductsController : Controller
|
||||
{
|
||||
private readonly IProductRepository _repository;
|
||||
public ProductsController(IProductRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
### ✅ Basic Routing Structure
|
||||
|
||||
1. **Defining Action Parameters** Parameters passed to action methods are automatically bound from the URL or query string. Use model binding to parse complex objects from the request body.
|
||||
|
||||
|
||||
```c#
|
||||
public IActionResult EditProduct(int id, string name) {
|
||||
// Parameters are bound from the URL }
|
||||
```
|
||||
Routing is configured in `Program.cs` via `app.MapControllerRoute`.
|
||||
|
||||
````csharp
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}"
|
||||
);
|
||||
|
||||
- `{controller=Home}`: default controller
|
||||
|
||||
- `{action=Index}`: default action
|
||||
|
||||
- `{id?}`: optional URL parameter
|
||||
|
||||
|
||||
---
|
||||
|
||||
### ✅ Attribute Routing
|
||||
|
||||
Define routes directly in the controller using attributes:
|
||||
|
||||
```csharp
|
||||
[Route("products")]
|
||||
public class ProductsController : Controller
|
||||
{
|
||||
[HttpGet("all")]
|
||||
public IActionResult GetAllProducts() { /*...*/ }
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public IActionResult GetProductById(int id) { /*...*/ }
|
||||
}
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
### ✅ Route Parameters & Constraints
|
||||
|
||||
You can enforce patterns and types using constraints:
|
||||
|
||||
```csharp
|
||||
app.MapControllerRoute(
|
||||
name: "custom",
|
||||
pattern: "{controller=Products}/{action=List}/{id:int:min(1)}"
|
||||
);
|
||||
```
|
||||
|
||||
- `int:min(1)` means `id` must be an integer ≥ 1
|
||||
- Other constraints: `bool`, `datetime`, `guid`, `minlength(x)`, etc.
|
||||
|
||||
---
|
||||
|
||||
### ✅ Per-Controller Default Routes
|
||||
|
||||
You can assign a default action to a specific controller:
|
||||
|
||||
```csharp
|
||||
app.MapControllerRoute(
|
||||
name: "gallery",
|
||||
pattern: "Gallery/{action=Main}/{id?}",
|
||||
defaults: new { controller = "Gallery" }
|
||||
);
|
||||
|
||||
app.MapControllerRoute(
|
||||
name: "default",
|
||||
pattern: "{controller=Home}/{action=Index}/{id?}"
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ SEO-Friendly URLs
|
||||
|
||||
Use descriptive URLs for readability and SEO:
|
||||
|
||||
```csharp
|
||||
app.MapControllerRoute(
|
||||
name: "productDetail",
|
||||
pattern: "products/details/{id:int}/{name}"
|
||||
);
|
||||
```
|
||||
|
||||
✅ Example output: `/products/details/10/laptop`
|
||||
|
||||
---
|
||||
|
||||
## 📍 Part 2: Controllers in ASP.NET Core MVC
|
||||
|
||||
Controllers handle requests and return responses, acting as a bridge between models and views.
|
||||
|
||||
### ✅ Creating a Basic Controller
|
||||
|
||||
```csharp
|
||||
public class HomeController : Controller
|
||||
{
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Handling HTTP Methods
|
||||
|
||||
Use attributes to define the HTTP method an action should handle:
|
||||
|
||||
```csharp
|
||||
[HttpPost]
|
||||
public IActionResult CreateProduct(Product product)
|
||||
{
|
||||
return RedirectToAction("Index");
|
||||
}
|
||||
```
|
||||
|
||||
Other attributes include:
|
||||
|
||||
- `[HttpGet]`
|
||||
- `[HttpPut]`
|
||||
- `[HttpDelete]`
|
||||
|
||||
---
|
||||
|
||||
### ✅ Dependency Injection in Controllers
|
||||
|
||||
Inject services like repositories into controllers for better separation of concerns:
|
||||
|
||||
```csharp
|
||||
public class ProductsController : Controller
|
||||
{
|
||||
private readonly IProductRepository _repository;
|
||||
|
||||
public ProductsController(IProductRepository repository)
|
||||
{
|
||||
_repository = repository;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### ✅ Action Parameters and Model Binding
|
||||
|
||||
Parameters are bound automatically from the URL, query string, or form body:
|
||||
|
||||
```csharp
|
||||
public IActionResult EditProduct(int id, string name)
|
||||
{
|
||||
// id and name are bound from query or route
|
||||
}
|
||||
```
|
||||
|
||||
For complex types, ASP.NET Core binds data from the request body (e.g., forms or JSON).
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Practice
|
||||
|
||||
- Define multiple routes with custom constraints
|
||||
- Build an SEO-friendly route pattern
|
||||
- Create controller with basic actions (`Index`, `Details`, `Create`)
|
||||
- Add attribute-based routes to actions
|
||||
- Use `[HttpGet]`, `[HttpPost]` on appropriate methods
|
||||
- Inject a service into a controller via constructor
|
||||
- Bind parameters from query and route
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
Sources:
|
||||
|
||||
- [Microsoft Docs](https://learn.microsoft.com/en-us/aspnet/core/)
|
||||
- ChatGPT 2025 sessions
|
||||
|
||||
@@ -1,376 +1,93 @@
|
||||
# Part 0: Roadmap of this Session
|
||||
### Views in MVC
|
||||
- [x] Creating and Organizing Views: Using view models and best practices for organizing views.
|
||||
- [x] _Layout.cshtml: Creating reusable layouts for consistent page structure.
|
||||
- [x] Bootstrap Integration: Introduction to Bootstrap and using its grid system, forms, and navigation.
|
||||
- [x] Razor View Engine: Using Razor for conditional content, loops, and strongly typed views.
|
||||
- [ ] HTML Helpers and Tag Helpers: Leveraging helpers to generate forms, links, and other elements
|
||||
# Session 3: Views, Razor Syntax, Bootstrap, and Helpers
|
||||
|
||||
## 📝 Overview
|
||||
|
||||
# Part 1: Introduction to Views
|
||||
In the Model-View-Controller (MVC) pattern, the _view_ handles the app's data presentation and user interaction. A view is an HTML template with embedded [Razor markup](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-9.0). Razor markup is code that interacts with HTML markup to produce a webpage that's sent to the client.
|
||||
In this session, we covered the following concepts:
|
||||
|
||||
In ASP.NET Core MVC, views are `.cshtml` files that use the [C# programming language](https://learn.microsoft.com/en-us/dotnet/csharp/) in Razor markup. Usually, view files are grouped into folders named for each of the app's [controllers](https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/actions?view=aspnetcore-9.0). The folders are stored in a `Views` folder at the root of the app:
|
||||
- Creating and Organizing Views in MVC
|
||||
- Razor Syntax for dynamic content rendering
|
||||
- Bootstrap integration for responsive UI
|
||||
- Using Tag Helpers and HTML Helpers
|
||||
|
||||

|
||||
## 📚 Topics Covered
|
||||
|
||||
The `Home` controller is represented by a `Home` folder inside the `Views` folder. The `Home` folder contains the views for the `About`, `Contact`, and `Index` (homepage) webpages. When a user requests one of these three webpages, controller actions in the `Home` controller determine which of the three views is used to build and return a webpage to the user.
|
||||
### ✅ Creating and Organizing Views
|
||||
|
||||
## Layouts
|
||||
> Learn how views are structured in ASP.NET Core MVC, how to use layouts and partials.
|
||||
|
||||
Use [layouts](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/layout?view=aspnetcore-9.0) to provide consistent webpage sections and reduce code repetition. Layouts often contain the header, navigation and menu elements, and the footer. The header and footer usually contain boilerplate markup for many metadata elements and links to script and style assets. Layouts help you avoid this boilerplate markup in your views.
|
||||
### ✅ Razor Syntax
|
||||
|
||||
## Partial Views
|
||||
[Partial views](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/partial?view=aspnetcore-9.0) reduce code duplication by managing reusable parts of views. For example, a partial view is useful for an author biography on a blog website that appears in several views. An author biography is ordinary view content and doesn't require code to execute in order to produce the content for the webpage. Author biography content is available to the view by model binding alone, so using a partial view for this type of content is ideal.
|
||||
> Use C# inside HTML with Razor to build dynamic views
|
||||
> ⭐ [Razor Docs](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-9.0)
|
||||
|
||||
### When to use partial views
|
||||
### ✅ Bootstrap
|
||||
|
||||
Partial views are an effective way to:
|
||||
> Integrate responsive design into your app using Bootstrap
|
||||
> ⭐ [Bootstrap W3Schools](https://www.w3schools.com/bootstrap/bootstrap_ver.asp)
|
||||
|
||||
- Break up large markup files into smaller components.
|
||||
In a large, complex markup file composed of several logical pieces, there's an advantage to working with each piece isolated into a partial view. The code in the markup file is manageable because the markup only contains the overall page structure and references to partial views.
|
||||
|
||||
- Reduce the duplication of common markup content across markup files.
|
||||
When the same markup elements are used across markup files, a partial view removes the duplication of markup content into one partial view file. When the markup is changed in the partial view, it updates the rendered output of the markup files that use the partial view.
|
||||
Partial views shouldn't be used to maintain common layout elements. Common layout elements should be specified in [_Layout.cshtml](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/layout?view=aspnetcore-9.0) files.
|
||||
### ✅ Tag Helpers and HTML Helpers
|
||||
|
||||
Don't use a partial view where complex rendering logic or code execution is required to render the markup. Instead of a partial view, use a [view component](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-9.0).
|
||||
> Tools to simplify HTML generation in Razor views
|
||||
|
||||
### Partial Tag Helper
|
||||
## 📌 Notes
|
||||
|
||||
The [Partial Tag Helper](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/tag-helpers/built-in/partial-tag-helper?view=aspnetcore-9.0) requires ASP.NET Core 2.1 or later.
|
||||
> _Collected from various sources including Microsoft Learn, W3Schools, and ChatGPT_
|
||||
|
||||
The Partial Tag Helper renders content asynchronously and uses an HTML-like syntax:
|
||||
### Part 1: Introduction to Views
|
||||
|
||||
```cs
|
||||
<partial name="_PartialName" />
|
||||
```
|
||||
- Views (.cshtml files) are templates that render HTML with Razor syntax.
|
||||
- Views are organized in `Views/ControllerName/ViewName.cshtml`.
|
||||
- The `View()` method in a controller renders the corresponding view.
|
||||
- Layouts (\_Layout.cshtml) allow reuse of common HTML structure like headers/footers.
|
||||
- Partial Views help modularize repeated sections (like a profile box).
|
||||
|
||||
```cs
|
||||
<partial name="~/Views/Folder/_PartialName.cshtml" />
|
||||
<partial name="/Views/Folder/_PartialName.cshtml" />
|
||||
```
|
||||
# Part 2: Razor Syntax
|
||||
https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-9.0
|
||||
## Razor syntax
|
||||
### Part 2: Razor Syntax
|
||||
|
||||
Razor supports C# and uses the `@` symbol to transition from HTML to C#. Razor evaluates C# expressions and renders them in the HTML output.
|
||||
- Use `@` to enter C# in HTML.
|
||||
- Implicit: `@Model.Name`, Explicit: `@(Model.Name + "!")`
|
||||
- Code blocks: `@{ var msg = "Hello"; }`
|
||||
- Loops and conditionals are supported: `@if`, `@for`, `@foreach`, `@switch`
|
||||
- Razor supports local functions in code blocks for reusability
|
||||
|
||||
When an `@` symbol is followed by a [Razor reserved keyword](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-9.0#razor-reserved-keywords), it transitions into Razor-specific markup. Otherwise, it transitions into plain HTML.
|
||||
### Part 3: Bootstrap
|
||||
|
||||
To escape an `@` symbol in Razor markup, use a second `@` symbol.
|
||||
- Bootstrap helps in building responsive UI components.
|
||||
- Grid system, forms, buttons, navbars, modals etc. are supported.
|
||||
- Integration involves adding Bootstrap CSS/JS in layout or view.
|
||||
|
||||
## Implicit Razor expressions
|
||||
### Part 4: Tag Helpers and HTML Helpers
|
||||
|
||||
Implicit Razor expressions start with `@` followed by C# code:
|
||||
#### Tag Helpers:
|
||||
|
||||
- Looks like HTML with `asp-*` attributes
|
||||
- Example: `<a asp-controller="Home" asp-action="About">Link</a>`
|
||||
- Requires `@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers` in `_ViewImports.cshtml`
|
||||
|
||||
```html
|
||||
<p>@DateTime.Now</p>
|
||||
<p>@DateTime.IsLeapYear(2016)</p>
|
||||
```
|
||||
#### HTML Helpers:
|
||||
|
||||
## Explicit Razor expressions
|
||||
- Use C# syntax like `@Html.TextBoxFor(...)`, `@Html.BeginForm()`
|
||||
- More verbose but offers fine control with C# expressions
|
||||
|
||||
Explicit Razor expressions consist of an `@` symbol with balanced parenthesis. To render last week's time, the following Razor markup is used:
|
||||
#### Comparison:
|
||||
|
||||
```html
|
||||
<p>Last week this time: @(DateTime.Now - TimeSpan.FromDays(7))</p>
|
||||
```
|
||||
| Feature | Tag Helpers | HTML Helpers |
|
||||
| ----------- | ----------- | ------------ |
|
||||
| Syntax | HTML-like | C# methods |
|
||||
| Readability | High | Moderate |
|
||||
| Use | `asp-*` | `@Html.*` |
|
||||
|
||||
## Razor code blocks
|
||||
## 🧪 Practice
|
||||
|
||||
Razor code blocks start with `@` and are enclosed by `{}`. Unlike expressions, C# code inside code blocks isn't rendered. Code blocks and expressions in a view share the same scope and are defined in order:
|
||||
- Create a view with a layout and partial
|
||||
- Use Razor syntax to display dynamic data
|
||||
- Build a form with Tag Helpers
|
||||
- Refactor a view using HTML Helpers
|
||||
|
||||
```cs
|
||||
@{
|
||||
var quote = "The future depends on what you do today. - Mahatma Gandhi";
|
||||
}
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
<p>@quote</p>
|
||||
Sources:
|
||||
|
||||
@{
|
||||
quote = "Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.";
|
||||
}
|
||||
|
||||
<p>@quote</p>
|
||||
```
|
||||
|
||||
The code renders the following HTML:
|
||||
|
||||
|
||||
```html
|
||||
<p>The future depends on what you do today. - Mahatma Gandhi</p>
|
||||
<p>Hate cannot drive out hate, only love can do that. - Martin Luther King, Jr.</p>
|
||||
```
|
||||
|
||||
In code blocks, declare [local functions](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/local-functions) with markup to serve as templating methods:
|
||||
|
||||
|
||||
```cs
|
||||
@{
|
||||
void RenderName(string name)
|
||||
{
|
||||
<p>Name: <strong>@name</strong></p>
|
||||
}
|
||||
|
||||
RenderName("Mahatma Gandhi");
|
||||
RenderName("Martin Luther King, Jr.");
|
||||
}
|
||||
```
|
||||
|
||||
The code renders the following HTML:
|
||||
|
||||
```html
|
||||
<p>Name: <strong>Mahatma Gandhi</strong></p>
|
||||
<p>Name: <strong>Martin Luther King, Jr.</strong></p>
|
||||
```
|
||||
|
||||
## Control structures
|
||||
|
||||
Control structures are an extension of code blocks. All aspects of code blocks (transitioning to markup, inline C#) also apply to the following structures:
|
||||
|
||||
### Conditionals `@if, else if, else, and @switch`
|
||||
`@if` controls when code runs:
|
||||
|
||||
```cs
|
||||
@if (value % 2 == 0)
|
||||
{
|
||||
<p>The value was even.</p>
|
||||
}
|
||||
```
|
||||
|
||||
`else` and `else if` don't require the `@` symbol:
|
||||
|
||||
|
||||
```cs
|
||||
@if (value % 2 == 0)
|
||||
{
|
||||
<p>The value was even.</p>
|
||||
}
|
||||
else if (value >= 1337)
|
||||
{
|
||||
<p>The value is large.</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<p>The value is odd and small.</p>
|
||||
}
|
||||
```
|
||||
|
||||
The following markup shows how to use a switch statement:
|
||||
|
||||
```cs
|
||||
@switch (value)
|
||||
{
|
||||
case 1:
|
||||
<p>The value is 1!</p>
|
||||
break;
|
||||
case 1337:
|
||||
<p>Your number is 1337!</p>
|
||||
break;
|
||||
default:
|
||||
<p>Your number wasn't 1 or 1337.</p>
|
||||
break;
|
||||
}
|
||||
```
|
||||
|
||||
### Looping `@for, @foreach, @while, and @do while`
|
||||
|
||||
`@for`
|
||||
```cs
|
||||
@for (var i = 0; i < people.Length; i++)
|
||||
{
|
||||
var person = people[i];
|
||||
<p>Name: @person.Name</p>
|
||||
<p>Age: @person.Age</p>
|
||||
}
|
||||
```
|
||||
|
||||
`@foreach`
|
||||
|
||||
```cs
|
||||
@foreach (var person in people)
|
||||
{
|
||||
<p>Name: @person.Name</p>
|
||||
<p>Age: @person.Age</p>
|
||||
}
|
||||
```
|
||||
|
||||
`@while`
|
||||
|
||||
|
||||
```cs
|
||||
@{ var i = 0; }
|
||||
@while (i < people.Length)
|
||||
{
|
||||
var person = people[i];
|
||||
<p>Name: @person.Name</p>
|
||||
<p>Age: @person.Age</p>
|
||||
|
||||
i++;
|
||||
}
|
||||
```
|
||||
# Part 3: Bootstrap and Frontend development
|
||||
## What is Bootstrap?
|
||||
|
||||
- Bootstrap is a free front-end framework for faster and easier web development
|
||||
- Bootstrap includes HTML and CSS based design templates for typography, forms, buttons, tables, navigation, modals, image carousels and many other, as well as optional JavaScript plugins
|
||||
- Bootstrap also gives you the ability to easily create responsive designs
|
||||
|
||||
https://www.w3schools.com/bootstrap/bootstrap_ver.asp
|
||||
https://getbootstrap.com/docs/4.0/components/buttons/
|
||||
![[Pasted image 20241121120517.png]]
|
||||
|
||||
# Part 4: Tag Helpers and HTML Helpers
|
||||
### **Tag Helpers and HTML Helpers in ASP.NET Core**
|
||||
|
||||
Tag Helpers and HTML Helpers are features of ASP.NET Core MVC used to simplify the creation of dynamic HTML content in Razor views. Both are tools for generating HTML but differ in syntax, approach, and usability.
|
||||
|
||||
---
|
||||
|
||||
## **1. Tag Helpers**
|
||||
|
||||
### **What Are Tag Helpers?**
|
||||
|
||||
Tag Helpers are server-side components in ASP.NET Core that help you generate and manipulate HTML elements using a natural and familiar syntax that resembles standard HTML.
|
||||
|
||||
#### Key Characteristics:
|
||||
|
||||
- Blend seamlessly with standard HTML.
|
||||
- Use attributes to bind data or add functionality.
|
||||
- Processed on the server and output pure HTML.
|
||||
|
||||
---
|
||||
|
||||
### **Examples of Tag Helpers**
|
||||
|
||||
1. **Anchor Tag Helper (`<a>`)**
|
||||
`<a asp-controller="Home" asp-action="About" class="btn btn-primary">Go to About</a>`
|
||||
- `asp-controller`: Specifies the controller (`Home`).
|
||||
- `asp-action`: Specifies the action (`About`).
|
||||
- This generates:
|
||||
`<a href="/Home/About" class="btn btn-primary">Go to About</a>`
|
||||
1. **Form Tag Helper**
|
||||
|
||||
`<form asp-controller="Account" asp-action="Login" method="post"> <input type="text" name="username" /> <button type="submit">Login</button> </form>`
|
||||
|
||||
- Automatically generates the form's `action` attribute based on the controller and action.
|
||||
3. **Input Tag Helper*
|
||||
|
||||
`<input asp-for="UserName" class="form-control" />`
|
||||
|
||||
- `asp-for`: Binds the input element to the `UserName` property of the model.
|
||||
4. **Validation Tag Helpers**
|
||||
|
||||
|
||||
`<span asp-validation-for="Email" class="text-danger"></span>`
|
||||
|
||||
- Displays validation messages for the `Email` property.
|
||||
|
||||
---
|
||||
|
||||
### **How Tag Helpers Work**
|
||||
|
||||
- Tag Helpers are identified by their **attributes**, like `asp-controller` or `asp-for`.
|
||||
- These attributes are processed on the server to generate the appropriate HTML.
|
||||
|
||||
#### Configuration:
|
||||
|
||||
Tag Helpers are enabled globally in Razor views by default using the `_ViewImports.cshtml` file:
|
||||
|
||||
`@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers`
|
||||
|
||||
#### Benefits:
|
||||
|
||||
- Intuitive and HTML-like syntax.
|
||||
- Cleaner and more readable Razor views.
|
||||
- Easier to maintain and debug.
|
||||
|
||||
---
|
||||
|
||||
## **2. HTML Helpers**
|
||||
|
||||
### **What Are HTML Helpers?**
|
||||
|
||||
HTML Helpers are server-side C# methods that generate HTML elements dynamically. They are written in Razor syntax (`@Html.*`) and allow you to create UI components programmatically.
|
||||
|
||||
#### Key Characteristics:
|
||||
|
||||
- Written as C# methods.
|
||||
- More explicit than Tag Helpers.
|
||||
- Processed on the server and output HTML.
|
||||
|
||||
---
|
||||
### **Examples of HTML Helpers**
|
||||
|
||||
1. **Anchor Links (`Html.ActionLink`)**
|
||||
|
||||
|
||||
`@Html.ActionLink("Go to About", "About", "Home", null, new { @class = "btn btn-primary" })`
|
||||
|
||||
- Generates:
|
||||
|
||||
html
|
||||
|
||||
`<a href="/Home/About" class="btn btn-primary">Go to About</a>`
|
||||
|
||||
2. **Forms (`Html.BeginForm`)**
|
||||
|
||||
razor
|
||||
`@using (Html.BeginForm("Login", "Account", FormMethod.Post)) { @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" }) <button type="submit">Login</button> }`
|
||||
|
||||
- Generates:
|
||||
|
||||
|
||||
`<form action="/Account/Login" method="post"> <input class="form-control" id="UserName" name="UserName" type="text" value=""> <button type="submit">Login</button> </form>`
|
||||
|
||||
3. **Input Fields (`Html.TextBoxFor`)**
|
||||
|
||||
|
||||
`@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })`
|
||||
|
||||
- Generates:
|
||||
|
||||
|
||||
`<input class="form-control" id="Email" name="Email" type="text" value="">`
|
||||
|
||||
4. **Validation Messages**
|
||||
|
||||
|
||||
`@Html.ValidationMessageFor(m => m.Email, null, new { @class = "text-danger" })`
|
||||
|
||||
- Displays validation messages for the `Email` property.
|
||||
|
||||
---
|
||||
|
||||
### **How HTML Helpers Work**
|
||||
|
||||
- They are methods in the `System.Web.Mvc.HtmlHelper` class.
|
||||
- Use lambda expressions to bind data to model properties.
|
||||
|
||||
#### Benefits:
|
||||
|
||||
- Provide programmatic control over HTML generation.
|
||||
- Allow detailed customization using C#.
|
||||
|
||||
---
|
||||
|
||||
## **Comparison: Tag Helpers vs. HTML Helpers**
|
||||
|
||||
| **Feature** | **Tag Helpers** | **HTML Helpers** |
|
||||
| ----------------- | ------------------------------------ | -------------------------------------- |
|
||||
| **Syntax** | HTML-like attributes | C# method calls |
|
||||
| **Readability** | Cleaner and more intuitive | Less readable in complex scenarios |
|
||||
| **Usage** | Uses attributes like `asp-for` | Uses Razor methods like `Html.TextBox` |
|
||||
| **Configuration** | Requires `_ViewImports.cshtml` setup | No special configuration required |
|
||||
| **Flexibility** | Easier to extend and customize | More explicit but less integrated |
|
||||
| **Examples** | `<input asp-for="Email" />` | `@Html.TextBoxFor(m => m.Email)` |
|
||||
|
||||
---
|
||||
|
||||
## **Best Practices**
|
||||
|
||||
1. Use **Tag Helpers** for modern, clean, and readable Razor views.
|
||||
2. Use **HTML Helpers** for scenarios requiring complex C# logic or when you prefer programmatic control.
|
||||
3. Avoid mixing both approaches in the same view for consistency.
|
||||
- [Microsoft Learn - Razor](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-9.0)
|
||||
- [Microsoft Learn - Views](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/overview?view=aspnetcore-9.0)
|
||||
- [W3Schools - Bootstrap](https://www.w3schools.com/bootstrap/bootstrap_ver.asp)
|
||||
- ChatGPT Assistance (2025 sessions)
|
||||
|
||||
@@ -1,412 +1,152 @@
|
||||
## View Components
|
||||
[View components](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/view-components?view=aspnetcore-9.0) are similar to partial views in that they allow you to reduce repetitive code, but they're appropriate for view content that requires code to run on the server in order to render the webpage. View components are useful when the rendered content requires database interaction, such as for a website shopping cart. View components aren't limited to model binding in order to produce webpage output.
|
||||
|
||||
|
||||
## ViewImports and ViewStart
|
||||
In Razor Pages, the application of `ViewStart.cshtml` and `ViewImports.cshtml` is governed by their **location in the folder hierarchy**. These files are automatically discovered and applied by ASP.NET Core's Razor engine based on the folder structure.
|
||||
|
||||
---
|
||||
|
||||
### **How `ViewStart.cshtml` Works in Razor Pages**
|
||||
|
||||
1. **Global Scope:**
|
||||
|
||||
- A `ViewStart.cshtml` file placed in the root of the `Pages` folder applies to all Razor Pages in the project.
|
||||
- Example structure:
|
||||
`Pages/ ├── _ViewStart.cshtml ├── Index.cshtml ├── About.cshtml`
|
||||
|
||||
If `_ViewStart.cshtml` contains:
|
||||
`@{ Layout = "_Layout"; }`
|
||||
Then `Index.cshtml` and `About.cshtml` will use the `_Layout` layout.
|
||||
|
||||
2. **Local Override:**
|
||||
- If a `ViewStart.cshtml` exists in a subfolder, it **overrides** the `ViewStart.cshtml` in the parent folder for that subfolder and its descendants.
|
||||
- Example structure:
|
||||
`Pages/ ├── _ViewStart.cshtml ├── Admin/ │ ├── _ViewStart.cshtml │ ├── Dashboard.cshtml └── Index.cshtml`
|
||||
- The `_ViewStart.cshtml` in `Pages/Admin/` will apply to `Dashboard.cshtml`.
|
||||
- The `_ViewStart.cshtml` in the root will apply to `Index.cshtml`.
|
||||
# Session 4: Views, Razor Syntax, Bootstrap, and Helpers
|
||||
|
||||
---
|
||||
## 📝 Overview
|
||||
|
||||
### **How `ViewImports.cshtml` Works in Razor Pages**
|
||||
1. **Global Scope:**
|
||||
- A `ViewImports.cshtml` file placed in the root of the `Pages` folder applies to all Razor Pages in the project.
|
||||
- Example structure:
|
||||
`Pages/ ├── _ViewImports.cshtml ├── Index.cshtml ├── Contact.cshtml`
|
||||
If `_ViewImports.cshtml` contains:
|
||||
`@using MyApp.Models @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers`
|
||||
Then both `Index.cshtml` and `Contact.cshtml` will have access to the `MyApp.Models` namespace and the Tag Helpers.
|
||||
2. **Local Override or Supplement:**
|
||||
- A `ViewImports.cshtml` file in a subfolder **adds to** or **overrides** the settings from the parent folder.
|
||||
- Example structure:
|
||||
`Pages/ ├── _ViewImports.cshtml ├── Admin/ │ ├── _ViewImports.cshtml │ ├── Dashboard.cshtml └── Index.cshtml`
|
||||
- The `@using` directives and Tag Helpers in `Pages/Admin/_ViewImports.cshtml` will only apply to `Dashboard.cshtml`.
|
||||
- The root `Pages/_ViewImports.cshtml` still applies to `Index.cshtml`.
|
||||
---
|
||||
In this session, we covered the following concepts:
|
||||
|
||||
### **How Razor Pages Discover These Files**
|
||||
|
||||
- **Runtime Discovery:** The Razor engine searches for these files in the **current folder** and all parent folders (up to the root).
|
||||
- **Hierarchical Application:**
|
||||
- `ViewStart.cshtml` and `ViewImports.cshtml` in a closer (nested) folder override or extend those in parent folders.
|
||||
- This hierarchy allows flexible configuration for specific parts of the application.
|
||||
|
||||
---
|
||||
|
||||
### **Best Practices for Razor Pages**
|
||||
|
||||
1. Place shared settings (e.g., default layout or common namespaces) in the root-level `ViewStart.cshtml` and `ViewImports.cshtml`.
|
||||
2. Use folder-specific overrides sparingly to avoid confusion.
|
||||
3. Keep these files clean and limited to truly shared settings or imports.
|
||||
Let me know if you'd like an example project structure for clarification!
|
||||
## Tag Helpers and HTML Helpers
|
||||
### **1. Tag Helpers**
|
||||
|
||||
### **What Are Tag Helpers?**
|
||||
|
||||
Tag Helpers are server-side components in ASP.NET Core that help you generate and manipulate HTML elements using a natural and familiar syntax that resembles standard HTML.
|
||||
|
||||
#### Key Characteristics:
|
||||
|
||||
- Blend seamlessly with standard HTML.
|
||||
- Use attributes to bind data or add functionality.
|
||||
- Processed on the server and output pure HTML.
|
||||
|
||||
---
|
||||
|
||||
### **Examples of Tag Helpers**
|
||||
|
||||
1. **Anchor Tag Helper (`<a>`)**
|
||||
`<a asp-controller="Home" asp-action="About" class="btn btn-primary">Go to About</a>`
|
||||
- `asp-controller`: Specifies the controller (`Home`).
|
||||
- `asp-action`: Specifies the action (`About`).
|
||||
- This generates:
|
||||
`<a href="/Home/About" class="btn btn-primary">Go to About</a>`
|
||||
1. **Form Tag Helper**
|
||||
|
||||
`<form asp-controller="Account" asp-action="Login" method="post"> <input type="text" name="username" /> <button type="submit">Login</button> </form>`
|
||||
|
||||
- Automatically generates the form's `action` attribute based on the controller and action.
|
||||
3. **Input Tag Helper*
|
||||
|
||||
`<input asp-for="UserName" class="form-control" />`
|
||||
|
||||
- `asp-for`: Binds the input element to the `UserName` property of the model.
|
||||
4. **Validation Tag Helpers**
|
||||
`<span asp-validation-for="Email" class="text-danger"></span>`
|
||||
|
||||
- Displays validation messages for the `Email` property.
|
||||
|
||||
---
|
||||
|
||||
### **How Tag Helpers Work**
|
||||
|
||||
- Tag Helpers are identified by their **attributes**, like `asp-controller` or `asp-for`.
|
||||
- These attributes are processed on the server to generate the appropriate HTML.
|
||||
|
||||
#### Configuration:
|
||||
|
||||
Tag Helpers are enabled globally in Razor views by default using the `_ViewImports.cshtml` file:
|
||||
|
||||
`@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers`
|
||||
|
||||
#### Benefits:
|
||||
|
||||
- Intuitive and HTML-like syntax.
|
||||
- Cleaner and more readable Razor views.
|
||||
- Easier to maintain and debug.
|
||||
|
||||
---
|
||||
|
||||
### **2. HTML Helpers**
|
||||
|
||||
### **What Are HTML Helpers?**
|
||||
|
||||
HTML Helpers are server-side C# methods that generate HTML elements dynamically. They are written in Razor syntax (`@Html.*`) and allow you to create UI components programmatically.
|
||||
|
||||
#### Key Characteristics:
|
||||
|
||||
- Written as C# methods.
|
||||
- More explicit than Tag Helpers.
|
||||
- Processed on the server and output HTML.
|
||||
|
||||
---
|
||||
### **Examples of HTML Helpers**
|
||||
|
||||
1. **Anchor Links (`Html.ActionLink`)**
|
||||
|
||||
|
||||
`@Html.ActionLink("Go to About", "About", "Home", null, new { @class = "btn btn-primary" })`
|
||||
|
||||
- Generates:
|
||||
|
||||
html
|
||||
|
||||
`<a href="/Home/About" class="btn btn-primary">Go to About</a>`
|
||||
|
||||
2. **Forms (`Html.BeginForm`)**
|
||||
|
||||
razor
|
||||
`@using (Html.BeginForm("Login", "Account", FormMethod.Post)) { @Html.TextBoxFor(m => m.UserName, new { @class = "form-control" }) <button type="submit">Login</button> }`
|
||||
|
||||
- Generates:
|
||||
|
||||
|
||||
`<form action="/Account/Login" method="post"> <input class="form-control" id="UserName" name="UserName" type="text" value=""> <button type="submit">Login</button> </form>`
|
||||
|
||||
3. **Input Fields (`Html.TextBoxFor`)**
|
||||
|
||||
|
||||
`@Html.TextBoxFor(m => m.Email, new { @class = "form-control" })`
|
||||
|
||||
- Generates:
|
||||
|
||||
|
||||
`<input class="form-control" id="Email" name="Email" type="text" value="">`
|
||||
|
||||
4. **Validation Messages**
|
||||
|
||||
|
||||
`@Html.ValidationMessageFor(m => m.Email, null, new { @class = "text-danger" })`
|
||||
|
||||
- Displays validation messages for the `Email` property.
|
||||
- Creating and Organizing Views in MVC
|
||||
- Razor Syntax for dynamic content rendering
|
||||
- Bootstrap integration for responsive UI
|
||||
- Using Tag Helpers and HTML Helpers
|
||||
- View Components
|
||||
- ViewImports and ViewStart
|
||||
- ViewData vs ViewBag
|
||||
- OOP Concepts in MVC: Encapsulation, Inheritance, Polymorphism, Abstraction, DTO
|
||||
|
||||
---
|
||||
## 📚 Topics Covered
|
||||
|
||||
### **How HTML Helpers Work**
|
||||
### ✅ Creating and Organizing Views
|
||||
|
||||
- They are methods in the `System.Web.Mvc.HtmlHelper` class.
|
||||
- Use lambda expressions to bind data to model properties.
|
||||
> Learn how views are structured in ASP.NET Core MVC, how to use layouts and partials.
|
||||
|
||||
#### Benefits:
|
||||
### ✅ Razor Syntax
|
||||
|
||||
- Provide programmatic control over HTML generation.
|
||||
- Allow detailed customization using C#.
|
||||
> Use C# inside HTML with Razor to build dynamic views
|
||||
> ⭐ [Razor Docs](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-9.0)
|
||||
|
||||
---
|
||||
### ✅ Bootstrap
|
||||
|
||||
### **Comparison: Tag Helpers vs. HTML Helpers**
|
||||
> Integrate responsive design into your app using Bootstrap
|
||||
> ⭐ [Bootstrap W3Schools](https://www.w3schools.com/bootstrap/bootstrap_ver.asp)
|
||||
|
||||
| **Feature** | **Tag Helpers** | **HTML Helpers** |
|
||||
| ----------------- | ------------------------------------ | -------------------------------------- |
|
||||
| **Syntax** | HTML-like attributes | C# method calls |
|
||||
| **Readability** | Cleaner and more intuitive | Less readable in complex scenarios |
|
||||
| **Usage** | Uses attributes like `asp-for` | Uses Razor methods like `Html.TextBox` |
|
||||
| **Configuration** | Requires `_ViewImports.cshtml` setup | No special configuration required |
|
||||
| **Flexibility** | Easier to extend and customize | More explicit but less integrated |
|
||||
| **Examples** | `<input asp-for="Email" />` | `@Html.TextBoxFor(m => m.Email)` |
|
||||
### ✅ Tag Helpers and HTML Helpers
|
||||
|
||||
---
|
||||
> Tools to simplify HTML generation in Razor views
|
||||
|
||||
### **Best Practices**
|
||||
## 📌 Notes
|
||||
|
||||
1. Use **Tag Helpers** for modern, clean, and readable Razor views.
|
||||
2. Use **HTML Helpers** for scenarios requiring complex C# logic or when you prefer programmatic control.
|
||||
3. Avoid mixing both approaches in the same view for consistency.
|
||||
> _Collected from various sources including Microsoft Learn, W3Schools, and ChatGPT_
|
||||
|
||||
---
|
||||
### **Difference Between ViewData and ViewBag in ASP.NET Core MVC**
|
||||
|
||||
1. **Nature and Syntax:**
|
||||
- **ViewData:**
|
||||
- A dictionary-based object (`ViewData` is of type `ViewDataDictionary`) that allows storing data as key-value pairs.
|
||||
- Syntax: `ViewData["Key"] = value;`
|
||||
- **ViewBag:**
|
||||
- A dynamic object (uses the `dynamic` keyword internally) that provides a more flexible way to pass data without needing a strongly typed key.
|
||||
- Syntax: `ViewBag.Key = value;`
|
||||
2. **Ease of Use:**
|
||||
- **ViewData** requires string keys and is less intuitive for accessing data.
|
||||
- **ViewBag** allows using properties directly (e.g., `ViewBag.Key`) which feels more natural in many cases.
|
||||
3. **Compile-Time Safety:**
|
||||
- **ViewData:** Offers no compile-time checking; you'll encounter runtime errors if the key is mistyped or doesn't exist.
|
||||
- **ViewBag:** Same limitation as `ViewData`—runtime errors will occur if you try to access a non-existing property.
|
||||
|
||||
---
|
||||
### **Storage**
|
||||
|
||||
Both `ViewData` and `ViewBag` store their data in the same place internally: the `ViewData` dictionary.
|
||||
|
||||
- When you assign a value to `ViewBag.Key`, it's actually stored in the `ViewData["Key"]` dictionary.
|
||||
- Accessing `ViewData["Key"]` and `ViewBag.Key` refers to the same underlying data, so they are interchangeable.
|
||||
|
||||
For example:
|
||||
|
||||
csharp
|
||||
|
||||
Copy code
|
||||
|
||||
```c#
|
||||
ViewData["Message"] = "Hello, ViewData!";
|
||||
ViewBag.Message = "Hello, ViewBag!";
|
||||
// This works because they share the same storage:
|
||||
string msgFromViewData = ViewData["Message"].ToString(); // "Hello, ViewBag!"
|
||||
string msgFromViewBag = ViewBag.Message; // "Hello, ViewBag!"
|
||||
```
|
||||
|
||||
### **How ViewBag Can Use Any Name**
|
||||
|
||||
The `ViewBag` uses the `dynamic` type in C#, which means properties on the `ViewBag` do not need to be declared beforehand.
|
||||
|
||||
When you assign `ViewBag.SomeProperty = value;`, the **runtime** dynamically creates an entry for `SomeProperty` in the `ViewData` dictionary. The `ViewBag` acts as a wrapper, intercepting calls to properties and storing them in `ViewData`.
|
||||
|
||||
**Example:**
|
||||
|
||||
|
||||
```c#
|
||||
ViewBag.Greeting = "Hello!";
|
||||
// Internally translates to: ViewData["Greeting"] = "Hello!";
|
||||
```
|
||||
|
||||
When you try to access `ViewBag.Greeting`, the framework dynamically checks if a corresponding entry exists in `ViewData` and retrieves it. If it doesn’t exist, a runtime error occurs.
|
||||
|
||||
---
|
||||
|
||||
### **Which One Should You Use?**
|
||||
|
||||
1. **Prefer `ViewBag`** when you want concise and clean code for passing small amounts of data dynamically.
|
||||
2. **Prefer `ViewData`** when you:
|
||||
- Need to pass data explicitly by string keys.
|
||||
- Work in scenarios where dynamic properties are not desirable.
|
||||
3. **For strongly-typed views**, avoid both in favor of **ViewModels**, as they provide compile-time safety and better maintainability.
|
||||
|
||||
## OOP
|
||||
|
||||
argument vs parameter
|
||||
### **Encapsulation**
|
||||
https://www.geeksforgeeks.org/c-sharp-encapsulation/
|
||||
|
||||
Encapsulation is defined as the wrapping up of data and information under a single unit. It is the mechanism that binds together the data and the functions that manipulate them. In a different way, encapsulation is a protective shield that prevents the data from being accessed by the code outside this shield.
|
||||
|
||||
- Technically in encapsulation, the variables or data of a class are hidden from any other class and can be accessed only through any member function of its own class in which they are declared.
|
||||
- As in encapsulation, the data in a class is hidden from other classes, so it is also known as ****data-hiding****.
|
||||
- ****Encapsulation can be achieved by:**** Declaring all the variables in the class as private and using [****C# Properties****](https://www.geeksforgeeks.org/c-properties/) in the class to set and get the values of variables.
|
||||
|
||||
// C# program to illustrate encapsulation
|
||||
|
||||
```c#
|
||||
using System;
|
||||
|
||||
public class DemoEncap {
|
||||
|
||||
// private variables declared
|
||||
// these can only be accessed by
|
||||
// public methods of class
|
||||
private String studentName;
|
||||
private int studentAge;
|
||||
|
||||
// using accessors to get and
|
||||
// set the value of studentName
|
||||
public String Name
|
||||
{
|
||||
|
||||
get { return studentName; }
|
||||
|
||||
set { studentName = value; }
|
||||
}
|
||||
|
||||
// using accessors to get and
|
||||
// set the value of studentAge
|
||||
public int Age
|
||||
{
|
||||
|
||||
get { return studentAge; }
|
||||
|
||||
set { studentAge = value; }
|
||||
}
|
||||
}
|
||||
|
||||
// Driver Class
|
||||
class GFG {
|
||||
|
||||
// Main Method
|
||||
static public void Main()
|
||||
{
|
||||
|
||||
// creating object
|
||||
DemoEncap obj = new DemoEncap();
|
||||
|
||||
// calls set accessor of the property Name,
|
||||
// and pass "Ankita" as value of the
|
||||
// standard field 'value'
|
||||
obj.Name = "Ankita";
|
||||
|
||||
// calls set accessor of the property Age,
|
||||
// and pass "21" as value of the
|
||||
// standard field 'value'
|
||||
obj.Age = 21;
|
||||
|
||||
// Displaying values of the variables
|
||||
Console.WriteLine(" Name : " + obj.Name);
|
||||
Console.WriteLine(" Age : " + obj.Age);
|
||||
}
|
||||
}
|
||||
```
|
||||
### Part 1: Introduction to Views
|
||||
|
||||
#### Advantages of Encapsulation
|
||||
|
||||
- ****Data Hiding:**** The user will have no idea about the inner implementation of the class. It will not be visible to the user that how the class is stored values in the variables. He only knows that we are passing the values to accessors and variables are getting initialized to that value.
|
||||
- ****Increased Flexibility:**** We can make the variables of the class as read-only or write-only depending on our requirement. If we wish to make the variables as read-only then we have to only use Get Accessor in the code. If we wish to make the variables as write-only then we have to only use Set Accessor.
|
||||
- ****Reusability:**** Encapsulation also improves the re-usability and easy to change with new requirements.
|
||||
- ****Testing code is easy:**** Encapsulated code is easy to test for unit testing.
|
||||
|
||||
Encapsulation is a fundamental concept in object-oriented programming (OOP) that refers to the bundling of data and the methods that operate on that data within a single unit. In C#, this is typically achieved through the use of classes.
|
||||
|
||||
The idea behind encapsulation is to keep the implementation details of a class hidden from the outside world, and to only expose a public interface that allows users to interact with the class in a controlled and safe manner. This helps to promote modularity, maintainability, and flexibility in the design of software systems.
|
||||
#### DTO
|
||||
A Data Transfer Object is an object that is used to encapsulate data, and send it from one subsystem of an application to another.
|
||||
|
||||
DTOs are most commonly used by the Services layer in an N-Tier application to transfer data between itself and the UI layer. The main benefit here is that it reduces the amount of data that needs to be sent across the wire in distributed applications. They also make great models in the MVC pattern.
|
||||
|
||||
Another use for DTOs can be to encapsulate parameters for method calls. This can be useful if a method takes more than four or five parameters.
|
||||
|
||||
### **Inheritance**
|
||||
Inheritance is a fundamental concept in object-oriented programming that allows us to define a new class based on an existing class. The new class inherits the properties and methods of the existing class and can also add new properties and methods of its own. Inheritance promotes code reuse, simplifies code maintenance, and improves code organization.
|
||||
#### Advantages of Inheritance:
|
||||
|
||||
1. Code Reusability: Inheritance allows us to reuse existing code by inheriting properties and methods from an existing class.
|
||||
2. Code Maintenance: Inheritance makes code maintenance easier by allowing us to modify the base class and have the changes automatically reflected in the derived classes.
|
||||
3. Code Organization: Inheritance improves code organization by grouping related classes together in a hierarchical structure.
|
||||
|
||||
[****Inheritance:****](https://www.geeksforgeeks.org/inheritance-in-java/)
|
||||
|
||||
For any bird, there are a set of predefined properties which are common for all the birds and there are a set of properties which are specific for a particular bird. Therefore, intuitively, we can say that all the birds inherit the common features like wings, legs, eyes, etc. Therefore, in the object-oriented way of representing the birds, we first declare a bird class with a set of properties which are common to all the birds. By doing this, we can avoid declaring these common properties in every bird which we create. Instead, we can simply __inherit__ the bird class in all the birds which we create. The following is an example of how the concept of inheritance is implemented.
|
||||
### **Polymorphism**
|
||||
|
||||
The word polymorphism is made of two words poly and morph, where poly means many and morphs means forms. In programming, polymorphism is a feature that allows one interface to be used for a general class of actions. In the above concept of a bird and pigeon, a pigeon is inherently a bird. And also, if the birds are further categorized into multiple categories like flying birds, flightless birds, etc. the pigeon also fits into the flying bird’s category. And also, if the animal class is further categorized into plant-eating animals and meat-eating animals, the pigeon again comes into the plant-eating animal’s category. Therefore, the idea of polymorphism is the ability of the same object to take multiple forms. There are two types of polymorphism:
|
||||
|
||||
1. ****Compile Time Polymorphism:**** It is also known as static polymorphism. This type of polymorphism is achieved by function overloading or operator overloading. It occurs when we define multiple methods with different signatures and the compiler knows which method needs to be executed based on the method signatures.
|
||||
2. [****Run Time Polymorphism****](https://www.geeksforgeeks.org/dynamic-method-dispatch-runtime-polymorphism-java/)****:**** It is also known as Dynamic Method Dispatch. It is a process in which a function call to the overridden method is resolved at Runtime. This type of polymorphism is achieved by Method Overriding. When the same method with the same parameters is overridden with different contexts, the compiler doesn’t have any idea that the method is overridden. It simply checks if the method exists and during the runtime, it executes the functions which have been overridden.
|
||||
|
||||
### **Abstraction**
|
||||
|
||||
Data abstraction is a design pattern in which data are visible only to semantically related functions, to prevent misuse. The success of data abstraction leads to frequent incorporation of [data hiding](https://en.wikipedia.org/wiki/Data_hiding "Data hiding") as a design principle in object-oriented and pure functional programming.
|
||||
#### Encapsulation vs Data Abstraction
|
||||
|
||||
- [**Encapsulation**](https://www.geeksforgeeks.org/c-encapsulation/) is data hiding(information hiding) while Abstraction is detail hiding(implementation hiding).
|
||||
- While encapsulation groups together data and methods that act upon the data, data abstraction deal with exposing to the user and hiding the details of implementation.
|
||||
|
||||
StackOverflow:
|
||||
https://stackoverflow.com/questions/15176356/difference-between-encapsulation-and-abstraction
|
||||
|
||||
**Encapsulation** hides variables or some implementation that may be changed so often **in a class** to prevent outsiders access it directly. They must access it via getter and setter methods.
|
||||
|
||||
**Abstraction** is used to hide something too, but in a **higher degree (class, interface)**. Clients who use an abstract class (or interface) do not care about what it was, they just need to know what it can do.
|
||||
|
||||
#### Advantages of Abstraction
|
||||
|
||||
- It reduces the complexity of viewing things.
|
||||
- Avoids code duplication and increases reusability.
|
||||
- Helps to increase the security of an application or program as only important details are provided to the user.
|
||||
- Views (.cshtml files) are templates that render HTML with Razor syntax.
|
||||
- Views are organized in `Views/ControllerName/ViewName.cshtml`.
|
||||
- The `View()` method in a controller renders the corresponding view.
|
||||
- Layouts (\_Layout.cshtml) allow reuse of common HTML structure like headers/footers.
|
||||
- Partial Views help modularize repeated sections (like a profile box).
|
||||
|
||||
### Part 2: Razor Syntax
|
||||
|
||||
- Use `@` to enter C# in HTML.
|
||||
- Implicit: `@Model.Name`, Explicit: `@(Model.Name + "!")`
|
||||
- Code blocks: `@{ var msg = "Hello"; }`
|
||||
- Loops and conditionals are supported: `@if`, `@for`, `@foreach`, `@switch`
|
||||
- Razor supports local functions in code blocks for reusability
|
||||
|
||||
### Part 3: Bootstrap
|
||||
|
||||
[****Abstraction:****](https://www.geeksforgeeks.org/abstraction-in-java-2/)
|
||||
|
||||
Abstraction in general means hiding. In the above scenario of the bird and pigeon, let’s say there is a user who wants to see pigeon fly. The user is simply interested in seeing the pigeon fly but not interested in how the bird is actually flying. Therefore, in the above scenario where the user wishes to make it fly, he will simply call the fly method by using ****pigeon.fly()**** where the pigeon is the object of the bird pigeon. Therefore, abstraction means the art of representing the essential features without concerning about the background details. In Java, the abstraction is implemented through the use of [interface](https://www.geeksforgeeks.org/interfaces-in-java/) and [abstract classes](https://www.geeksforgeeks.org/abstract-classes-in-java/). We can achieve complete abstraction with the use of Interface whereas a partial or a complete abstraction can be achieved with the use of abstract classes. The reason why abstraction is considered as one of the important concepts is:
|
||||
- Bootstrap helps in building responsive UI components.
|
||||
- Grid system, forms, buttons, navbars, modals etc. are supported.
|
||||
- Integration involves adding Bootstrap CSS/JS in layout or view.
|
||||
|
||||
1. It reduces the complexity of viewing things.
|
||||
2. Avoids code duplication and increases reusability.
|
||||
3. Helps to increase security of an application or program as only important details are provided to the user.
|
||||
### Part 4: Tag Helpers and HTML Helpers
|
||||
|
||||
#### Tag Helpers:
|
||||
|
||||
- Looks like HTML with `asp-*` attributes
|
||||
- Example: `<a asp-controller="Home" asp-action="About">Link</a>`
|
||||
- Requires `@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers` in `_ViewImports.cshtml`
|
||||
|
||||
#### HTML Helpers:
|
||||
|
||||
- Use C# syntax like `@Html.TextBoxFor(...)`, `@Html.BeginForm()`
|
||||
- More verbose but offers fine control with C# expressions
|
||||
|
||||
#### Comparison:
|
||||
|
||||
| Feature | Tag Helpers | HTML Helpers |
|
||||
| ----------- | ----------- | ------------ |
|
||||
| Syntax | HTML-like | C# methods |
|
||||
| Readability | High | Moderate |
|
||||
| Use | `asp-*` | `@Html.*` |
|
||||
|
||||
### Part 5: View Components
|
||||
|
||||
- View components are reusable UI elements with server-side logic.
|
||||
- Similar to partial views but support code execution (e.g., DB queries).
|
||||
- Suitable for dynamic parts like shopping carts or recent posts.
|
||||
|
||||
### Part 6: ViewImports and ViewStart
|
||||
|
||||
- `_ViewStart.cshtml` sets the layout for Razor Pages. Placing one in a folder affects all views inside it.
|
||||
- `_ViewImports.cshtml` adds namespaces, tag helpers, etc.
|
||||
- Hierarchical: Local files override root-level ones.
|
||||
|
||||
### Part 7: ViewData vs ViewBag
|
||||
|
||||
| Feature | ViewData | ViewBag |
|
||||
| ------------------ | ----------------- | ------------- |
|
||||
| Type | Dictionary | Dynamic |
|
||||
| Access | `ViewData["Key"]` | `ViewBag.Key` |
|
||||
| Compile-time check | ❌ | ❌ |
|
||||
| Shared storage | ✅ | ✅ |
|
||||
|
||||
- Use ViewBag for simpler, cleaner access; ViewData for explicit key-value access.
|
||||
- Both are weakly typed and best avoided in favor of ViewModels in large apps.
|
||||
|
||||
### Part 8: OOP Concepts in MVC
|
||||
|
||||
#### Encapsulation
|
||||
|
||||
- Use `private` fields with public `get`/`set` properties.
|
||||
- Prevents external access to internal data structures.
|
||||
|
||||
#### DTO (Data Transfer Object)
|
||||
|
||||
- Used to carry data between layers.
|
||||
- Reduces coupling and increases control over exposed data.
|
||||
|
||||
#### Inheritance
|
||||
|
||||
- Share common logic between base and derived classes.
|
||||
- Enables better reuse and organization.
|
||||
|
||||
#### Polymorphism
|
||||
|
||||
- **Compile-time**: Method overloading.
|
||||
- **Runtime**: Method overriding.
|
||||
- One interface, many implementations.
|
||||
|
||||
#### Abstraction
|
||||
|
||||
- Hides complex implementation from the user.
|
||||
- Achieved via abstract classes or interfaces.
|
||||
|
||||
## 🧪 Practice
|
||||
|
||||
- Create a view with a layout and partial
|
||||
- Use Razor syntax to display dynamic data
|
||||
- Build a form with Tag Helpers
|
||||
- Refactor a view using HTML Helpers
|
||||
- Create and render a View Component
|
||||
- Use `_ViewStart.cshtml` and `_ViewImports.cshtml` for configuration
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
Sources:
|
||||
|
||||
- [Microsoft Learn - Razor](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/razor?view=aspnetcore-9.0)
|
||||
- [Microsoft Learn - Views](https://learn.microsoft.com/en-us/aspnet/core/mvc/views/overview?view=aspnetcore-9.0)
|
||||
- [W3Schools - Bootstrap](https://www.w3schools.com/bootstrap/bootstrap_ver.asp)
|
||||
- [GeeksforGeeks - OOP in C#](https://www.geeksforgeeks.org/c-sharp-oops-concepts/)
|
||||
- ChatGPT Assistance (2025 sessions)
|
||||
|
||||
@@ -1,701 +1,128 @@
|
||||
# Session 5: Interfaces and Object-Oriented Relationships
|
||||
|
||||
## 📝 Overview
|
||||
|
||||
# Part 1: Interfaces
|
||||
In this session, we explored:
|
||||
|
||||
- The concept and syntax of **Interfaces** in C#
|
||||
- Implementation of interfaces in real scenarios
|
||||
- Comparison of **Abstract Classes vs Interfaces**
|
||||
- Key OOP relationships: **Inheritance**, **Composition**, **Aggregation**, **Association**, and **Dependency**
|
||||
- Applying these relationships in a **Library Management System**
|
||||
|
||||
Stack Overflow:
|
||||
https://stackoverflow.com/questions/2866987/what-is-the-definition-of-interface-in-object-oriented-programming
|
||||
## 📚 Topics Covered
|
||||
|
||||
An interface is one of the more overloaded and confusing terms in development.
|
||||
### Interfaces in C#
|
||||
|
||||
It is actually a concept of abstraction and encapsulation. For a given "box", it _declares_ the "inputs" and "outputs" of that box. In the world of software, that usually means the operations that can be invoked on the box (along with arguments) and in some cases the return types of these operations.
|
||||
> Interfaces define contracts that classes must fulfill. They enable loose coupling and multiple inheritance in C#.
|
||||
|
||||
What it does not do is define what the semantics of these operations are, although it is commonplace (and very good practice) to document them in proximity to the declaration (e.g., via comments), or to pick good naming conventions. Nevertheless, there are no guarantees that these intentions would be followed.
|
||||
- Syntax: `interface IMyInterface { void Method(); }`
|
||||
- Implementation: `class MyClass : IMyInterface`
|
||||
- All members are `public` and `abstract` by default
|
||||
- Cannot contain fields
|
||||
- Supports multiple inheritance
|
||||
|
||||
Here is an analogy: Take a look at your television when it is off. Its interface are the buttons it has, the various plugs, and the screen. Its semantics and behavior are that it takes inputs (e.g., cable programming) and has outputs (display on the screen, sound, etc.). However, when you look at a TV that is not plugged in, you are projecting your expected semantics into an interface. For all you know, the TV could just explode when you plug it in. However, based on its "interface" you can assume that it won't make any coffee since it doesn't have a water intake.
|
||||
### Interface Example
|
||||
|
||||
In object oriented programming, an interface generally defines the set of methods (or messages) that an instance of a class that has that interface could respond to.
|
||||
````c#
|
||||
interface IDisplayer { void Display(); }
|
||||
|
||||
What adds to the confusion is that in some languages, like Java, there is an actual interface with its language specific semantics. In Java, for example, it is a set of method declarations, with no implementation, but an interface also corresponds to a type and obeys various typing rules.
|
||||
|
||||
In other languages, like C++, you do not have interfaces. A class itself defines methods, but you could think of the interface of the class as the declarations of the non-private methods. Because of how C++ compiles, you get header files where you could have the "interface" of the class without actual implementation. You could also mimic Java interfaces with abstract classes with pure virtual functions, etc.
|
||||
|
||||
An interface is most certainly not a blueprint for a class. A blueprint, by one definition is a "detailed plan of action". An interface promises nothing about an action! The source of the confusion is that in most languages, if you have an interface type that defines a set of methods, the class that implements it "repeats" the same methods (but provides definition), so the interface looks like a skeleton or an outline of the class.
|
||||
|
||||
|
||||
|
||||
|
||||
Like a class, **_Interface_** can have methods, properties, events, and indexers as its members. But interfaces will contain only the declaration of the members. The implementation of the interface’s members will be given by class who implements the interface implicitly or explicitly.
|
||||
|
||||
- Interfaces specify what a class must do and not how.
|
||||
- Interfaces can’t have private members.
|
||||
- By default all the members of Interface are public and abstract.
|
||||
- The interface will always defined with the help of keyword ‘**_interface_**‘.
|
||||
- Interface cannot contain fields because they represent a particular implementation of data.
|
||||
- _Multiple inheritance_ is possible with the help of Interfaces but not with classes.
|
||||
|
||||
**Syntax for Interface Declaration:**
|
||||
|
||||
interface <interface_name >
|
||||
{
|
||||
// declare Events
|
||||
// declare indexers
|
||||
// declare methods
|
||||
// declare properties
|
||||
class Test : IDisplayer {
|
||||
public void Display() => Console.WriteLine("Hello from interface!");
|
||||
}
|
||||
|
||||
**Syntax for Implementing Interface:**
|
||||
### Abstract Class vs Interface
|
||||
|
||||
class class_name : interface_name
|
||||
|Feature|Abstract Class|Interface|
|
||||
|---|---|---|
|
||||
|Implementation Allowed?|Yes|No|
|
||||
|Multiple Inheritance|No|Yes|
|
||||
|Constructors|Yes|No|
|
||||
|Fields|Yes|No|
|
||||
|Use Case|Partial abstraction|Full abstraction|
|
||||
|
||||
To declare an interface, use _interface_ keyword. It is used to provide total abstraction. That means all the members in the interface are declared with the empty body and are public and abstract by default. A class that implements interface must implement all the methods declared in the interface.
|
||||
### OOP Relationships
|
||||
|
||||
- **Example 1:**
|
||||
```c#
|
||||
// C# program to demonstrate working of
|
||||
// interface
|
||||
using System;
|
||||
#### Inheritance (IS-A)
|
||||
|
||||
// A simple interface
|
||||
interface IDisplayer
|
||||
{
|
||||
// method having only declaration
|
||||
// not definition
|
||||
void display();
|
||||
}
|
||||
- A class inherits members from another class.
|
||||
|
||||
// A class that implements interface.
|
||||
class testClass : IDisplayer ,
|
||||
{
|
||||
|
||||
// providing the body part of function
|
||||
public void display()
|
||||
{
|
||||
Console.WriteLine("Sudo Placement GeeksforGeeks");
|
||||
}
|
||||
|
||||
// Main Method
|
||||
public static void Main (String []args)
|
||||
{
|
||||
// Creating object
|
||||
testClass t = new testClass();
|
||||
// calling method
|
||||
t.display();
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
- **Example 2:**
|
||||
```c#
|
||||
// C# program to illustrate the interface
|
||||
using System;
|
||||
|
||||
// interface declaration
|
||||
interface IVehicle {
|
||||
|
||||
// all are the abstract methods.
|
||||
void changeGear(int a);
|
||||
void speedUp(int a);
|
||||
void applyBrakes(int a);
|
||||
}
|
||||
|
||||
// class implements interface
|
||||
class Bicycle : IVehicle{
|
||||
|
||||
int speed;
|
||||
int gear;
|
||||
|
||||
// to change gear
|
||||
public void changeGear(int newGear)
|
||||
{
|
||||
|
||||
gear = newGear;
|
||||
}
|
||||
|
||||
// to increase speed
|
||||
public void speedUp(int increment)
|
||||
{
|
||||
|
||||
speed = speed + increment;
|
||||
}
|
||||
|
||||
// to decrease speed
|
||||
public void applyBrakes(int decrement)
|
||||
{
|
||||
|
||||
speed = speed - decrement;
|
||||
}
|
||||
|
||||
public void printStates()
|
||||
{
|
||||
Console.WriteLine("speed: " + speed +
|
||||
" gear: " + gear);
|
||||
}
|
||||
}
|
||||
|
||||
// class implements interface
|
||||
class Bike : IVehicle {
|
||||
|
||||
int speed;
|
||||
int gear;
|
||||
|
||||
// to change gear
|
||||
public void changeGear(int newGear)
|
||||
{
|
||||
|
||||
gear = newGear;
|
||||
}
|
||||
|
||||
// to increase speed
|
||||
public void speedUp(int increment)
|
||||
{
|
||||
speed = speed + increment;
|
||||
}
|
||||
|
||||
// to decrease speed
|
||||
public void applyBrakes(int decrement){
|
||||
|
||||
speed = speed - decrement;
|
||||
}
|
||||
|
||||
public void printStates()
|
||||
{
|
||||
Console.WriteLine("speed: " + speed +
|
||||
" gear: " + gear);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class GFG {
|
||||
|
||||
// Main Method
|
||||
public static void Main(String []args)
|
||||
{
|
||||
|
||||
// creating an instance of Bicycle
|
||||
// doing some operations
|
||||
Bicycle bicycle = new Bicycle();
|
||||
bicycle.changeGear(2);
|
||||
bicycle.speedUp(3);
|
||||
bicycle.applyBrakes(1);
|
||||
|
||||
Console.WriteLine("Bicycle present state :");
|
||||
bicycle.printStates();
|
||||
|
||||
// creating instance of bike.
|
||||
Bike bike = new Bike();
|
||||
bike.changeGear(1);
|
||||
bike.speedUp(4);
|
||||
bike.applyBrakes(3);
|
||||
|
||||
Console.WriteLine("Bike present state :");
|
||||
bike.printStates();
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
**Output:**
|
||||
Bicycle present state :
|
||||
speed: 2 gear: 2
|
||||
Bike present state :
|
||||
speed: 1 gear: 1
|
||||
|
||||
|
||||
**Advantage of Interface:**
|
||||
|
||||
- It is used to achieve loose coupling.
|
||||
- It is used to achieve total abstraction.
|
||||
- To achieve component-based programming
|
||||
- To achieve multiple inheritance and abstraction.
|
||||
- Interfaces add a plug and play like architecture into applications.
|
||||
|
||||
|
||||
https://www.geeksforgeeks.org/difference-between-abstract-class-and-interface-in-c-sharp/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Part 2: Relationships
|
||||
|
||||
|
||||
One of the advantages of Object-Oriented programming language is code reuse. This reusability is possible due to the relationship b/w the classes. Object oriented programming generally support 4 types of relationships that are: inheritance, association, composition, and aggregation. All these relationships are based on "is a" relationship, "has-a" relationship, and "part-of" relationship.
|
||||
|
||||
In this article, we will understand all these relationships.
|
||||
|
||||
## Inheritance
|
||||
|
||||
Inheritance is an “IS-A” type of relationship. The “IS-A” relationship is a totally based on Inheritance, which can be of two types Class Inheritance or Interface Inheritance. Inheritance is a parent-child relationship where we create a new class by using existing class code. It is just like saying that “A is a type of B”. For example “Apple is a fruit”, and “Ferrari is a car”.
|
||||
|
||||
For better understanding let us take a real-world scenario.
|
||||
|
||||
- HOD is a staff member of the college.
|
||||
- All teachers are staff members of the college.
|
||||
- HOD and teachers have ID cards to enter into college.
|
||||
- HOD has a staff that works according to the instructions of him.
|
||||
- HOD has the responsibility to undertake the work of the teacher to cover the course in the fixed time period.
|
||||
|
||||
Let us take the first two assumptions, “HOD is a staff member of the college” and “All teachers are staff members of the college”. For this assumption, we can create a “StaffMember” parent class and inherit this parent class in the “HOD” and “Teacher” classes.
|
||||
|
||||
```c#
|
||||
class StaffMember
|
||||
{
|
||||
public StaffMember()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
class HOD : StaffMember
|
||||
{
|
||||
public HOD()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
class Teacher : StaffMember
|
||||
{
|
||||
public Teacher()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
```c#
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static System.Console;
|
||||
namespace Entity2
|
||||
{
|
||||
class StaffMember
|
||||
{
|
||||
public int MemberId { get; set; }
|
||||
public string MemberName { get; set; }
|
||||
public string Department { get; set; }
|
||||
public StaffMember() { }
|
||||
}
|
||||
class HOD : StaffMember
|
||||
{
|
||||
public HOD() { }
|
||||
public int Course_Completed { get; set; }
|
||||
|
||||
public void Hod_Info()
|
||||
{
|
||||
string Info = $"Member Id = {this.MemberId} \n Member Name = {this.MemberName} \n Department Name = {this.Department} \n Total Course Completed = {this.Course_Completed} %";
|
||||
WriteLine(Info);
|
||||
}
|
||||
}
|
||||
class Teacher : StaffMember
|
||||
{
|
||||
public Teacher() { }
|
||||
public int Hod_Id { get; set; }
|
||||
public void Teacher_Info()
|
||||
{
|
||||
string Info = $"Member Id = {this.MemberId} \n Member Name = {this.MemberName} \n Department Name = {this.Department} \n Id of HOD = {this.Hod_Id}";
|
||||
WriteLine(Info);
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
HOD Obj_Hod = new HOD();
|
||||
Obj_Hod.MemberId = 10;
|
||||
Obj_Hod.MemberName = "Dazy Arya";
|
||||
Obj_Hod.Department = "CSE";
|
||||
Obj_Hod.Course_Completed = 85;
|
||||
|
||||
Teacher Obj_Tech = new Teacher();
|
||||
Obj_Tech.Department = "CSE";
|
||||
Obj_Tech.MemberId = 15;
|
||||
Obj_Tech.MemberName = "Ambika Gupta";
|
||||
Obj_Tech.Hod_Id = 10;
|
||||
|
||||
Obj_Hod.Hod_Info();
|
||||
Obj_Tech.Teacher_Info();
|
||||
ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Composition
|
||||
|
||||
Composition is a "part-of" relationship. Simply composition means mean use of instance variables that are references to other objects. In a composition relationship, both entities are interdependent on each other for example “engine is part of car”, and “heart is part of body”.
|
||||
|
||||
Let us take an example of a car and an engine. Engine is a part of each car and both are dependent on each other.
|
||||
|
||||
```c#
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static System.Console;
|
||||
namespace Entity2
|
||||
{
|
||||
class Car
|
||||
{
|
||||
public Car() { }
|
||||
public string Color { get; set; }
|
||||
public string Max_Speed { get; set; }
|
||||
public Engine Engine {get; set;}
|
||||
}
|
||||
class Suzuki : Car
|
||||
{
|
||||
public Suzuki()
|
||||
{
|
||||
Engine = new Engine(); // Eager Composition
|
||||
}
|
||||
|
||||
public Suzuki(Engine engine) // Eager Aggregation
|
||||
{
|
||||
Engine = engine;
|
||||
}
|
||||
|
||||
public int Total_Seats { get; set; }
|
||||
public string Model_No { get; set; }
|
||||
public void CarInfo()
|
||||
{
|
||||
string Info = $"Color of car is {this.Color} \nMaximum speed is {this.Max_Speed}\nNumber of seats is {this.Total_Seats}\nModel No is {this.Model_No}\n";
|
||||
WriteLine(Info);
|
||||
Engine.Engine_Info();
|
||||
}
|
||||
}
|
||||
class Engine
|
||||
{
|
||||
public void Engine_Info()
|
||||
{
|
||||
WriteLine("Engine is 4 stroke and fuel efficiency is good");
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Suzuki Obj = new Suzuki();
|
||||
Obj.Color = "Black";
|
||||
Obj.Max_Speed = "240KM/Hour";
|
||||
Obj.Model_No = "SUZ234";
|
||||
Obj.Total_Seats = 4;
|
||||
Obj.CarInfo();
|
||||
ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Association
|
||||
|
||||
The association is a “has-a” type relationship. The association establishes the relationship b/w two classes using their objects. Association relationships can be one-to-one, to-many, many-to-one, and many-to-many. For example, suppose we have two classes then these two classes are said to have a “has-a” relationship if both of these entities share each other’s object for some work and at the same time they can exist without each other's dependency or both have their own lifetime.
|
||||
|
||||
```c#
|
||||
class Employee
|
||||
{
|
||||
public Employee() { }
|
||||
public string Emp_Name { get; set; }
|
||||
|
||||
public void Manager_Name(Manager Obj)
|
||||
{
|
||||
Obj.manager_Info(this);
|
||||
}
|
||||
}
|
||||
class Manager
|
||||
{
|
||||
public Manager() { }
|
||||
public string Manager_Name { get; set; }
|
||||
public void manager_Info(Employee Obj)
|
||||
{
|
||||
WriteLine($"Manager of Employee {Obj.Emp_Name} is {this.Manager_Name}");
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Manager Man_Obj = new Manager();
|
||||
Man_Obj.Manager_Name = "Dazy Aray";
|
||||
Employee Emp_Obj = new Employee();
|
||||
Emp_Obj.Emp_Name = "Ambika";
|
||||
Emp_Obj.Manager_Name(Man_Obj);
|
||||
ReadLine();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
The above example shows an association relationship because both Employee and Manager classes use the object of each other and both their own independent life cycle.
|
||||
|
||||
## Aggregation
|
||||
|
||||
Aggregation is based on a "has-a" relationship. Aggregation is a special form of association. In association, there is not any classes (entities) that work as owners but in aggregation one entity work as an owner. In aggregation, both entities meet for some work and then get separated. Aggregation is a one-way association.
|
||||
|
||||
### Example
|
||||
|
||||
Let us take an example of “Student” and “address”. Each student must have an address so the relationship b/w Student class and Address class will be a “Has-A” type relationship but vice versa is not true(it is not necessary that each address contain by any student). So Students work as owner entities. This will be an aggregation relationship.
|
||||
|
||||
```c#
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using static System.Console;
|
||||
namespace Entity2
|
||||
{
|
||||
class Student_
|
||||
{
|
||||
public Student_() { }
|
||||
public string Name { get; set; }
|
||||
public int roll_No { get; set; }
|
||||
public int Class { get; set; }
|
||||
public void Get_Student_Info(Address Obj)
|
||||
{
|
||||
WriteLine($"Student Name={this.Name}\n Roll_No={this.roll_No}\n Class={this.Class}\n");
|
||||
Obj.Get_Address();
|
||||
}
|
||||
}
|
||||
class Address
|
||||
{
|
||||
public Address() { }
|
||||
public string Street { get; set; }
|
||||
public string City { get; set; }
|
||||
public string State { get; set; }
|
||||
public string Pincode { get; set; }
|
||||
public void Get_Address()
|
||||
{
|
||||
WriteLine($"Street={this.Street} \n City={this.City} \n State={this.State}\n Pincode={this.Pincode}");
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Student_ Stu_Obj = new Student_();
|
||||
Stu_Obj.Name = "Pankaj Choudhary";
|
||||
Stu_Obj.roll_No = 1210038;
|
||||
Stu_Obj.Class = 12;
|
||||
|
||||
Address Obj = new Address();
|
||||
Obj.City = "Alwar";
|
||||
Obj.Street = "P-20 Gandhi Nagar";
|
||||
Obj.State = "Rajasthan";
|
||||
Obj.Pincode = "301001";
|
||||
|
||||
Stu_Obj.Get_Student_Info(Obj);
|
||||
ReadLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
https://www.c-sharpcorner.com/article/types-of-relationships-in-object-oriented-programming-oops/
|
||||
|
||||
|
||||
## Dependency
|
||||
|
||||
#### Definition:
|
||||
|
||||
Dependency is a relationship where one class depends on another class for its functionality, but this is a temporary relationship. A dependent class uses another class within a method, often as a parameter or locally instantiated object.
|
||||
|
||||
#### Key Points:
|
||||
|
||||
- Represents a **temporary relationship**.
|
||||
- Occurs when a method in one class uses another class.
|
||||
- Does not create long-term connections between classes.
|
||||
|
||||
#### Example:
|
||||
|
||||
`class Printer { public void Print(string content) => Console.WriteLine($"Printing: {content}"); } class Report { public void Generate(Printer printer) { printer.Print("Report Content"); } }`
|
||||
|
||||
Here, `Report` depends on `Printer` to print the report, but there’s no persistent association.
|
||||
|
||||
https://medium.com/@humzakhalid94/understanding-object-oriented-relationships-inheritance-association-composition-and-aggregation-4d298494ac1c
|
||||
|
||||
![[Pasted image 20241203000244.png]]
|
||||
|
||||
### **Scenario: Library Management System**
|
||||
|
||||
We will build a simple Library Management System that includes the following:
|
||||
|
||||
- **Inheritance (IS-A Relationship):**
|
||||
- A `Person` base class is inherited by `Librarian` and `Member`.
|
||||
- **Composition (PART-OF Relationship):**
|
||||
- A `Library` class contains instances of other objects like `Bookshelf`, `Book`, and `LibraryCard`.
|
||||
- **Association (HAS-A Relationship):**
|
||||
- Members and Librarians interact using `LibraryCard` to borrow or issue books.
|
||||
- **Aggregation (Ownership Relationship):**
|
||||
- `Member` aggregates `Address`. The `Address` can exist independently of a `Member`.
|
||||
|
||||
---
|
||||
|
||||
### **Code Implementation**
|
||||
- Promotes reusability.
|
||||
|
||||
|
||||
```c#
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
class Person { }
|
||||
class Student : Person { }
|
||||
````
|
||||
|
||||
namespace LibraryManagementSystem
|
||||
{
|
||||
// Inheritance: Base class Person
|
||||
class Person
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public int Age { get; set; }
|
||||
}
|
||||
#### Composition (PART-OF)
|
||||
|
||||
// Inheritance: Derived class Librarian (IS-A Person)
|
||||
class Librarian : Person
|
||||
{
|
||||
public void IssueBook(Member member, Book book)
|
||||
{
|
||||
Console.WriteLine($"{Name} (Librarian) issued '{book.Title}' to {member.Name}.");
|
||||
}
|
||||
}
|
||||
|
||||
// Inheritance: Derived class Member (IS-A Person)
|
||||
class Member : Person
|
||||
{
|
||||
public LibraryCard Card { get; set; } // Association with LibraryCard
|
||||
public Address MemberAddress { get; set; } // Aggregation with Address
|
||||
}
|
||||
|
||||
// Composition: Library contains other objects
|
||||
class Library
|
||||
{
|
||||
public string LibraryName { get; set; }
|
||||
public List<Bookshelf> Bookshelves { get; set; }
|
||||
public Library()
|
||||
{
|
||||
Bookshelves = new List<Bookshelf>();
|
||||
}
|
||||
|
||||
public void AddBookshelf(Bookshelf shelf)
|
||||
{
|
||||
Bookshelves.Add(shelf);
|
||||
}
|
||||
|
||||
public void DisplayLibraryInfo()
|
||||
{
|
||||
Console.WriteLine($"Welcome to {LibraryName} Library!");
|
||||
Console.WriteLine($"We have {Bookshelves.Count} bookshelves.");
|
||||
}
|
||||
}
|
||||
|
||||
// Composition: Bookshelf is part of Library
|
||||
class Bookshelf
|
||||
{
|
||||
public int ShelfNumber { get; set; }
|
||||
public List<Book> Books { get; set; } = new List<Book>();
|
||||
|
||||
public void AddBook(Book book)
|
||||
{
|
||||
Books.Add(book);
|
||||
}
|
||||
}
|
||||
|
||||
// Association: Book can be shared between Members and Library
|
||||
class Book
|
||||
{
|
||||
public string Title { get; set; }
|
||||
public string Author { get; set; }
|
||||
}
|
||||
|
||||
// Aggregation: Address can exist independently of Member
|
||||
class Address
|
||||
{
|
||||
public string Street { get; set; }
|
||||
public string City { get; set; }
|
||||
public string State { get; set; }
|
||||
public string Pincode { get; set; }
|
||||
}
|
||||
|
||||
// Composition: LibraryCard is a part of Member
|
||||
class LibraryCard
|
||||
{
|
||||
public int CardNumber { get; set; }
|
||||
public DateTime IssuedDate { get; set; }
|
||||
}
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
// Create Library
|
||||
Library library = new Library { LibraryName = "Central Library" };
|
||||
|
||||
// Create Bookshelf and Books
|
||||
Bookshelf shelf1 = new Bookshelf { ShelfNumber = 1 };
|
||||
shelf1.AddBook(new Book { Title = "C# Programming", Author = "John Doe" });
|
||||
shelf1.AddBook(new Book { Title = "Data Structures", Author = "Jane Smith"});
|
||||
|
||||
// Add Bookshelf to Library (Composition)
|
||||
library.AddBookshelf(shelf1);
|
||||
|
||||
// Display Library Info
|
||||
library.DisplayLibraryInfo();
|
||||
|
||||
// Create Member with Aggregated Address
|
||||
Address memberAddress = new Address
|
||||
{
|
||||
Street = "123 Main St",
|
||||
City = "Metropolis",
|
||||
State = "NY",
|
||||
Pincode = "10001"
|
||||
};
|
||||
|
||||
Member member = new Member
|
||||
{
|
||||
Name = "Alice",
|
||||
Age = 25,
|
||||
MemberAddress = memberAddress,
|
||||
Card = new LibraryCard { CardNumber = 101, IssuedDate = DateTime.Now }
|
||||
};
|
||||
|
||||
// Create Librarian
|
||||
Librarian librarian = new Librarian
|
||||
{
|
||||
Name = "Mr. Smith",
|
||||
Age = 40
|
||||
};
|
||||
|
||||
// Issue Book (Association)
|
||||
Book selectedBook = shelf1.Books[0]; // Select the first book on the shelf
|
||||
librarian.IssueBook(member, selectedBook);
|
||||
|
||||
// Display Member Info and Address
|
||||
Console.WriteLine($"Member Info:\nName: {member.Name}\nAddress: {member.MemberAddress.Street}, {member.MemberAddress.City}");
|
||||
}
|
||||
}
|
||||
}
|
||||
- Objects are composed of other objects.
|
||||
- Strong lifecycle dependency.
|
||||
|
||||
```c#
|
||||
class Engine { }
|
||||
class Car { Engine engine = new Engine(); }
|
||||
```
|
||||
|
||||
---
|
||||
#### Association (HAS-A)
|
||||
|
||||
### **Concepts Explained**
|
||||
- Loose relationship between objects.
|
||||
- Both can exist independently.
|
||||
|
||||
1. **Inheritance (IS-A Relationship):**
|
||||
- `Librarian` and `Member` inherit from `Person`.
|
||||
- Both are specialized versions of `Person` with additional functionality.
|
||||
2. **Composition (PART-OF Relationship):**
|
||||
- A `Library` contains `Bookshelf` instances.
|
||||
- A `Bookshelf` contains `Book` instances.
|
||||
- A `LibraryCard` is part of `Member`.
|
||||
3. **Association (HAS-A Relationship):**
|
||||
- `Librarian` interacts with `Member` and `Book` for issuing books.
|
||||
- `Library` can exist without `Librarian` or `Member`.
|
||||
4. **Aggregation (Ownership Relationship):**
|
||||
- A `Member` has an `Address`.
|
||||
- An `Address` can exist independently of a `Member`.
|
||||
```c#
|
||||
class Teacher { }
|
||||
class School {
|
||||
public void AddTeacher(Teacher t) { }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
This example integrates all object-oriented relationships in a cohesive project.
|
||||
#### Aggregation (WEAK-PART-OF)
|
||||
|
||||
- Special association where one object "owns" another but the owned object can exist independently.
|
||||
|
||||
```c#
|
||||
class Address { }
|
||||
class Student {
|
||||
public Address address;
|
||||
}
|
||||
```
|
||||
|
||||
#### Dependency
|
||||
|
||||
- Temporary usage of one class by another.
|
||||
|
||||
```c#
|
||||
class Printer { void Print(string msg) => Console.WriteLine(msg); }
|
||||
class Report { void Generate(Printer p) => p.Print("Report"); }
|
||||
```
|
||||
|
||||
### Applied Example: Library Management System
|
||||
|
||||
A real-world example combining all relationships:
|
||||
|
||||
- **Person → Member/Librarian** (Inheritance)
|
||||
- **Library → Bookshelf → Book** (Composition)
|
||||
- **Member ↔ LibraryCard** (Association)
|
||||
- **Member → Address** (Aggregation)
|
||||
- **Report.Generate(Printer)** (Dependency)
|
||||
|
||||
✔ See full code snippet [here](https://chatgpt.com/c/68715298-27f8-8010-a29b-8f6e457f6179#) or review it during the live session.
|
||||
|
||||
## 🧪 Practice Tasks
|
||||
|
||||
- Implement an `IVehicle` interface in two different classes.
|
||||
- Use composition to build a `Computer` with `CPU`, `RAM`, and `HardDrive`.
|
||||
- Demonstrate aggregation with `Employee` and `Address`.
|
||||
- Create an association between `Doctor` and `Patient`.
|
||||
- Write a class `Order` that depends on `PaymentProcessor`.
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
Sources:
|
||||
|
||||
- StackOverflow
|
||||
- GeeksforGeeks
|
||||
- C# Corner
|
||||
- Medium
|
||||
- ChatGPT Assistance (2025 sessions)
|
||||
|
||||
@@ -1,7 +1,369 @@
|
||||
# Session 6: SOLID Principles and Dependency Injection (DI)
|
||||
|
||||
# Part 3: SOLID Principle
|
||||
https://www.geeksforgeeks.org/solid-principle-in-programming-understand-with-real-life-examples/
|
||||
## 📝 Overview
|
||||
|
||||
In this session, we will learn two foundational concepts for writing clean, maintainable, and scalable software:
|
||||
|
||||
# Part 4: DI
|
||||
https://www.geeksforgeeks.org/dependency-injectiondi-design-pattern/
|
||||
- **SOLID Principles:** Five key design principles that help create better object-oriented designs.
|
||||
- **Dependency Injection (DI):** A design pattern to manage class dependencies, improve modularity, and facilitate testing.
|
||||
|
||||
---
|
||||
|
||||
## 📚 Topics Covered
|
||||
|
||||
### ✅ SOLID Principles
|
||||
|
||||
- Single Responsibility Principle (SRP)
|
||||
- Open/Closed Principle (OCP)
|
||||
- Liskov Substitution Principle (LSP)
|
||||
- Interface Segregation Principle (ISP)
|
||||
- Dependency Inversion Principle (DIP)
|
||||
|
||||
### ✅ Dependency Injection (DI)
|
||||
|
||||
- What is DI and why use it
|
||||
- Types of DI: Constructor, Setter, Interface injection
|
||||
- Benefits of DI
|
||||
- Real-life analogy
|
||||
- Detailed examples in C#
|
||||
- DI frameworks overview
|
||||
|
||||
---
|
||||
|
||||
## 📌 Notes
|
||||
|
||||
### Part 3: SOLID Principles
|
||||
|
||||
SOLID is an acronym for five design principles aimed at improving code quality:
|
||||
|
||||
---
|
||||
|
||||
#### 1. Single Responsibility Principle (SRP)
|
||||
|
||||
- A class should have only one reason to change.
|
||||
- Meaning: Each class should only do one thing or handle one responsibility.
|
||||
|
||||
**Example:**
|
||||
|
||||
```c#
|
||||
class Invoice {
|
||||
public void CalculateTotal() { /* calculation code */ }
|
||||
public void PrintInvoice() { /* printing code */ } // Violates SRP
|
||||
}
|
||||
```
|
||||
|
||||
Better to separate:
|
||||
|
||||
```c#
|
||||
class InvoiceCalculator {
|
||||
public void CalculateTotal() { /* calculation code */ }
|
||||
}
|
||||
|
||||
class InvoicePrinter {
|
||||
public void PrintInvoice() { /* printing code */ }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 2. Open/Closed Principle (OCP)
|
||||
|
||||
- Software entities (classes, modules, functions) should be open for extension but closed for modification.
|
||||
- You should be able to add new features without changing existing code.
|
||||
|
||||
**Example:**
|
||||
|
||||
```c#
|
||||
abstract class Shape {
|
||||
public abstract double Area();
|
||||
}
|
||||
|
||||
class Rectangle : Shape {
|
||||
public double Width, Height;
|
||||
public override double Area() => Width * Height;
|
||||
}
|
||||
|
||||
class Circle : Shape {
|
||||
public double Radius;
|
||||
public override double Area() => Math.PI * Radius * Radius;
|
||||
}
|
||||
```
|
||||
|
||||
You can add new shapes without modifying existing ones.
|
||||
|
||||
---
|
||||
|
||||
#### 3. Liskov Substitution Principle (LSP)
|
||||
|
||||
- Objects of a superclass should be replaceable with objects of subclasses without affecting the correctness of the program.
|
||||
|
||||
**Example Violation:**
|
||||
|
||||
```c#
|
||||
class Bird {
|
||||
public virtual void Fly() { }
|
||||
}
|
||||
|
||||
class Ostrich : Bird {
|
||||
public override void Fly() {
|
||||
throw new Exception("Ostriches can't fly!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Better to redesign so `Ostrich` is not forced to implement unsupported behavior.
|
||||
|
||||
---
|
||||
|
||||
#### 4. Interface Segregation Principle (ISP)
|
||||
|
||||
- Clients should not be forced to depend on interfaces they do not use.
|
||||
- Split large interfaces into smaller, more specific ones.
|
||||
|
||||
**Example:**
|
||||
|
||||
```c#
|
||||
interface IWorker {
|
||||
void Work();
|
||||
void Eat();
|
||||
}
|
||||
|
||||
class Robot : IWorker {
|
||||
public void Work() { /* working */ }
|
||||
public void Eat() { throw new NotImplementedException(); } // Violation
|
||||
}
|
||||
```
|
||||
|
||||
Better to split:
|
||||
|
||||
```c#
|
||||
interface IWorkable {
|
||||
void Work();
|
||||
}
|
||||
|
||||
interface IFeedable {
|
||||
void Eat();
|
||||
}
|
||||
|
||||
class Robot : IWorkable {
|
||||
public void Work() { /* working */ }
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 5. Dependency Inversion Principle (DIP)
|
||||
|
||||
- High-level modules should not depend on low-level modules; both should depend on abstractions.
|
||||
- Abstractions should not depend on details; details should depend on abstractions.
|
||||
|
||||
**Example:**
|
||||
|
||||
Instead of:
|
||||
|
||||
```c#
|
||||
class BackendDeveloper {
|
||||
public void Develop() { /* backend code */ }
|
||||
}
|
||||
|
||||
class FrontendDeveloper {
|
||||
public void Develop() { /* frontend code */ }
|
||||
}
|
||||
|
||||
class Project {
|
||||
BackendDeveloper backend = new BackendDeveloper();
|
||||
FrontendDeveloper frontend = new FrontendDeveloper();
|
||||
|
||||
public void DevelopProject() {
|
||||
backend.Develop();
|
||||
frontend.Develop();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Use abstraction:
|
||||
|
||||
```c#
|
||||
interface IDeveloper {
|
||||
void Develop();
|
||||
}
|
||||
|
||||
class BackendDeveloper : IDeveloper { public void Develop() { } }
|
||||
class FrontendDeveloper : IDeveloper { public void Develop() { } }
|
||||
|
||||
class Project {
|
||||
private IDeveloper _developer1;
|
||||
private IDeveloper _developer2;
|
||||
|
||||
public Project(IDeveloper dev1, IDeveloper dev2) {
|
||||
_developer1 = dev1;
|
||||
_developer2 = dev2;
|
||||
}
|
||||
|
||||
public void DevelopProject() {
|
||||
_developer1.Develop();
|
||||
_developer2.Develop();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Part 4: Dependency Injection (DI)
|
||||
|
||||
---
|
||||
|
||||
#### What is Dependency Injection?
|
||||
|
||||
Dependency Injection is a design pattern where an object receives the objects it depends on, rather than creating them itself.
|
||||
|
||||
**Analogy:** Ordering coffee from a cafe instead of growing coffee beans yourself.
|
||||
|
||||
---
|
||||
|
||||
#### Types of Dependency Injection
|
||||
|
||||
| Type | Description | Example Usage |
|
||||
| ------------------------- | ---------------------------------------------- | ------------------------------------ |
|
||||
| **Constructor Injection** | Dependencies passed via constructor parameters | `public Car(IEngine engine) { ... }` |
|
||||
| **Setter Injection** | Dependencies set via properties or setters | `car.Engine = new DieselEngine();` |
|
||||
| **Interface Injection** | Dependencies injected via interface methods | `void SetEngine(IEngine engine);` |
|
||||
|
||||
---
|
||||
|
||||
#### Benefits of DI
|
||||
|
||||
- Loosely coupled code
|
||||
- Easier testing (mock dependencies)
|
||||
- Clear dependency declaration
|
||||
- Easier maintenance and flexibility
|
||||
- Supports Inversion of Control (IoC)
|
||||
|
||||
---
|
||||
|
||||
#### Examples
|
||||
|
||||
**Constructor Injection:**
|
||||
|
||||
```c#
|
||||
public interface IEngine {
|
||||
void Start();
|
||||
}
|
||||
|
||||
public class DieselEngine : IEngine {
|
||||
public void Start() { Console.WriteLine("Diesel engine started."); }
|
||||
}
|
||||
|
||||
public class Car {
|
||||
private IEngine _engine;
|
||||
|
||||
public Car(IEngine engine) { _engine = engine; }
|
||||
|
||||
public void StartCar() { _engine.Start(); }
|
||||
}
|
||||
|
||||
// Usage:
|
||||
IEngine engine = new DieselEngine();
|
||||
Car car = new Car(engine);
|
||||
car.StartCar();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Setter Injection:**
|
||||
|
||||
```c#
|
||||
public class Car {
|
||||
private IEngine _engine;
|
||||
|
||||
public IEngine Engine {
|
||||
set { _engine = value; }
|
||||
}
|
||||
|
||||
public void StartCar() {
|
||||
if (_engine == null) Console.WriteLine("Engine not set!");
|
||||
else _engine.Start();
|
||||
}
|
||||
}
|
||||
|
||||
// Usage:
|
||||
Car car = new Car();
|
||||
car.Engine = new DieselEngine();
|
||||
car.StartCar();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
**Interface Injection:**
|
||||
|
||||
```c#
|
||||
public interface IEngineSetter {
|
||||
void SetEngine(IEngine engine);
|
||||
}
|
||||
|
||||
public class Car : IEngineSetter {
|
||||
private IEngine _engine;
|
||||
|
||||
public void SetEngine(IEngine engine) {
|
||||
_engine = engine;
|
||||
}
|
||||
|
||||
public void StartCar() { _engine?.Start(); }
|
||||
}
|
||||
|
||||
// Usage:
|
||||
Car car = new Car();
|
||||
car.SetEngine(new DieselEngine());
|
||||
car.StartCar();
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### DI Frameworks & Containers
|
||||
|
||||
- Manual injection can be tedious.
|
||||
- Frameworks automate dependency management.
|
||||
- Popular .NET DI frameworks:
|
||||
- Microsoft.Extensions.DependencyInjection (built-in ASP.NET Core)
|
||||
- Autofac
|
||||
- Ninject
|
||||
- Unity
|
||||
|
||||
**Example in ASP.NET Core:**
|
||||
|
||||
```c#
|
||||
// Startup.cs or Program.cs
|
||||
services.AddTransient<IEngine, DieselEngine>();
|
||||
services.AddTransient<Car>();
|
||||
|
||||
// Usage in constructor
|
||||
public class MyController {
|
||||
private readonly Car _car;
|
||||
|
||||
public MyController(Car car) {
|
||||
_car = car;
|
||||
}
|
||||
|
||||
public void Drive() {
|
||||
_car.StartCar();
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Practice
|
||||
|
||||
- Refactor a tightly coupled class using constructor injection.
|
||||
- Create multiple implementations of a service interface and switch between them using DI.
|
||||
- Implement setter injection and observe behavior when dependency is missing.
|
||||
- Explore ASP.NET Core built-in DI container: register services and inject them in controllers.
|
||||
|
||||
---
|
||||
|
||||
## 🙏 References
|
||||
|
||||
- [SOLID Principles - GeeksforGeeks](https://www.geeksforgeeks.org/solid-principle-in-programming-understand-with-real-life-examples/)
|
||||
- [Dependency Injection (DI) - GeeksforGeeks](https://www.geeksforgeeks.org/dependency-injectiondi-design-pattern/)
|
||||
- [Microsoft Docs: Dependency Injection in ASP.NET Core](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection)
|
||||
- [Refactoring Guru: Dependency Injection](https://refactoring.guru/design-patterns/dependency-injection)
|
||||
|
||||
@@ -1,215 +1,93 @@
|
||||
# Dependency injection
|
||||
Dependency injection is a technique used in object-oriented programming ([OOP](https://www.techtarget.com/searchapparchitecture/definition/object-oriented-programming-OOP)) to reduce the hardcoded dependencies between objects. A dependency in this context refers to a piece of [code](https://www.techtarget.com/whatis/definition/code) that relies on another resource to carry out its intended function. Often, that resource is a different object in the same application.
|
||||
# Session 7: Dependency Injection, EF Core, and Abstract Classes vs Interfaces in OOP
|
||||
|
||||
Dependencies within an OOP application enable objects to perform their assigned tasks by providing additional functionality. For example, an application might include two class definitions: Class A and Class B. As part of its definition, Class B creates an instance of Class A to carry out a specific task, which means that Class B is dependent on Class A to carry out its function. The dependency is hardcoded into the Class B definition, resulting in code that is tightly coupled. Such code is more difficult to test, modify or reuse than [loosely coupled](https://www.techtarget.com/searchnetworking/definition/loose-coupling) code.
|
||||
## 📝 Overview
|
||||
|
||||
Instead of the dependency being hardcoded, it can be injected through a mechanism such as a class constructor or public property. In this scenario, Class A gets passed into Class B via a parameter, rather than Class B creating the object itself. Class B can then be compiled without including the entire Class A definition, resulting in a class that functions independently of its dependencies. The result is code that is more readable, maintainable, testable, reusable and flexible than tightly coupled code.
|
||||
|
||||
Dependency inversion is of particular importance when it comes to dependency injection. Dependency inversion focuses on decoupling and [abstracting](https://www.techtarget.com/whatis/definition/abstraction) code, rather than relying too heavily on concretions, which are hardcoded concrete implementations. Dependency inversion also ensures that high-level modules do not depend on low-level modules.
|
||||
|
||||
Dependency injection supports the dependency inversion principle by [injecting dependencies into the class definitions](https://www.theserverside.com/video/Dependency-injection-in-Spring) instead of hardcoding them. In this way, it abstracts the details and ensures that high-level modules don't depend on low-level modules.
|
||||
|
||||
1. **Service.** A class that carries out some type of functionality. Any object can be either a service or client. Which one it is depends on the role the object has in a particular injection.
|
||||
2. **Client.** A class that requests something from a service. A client can be any class that uses a service.
|
||||
3. **Interface.** A component implemented by a service for use by one or more clients. The component enables the client to access the service's functions, while abstracting the details of about how the service implements those functions, thus breaking dependencies between lower and higher classes.
|
||||
4. **Injector.** A component that introduces a service to a client. The injector creates a service instance and then inserts the service into a client. The injector can be many objects working together.
|
||||
|
||||
|
||||
## Advantages of dependency injection
|
||||
|
||||
Many development teams use dependency injection because it offers several important benefits:
|
||||
|
||||
- Code modules do not need to instantiate references to resources, and dependencies can be easily swapped out, even mock dependencies. By enabling the framework to do the resource creation, configuration data is centralized, and updates occur only in one place.
|
||||
- Injected resources can be customized through [Extensible Markup Language](https://www.techtarget.com/whatis/definition/XML-Extensible-Markup-Language) files outside the source code. This enables changes to be applied without having to recompile the entire codebase.
|
||||
- Programs are more testable, maintainable and reusable because the client classes do not need to know how dependencies are implemented.
|
||||
- Developers working on the same application can build classes independently of each other because they only need to know how to use the interfaces to the referenced classes, not the workings of the classes themselves.
|
||||
- Dependency injection helps in [unit testing](https://www.techtarget.com/searchsoftwarequality/definition/unit-testing) because configuration details can be saved to configuration files. This also enables the system to be reconfigured without recompiling.
|
||||
|
||||
## Disadvantages of dependency injection
|
||||
|
||||
Although dependency injection can be beneficial, it also comes with several challenges:
|
||||
|
||||
- Dependency injection makes troubleshooting difficult because much of the code is pushed into an unknown location that creates resources and distributes them as needed across the application.
|
||||
- Debugging code when misbehaving objects are buried in a complicated third-party framework can be frustrating and time-consuming.
|
||||
- Dependency injection can slow integrated development environment automation, as dependency injection frameworks use either reflection or dynamic programming.
|
||||
|
||||
|
||||
## Types of dependency injection
|
||||
|
||||
OOP supports the following [approaches to dependency injection](https://www.theserverside.com/video/Constructor-injection-vs-setter-injection-in-Spring-Boot?_gl=1*j2jgxa*_ga*Njg3MzcwOTcxLjE3MzA4NzQxNjM.*_ga_TQKE4GS5P9*MTczOTM1NTQ2NS45LjEuMTczOTM1NTUxOS4wLjAuMA..):
|
||||
|
||||
- **Constructor injection.** An injector uses a class constructor to inject the dependency. The referenced object is passed in as a parameter to the constructor.
|
||||
- **Setter (property) injection.** The client exposes a setter method that the injector uses to pass in the dependency.
|
||||
- **Method injection.** A client class is used to implement an interface. A [method](https://www.techtarget.com/whatis/definition/method) then provides the dependency, and an injector uses the interface to supply the dependency to the class.
|
||||
- **Interface injection.** An injector method, provided by a dependency, injects the dependency into another client. Clients then need to implement an interface that uses a setter method to accept the dependency.
|
||||
|
||||
|
||||
https://stackoverflow.com/questions/130794/what-is-dependency-injection
|
||||
|
||||
|
||||
|
||||
|
||||
# EF Core
|
||||
## Entity Framework Features
|
||||
|
||||
- **Cross-platform:** EF Core is a cross-platform framework which can run on Windows, Linux and Mac.
|
||||
- **Modelling:** EF (Entity Framework) creates an EDM (Entity Data Model) based on POCO (Plain Old CLR Object) entities with get/set properties of different data types. It uses this model when querying or saving entity data to the underlying database.
|
||||
- **Querying:** EF allows us to use LINQ queries (C#/VB.NET) to retrieve data from the underlying database. The database provider will translate this LINQ queries to the database-specific query language (e.g. SQL for a relational database). EF also allows us to execute raw SQL queries directly to the database.
|
||||
- **Change Tracking:** EF keeps track of changes occurred to instances of your entities (Property values) which need to be submitted to the database.
|
||||
- **Saving:** EF executes INSERT, UPDATE, and DELETE commands to the database based on the changes occurred to your entities when you call the `SaveChanges()` method. EF also provides the asynchronous `SaveChangesAsync()` method.
|
||||
- **Concurrency:** EF uses Optimistic Concurrency by default to protect overwriting changes made by another user since data was fetched from the database.
|
||||
- **Transactions:** EF performs automatic transaction management while querying or saving data. It also provides options to customize transaction management.
|
||||
- **Caching:** EF includes first level of caching out of the box. So, repeated querying will return data from the cache instead of hitting the database.
|
||||
- **Built-in Conventions:** EF follows conventions over the configuration programming pattern, and includes a set of default rules which automatically configure the EF model.
|
||||
- **Configurations:** EF allows us to configure the EF model by using data annotation attributes or Fluent API to override default conventions.
|
||||
- **Migrations:** EF provides a set of migration commands that can be executed on the NuGet Package Manager Console or the Command Line Interface to create or manage underlying database Schema.
|
||||
|
||||
https://stackoverflow.com/questions/3058/what-is-inversion-of-control
|
||||
|
||||
https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/
|
||||
|
||||
|
||||
# Why use abstract class in the examples?
|
||||
|
||||
|
||||
## **1. Scenario Overview**
|
||||
|
||||
Let’s say we have an interface `IService`, and three different classes (`ServiceA`, `ServiceB`, `ServiceC`) that share common functionality.
|
||||
|
||||
### **Approach 1: Each Class Implements the Interface Directly**
|
||||
![[Pasted image 20250212171204.png]]
|
||||
Each class provides its own implementation of `Execute()`. **No shared code exists among them**.
|
||||
This session covers key concepts of Dependency Injection (DI), Entity Framework Core (EF Core), and the differences between Abstract Classes and Interfaces in object-oriented programming.
|
||||
|
||||
---
|
||||
|
||||
### **Approach 2: Using an Abstract Base Class**
|
||||
## 📚 Topics Covered
|
||||
|
||||
If there’s common functionality across `ServiceA`, `ServiceB`, and `ServiceC`, we can introduce an **abstract class**:
|
||||
### ✅ Dependency Injection (DI)
|
||||
|
||||
- What is DI and why it matters in OOP
|
||||
- Key components: Service, Client, Interface, Injector
|
||||
- Advantages and disadvantages of DI
|
||||
- Types of DI: Constructor, Setter, Method, Interface injection
|
||||
- Relationship to the Dependency Inversion Principle
|
||||
|
||||
```c#
|
||||
public interface IService
|
||||
{
|
||||
void Execute();
|
||||
}
|
||||
### ✅ Entity Framework Core (EF Core)
|
||||
|
||||
public abstract class BaseService : IService
|
||||
{
|
||||
public void Log() => Console.WriteLine("Logging action"); // Common functionality
|
||||
- Cross-platform capabilities
|
||||
- Modeling with POCO classes and EDM
|
||||
- Querying using LINQ and raw SQL
|
||||
- Change tracking and concurrency
|
||||
- Transactions and caching
|
||||
- Configuration and migrations
|
||||
|
||||
public abstract void Execute(); // Forces derived classes to implement this
|
||||
}
|
||||
### ✅ Abstract Classes vs Interfaces
|
||||
|
||||
public class ServiceA : BaseService
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
Log();
|
||||
Console.WriteLine("Executing Service A");
|
||||
}
|
||||
}
|
||||
|
||||
public class ServiceB : BaseService
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
Log();
|
||||
Console.WriteLine("Executing Service B");
|
||||
}
|
||||
}
|
||||
|
||||
public class ServiceC : BaseService
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
Log();
|
||||
Console.WriteLine("Executing Service C");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here, `BaseService` provides **shared functionality** (e.g., `Log()`) so that `ServiceA`, `ServiceB`, and `ServiceC` don’t have to repeat the same logic.
|
||||
- Defining interfaces and abstract base classes
|
||||
- Code reuse and shared functionality with abstract classes
|
||||
- Flexibility and multiple inheritance with interfaces
|
||||
- When to use interfaces, abstract classes, or a combination
|
||||
- Real C# example demonstrating both
|
||||
|
||||
---
|
||||
|
||||
## **2. Comprehensive Comparison**
|
||||
## 📌 Notes
|
||||
|
||||
| Feature | Interface Only | Abstract Base Class |
|
||||
| -------------------------------- | ------------------------------------------------------------------------------- | ---------------------------------------------------------------------------- |
|
||||
| **Forces contract adherence** | ✅ Yes, all classes must implement the methods | ✅ Yes, but can provide default behavior |
|
||||
| **Allows multiple inheritance** | ✅ Yes (C# supports multiple interfaces) | ❌ No (C# doesn’t support multiple inheritance for classes) |
|
||||
| **Allows shared implementation** | ❌ No, each class must provide its own implementation | ✅ Yes, common functionality can be placed in the base class |
|
||||
| **Flexibility** | ✅ More flexible; any class can implement it without worrying about a base class | ❌ Less flexible; forces all classes to derive from the base class |
|
||||
| **Scalability** | ✅ Easy to scale and extend | ✅ Good if many classes share behavior |
|
||||
| **Testability** | ✅ Can be mocked easily | ✅ Can be mocked, but harder if logic is mixed |
|
||||
| **Encapsulation** | ❌ No default behavior | ✅ Can provide reusable, hidden logic |
|
||||
| **Dependency Injection (DI)** | ✅ Works well with DI | ✅ Works well, but makes DI a little more complex if constructor logic exists |
|
||||
### Dependency Injection (DI)
|
||||
|
||||
- DI reduces hardcoded dependencies by injecting required services into classes rather than creating them internally.
|
||||
- Promotes loose coupling, better maintainability, and testability.
|
||||
- Key players:
|
||||
- **Service:** Provides functionality
|
||||
- **Client:** Uses the service
|
||||
- **Interface:** Abstracts service implementation
|
||||
- **Injector:** Injects service instances into clients
|
||||
- DI supports the **Dependency Inversion Principle** by decoupling high-level modules from low-level implementations.
|
||||
- Common types:
|
||||
- **Constructor injection:** Dependencies passed via constructor parameters
|
||||
- **Setter injection:** Dependencies passed via public setter methods
|
||||
- **Method injection:** Dependencies passed through methods implementing an interface
|
||||
- **Interface injection:** Client implements interface with a method to accept dependency
|
||||
- Benefits: Easier mocking/testing, centralized config, modular development
|
||||
- Drawbacks: Harder debugging, potential performance impact with reflection-based DI frameworks
|
||||
|
||||
### Entity Framework Core (EF Core)
|
||||
|
||||
- EF Core is a cross-platform ORM for .NET to interact with databases using .NET objects.
|
||||
- Supports LINQ queries which translate to SQL behind the scenes.
|
||||
- Tracks changes to objects for efficient updates.
|
||||
- Uses optimistic concurrency control to avoid overwriting data accidentally.
|
||||
- Supports transactions automatically and provides first-level caching.
|
||||
- Offers configuration via conventions, annotations, or Fluent API.
|
||||
- Includes migration tools to evolve database schema alongside code changes.
|
||||
|
||||
### Abstract Classes vs Interfaces
|
||||
|
||||
- **Interfaces** define contracts without implementation, supporting multiple inheritance and maximum flexibility.
|
||||
- **Abstract classes** allow shared code with some method implementations and force subclasses to implement abstract methods.
|
||||
- Abstract classes cannot be multiply inherited in C# but reduce code duplication when shared behavior exists.
|
||||
- Use interfaces when implementations differ widely or multiple inheritance is needed.
|
||||
- Use abstract classes when shared logic reduces repetition.
|
||||
- Combining both gives flexibility (interface for DI) and code reuse (abstract base class).
|
||||
- Example provided demonstrates `IService` interface, `BaseService` abstract class with a `Log()` method, and concrete service classes overriding `Execute()`.
|
||||
|
||||
---
|
||||
|
||||
## **3. When to Use Each Approach**
|
||||
## 🧪 Practice
|
||||
|
||||
### **Use Only Interfaces When:**
|
||||
|
||||
✔️ **You need maximum flexibility** – Any class can implement `IService` without being tied to a base class.
|
||||
✔️ **Each class has very different implementations** – If `ServiceA`, `ServiceB`, and `ServiceC` have nothing in common besides the method signature.
|
||||
✔️ **You might need multiple inheritance** – Since C# **doesn’t support multiple class inheritance**, an interface allows a class to implement multiple behaviors.
|
||||
✔️ **You’re focusing on dependency inversion** – Interfaces work well with DI and keep components loosely coupled.
|
||||
|
||||
### **Use an Abstract Base Class When:**
|
||||
|
||||
✔️ **There’s shared behavior across implementations** – If all service classes require a `Log()` method or any other common logic.
|
||||
✔️ **You want partial implementation** – The base class can implement default behavior while forcing subclasses to implement required methods.
|
||||
✔️ **The hierarchy makes sense logically** – If all services are conceptually similar and should extend a base class.
|
||||
✔️ **You want to reduce code duplication** – The base class can contain reusable logic.
|
||||
- Implement a small ASP.NET Core project demonstrating constructor-based DI.
|
||||
- Create POCO entities and perform CRUD operations using EF Core.
|
||||
- Design and implement an interface and abstract class hierarchy with shared functionality and test the differences.
|
||||
- Explore swapping implementations using DI containers.
|
||||
|
||||
---
|
||||
|
||||
## **4. Hybrid Approach: Combining Both**
|
||||
## 🙏 References
|
||||
|
||||
Sometimes, you might **use both an interface and an abstract class** for more flexibility:
|
||||
|
||||
csharp
|
||||
|
||||
CopyEdit
|
||||
|
||||
```c#
|
||||
public interface IService
|
||||
{
|
||||
void Execute();
|
||||
}
|
||||
|
||||
public abstract class BaseService : IService
|
||||
{
|
||||
public void Log() => Console.WriteLine("Logging action");
|
||||
|
||||
public abstract void Execute();
|
||||
}
|
||||
|
||||
public class ServiceA : BaseService
|
||||
{
|
||||
public override void Execute()
|
||||
{
|
||||
Log();
|
||||
Console.WriteLine("Executing Service A");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This way:
|
||||
|
||||
- Clients can depend on **IService** (for DI flexibility).
|
||||
- `BaseService` provides common behavior **without enforcing its use**.
|
||||
|
||||
---
|
||||
|
||||
## **5. Conclusion**
|
||||
|
||||
- ✅ **Use interfaces** when **flexibility and loose coupling** are most important.
|
||||
- ✅ **Use abstract classes** when **code reuse and a shared structure** are beneficial.
|
||||
- ✅ **Use both** when you want **dependency inversion with shared functionality**.
|
||||
|
||||
Would you like a real-world ASP.NET Core example, like how DI containers work with abstract classes vs. interfaces? 🚀
|
||||
|
||||
|
||||
![[Pasted image 20250212184706.png]]
|
||||
- [Dependency Injection - GeeksforGeeks](https://www.geeksforgeeks.org/dependency-injectiondi-design-pattern/)
|
||||
- [A Quick Intro to Dependency Injection - FreeCodeCamp](https://www.freecodecamp.org/news/a-quick-intro-to-dependency-injection-what-it-is-and-when-to-use-it-7578c84fa88f/)
|
||||
- [EF Core Features - StackOverflow](https://stackoverflow.com/questions/3058/what-is-inversion-of-control)
|
||||
|
||||
Reference in New Issue
Block a user