ASP.NET MVC | Real World Project and Best Practices : Mastering
Tags: dotnet, aspdotnetmvc, programming, learning
Published: 2024-02-29 16:14:47

**Expense Quest App**
🚀 Let's learn together 

**MVC** Model-View-Controller, a design pattern used to develop user interfaces by dividing an application into three interconnected components. This separation helps manage complexity, enables easier testing, and allows multiple developers to work simultaneously on the application. 
**Model** The Model represents the data structure and business logic. For an expense tracker, the model might look something like this:

```csharp
public class Expense
{
    public int Id { get; set; }

    [Required(ErrorMessage = "Description is required")]
    [StringLength(100, ErrorMessage = "Description cannot be longer than 100 characters")]
    public string Description { get; set; }

    [Required(ErrorMessage = "Amount is required")]
    [Range(0.01, double.MaxValue, ErrorMessage = "Amount must be greater than 0")]
    public decimal Amount { get; set; }

    [Required(ErrorMessage = "Date is required")]
    [DataType(DataType.Date)]
    public DateTime Date { get; set; }
}
```

**View** The View displays the data from the model to the user. 

```csharp
@model IEnumerable<Expense>

<h2>Expenses</h2>
<table>
    <tr>
        <th>Description</th>
        <th>Amount</th>
        <th>Date</th>
    </tr>
    @foreach(var expense in Model)
    {
        <tr>
            <td>@expense.Description</td>
            <td>@String.Format("{0:C}", expense.Amount)</td>
            <td>@expense.Date.ToShortDateString()</td>
        </tr>
    }
</table>
```

**Controller** The Controller handles interactions, processes requests, and returns responses. For managing expenses, the ExpensesController might contain actions to list, add, and delete expenses:

```csharp
public class ExpensesController : Controller
{
    private readonly IExpenseRepository _repository; // Assuming an interface for data access

    public ExpensesController(IExpenseRepository repository)
    {
        _repository = repository;
    }

    public ActionResult Index()
    {
        var expenses = _repository.GetAllExpenses();
        return View(expenses); // Passes the list of expenses to the view
    }

    public ActionResult Add(Expense expense)
    {
        _repository.AddExpense(expense);
        return RedirectToAction("Index"); // Redirects to the list of expenses after adding
    }

    public ActionResult Delete(int id)
    {
        _repository.DeleteExpense(id);
        return RedirectToAction("Index"); // Redirects to the updated list of expenses
    }
}
```

> HTTP Methods

```csharp
  [HttpPost]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> Create([Bind("CategoryId,Title,Icon,Type")] Category category)
        {
            if (ModelState.IsValid)
            {
                _context.Add(category);
                await _context.SaveChangesAsync();
                return RedirectToAction(nameof(Index));
            }
            return View(category);
        }

 public async Task<IActionResult> Edit(int? id)
        {
            if (id == null)
            {
                return NotFound();
            }

            var category = await _context.Categories.FindAsync(id);
            if (category == null)
            {
                return NotFound();
            }
            return View(category);
        }

 [HttpPost, ActionName("Delete")]
        [ValidateAntiForgeryToken]
        public async Task<IActionResult> DeleteConfirmed(int id)
        {
            var category = await _context.Categories.FindAsync(id);
            if (category != null)
            {
                _context.Categories.Remove(category);
            }

            await _context.SaveChangesAsync();
            return RedirectToAction(nameof(Index));
        }

        private bool CategoryExists(int id)
        {
            return _context.Categories.Any(e => e.CategoryId == id);
        }
```
Workflow in ASP.NET MVC

- User Interaction: The process starts with the user interacting with the application, triggering an HTTP request to the server.

- Routing: ASP.NET MVC uses routing to map this request to a specific controller's action method.

- Controller Processing: The identified controller's action method executes. It may interact with the model to retrieve or manipulate data.

- View Rendering: The controller selects a view and passes it any necessary model data. The view then generates HTML to send back to the client.

- Response: The generated HTML is sent back to the browser, allowing the user to see the result.

This pattern promotes a clean separation of concerns, making ASP.NET MVC applications organized, scalable, and maintainable