MVC Controllers: BooksController.cs (Cont.)

using System;
The namespace contains fundamental classes and base classes that define commonly used value and reference data types, events and event handlers, interfaces, attributes, and processing exceptions.

using System.Collections.Generic;
The namespace contains interfaces and classes that define generic collections, which allow users to create strongly typed collections that provide better type safety and performance than non-generic strongly typed collections.

using System.Linq;
Language-Integrated Query (LINQ) is the name for a set of technologies based on the integration of query capabilities directly into the C# language.

using System.Threading.Tasks;
The Task class represents a single operation that does not return a value and that usually executes asynchronously.

using Microsoft.AspNetCore.Mvc;
It provides types required to build an MVC app.

using Microsoft.EntityFrameworkCore;
Entity Framework allows developers to work with relational data using domain-specific objects, eliminating the need for most of the data-access code that developers usually need to write.

 // GET: Books
 public async Task<IActionResult> Index( ) {
   return View( await _context.Book.ToListAsync( ) );
 }

async Task<IActionResult>
The async keyword marks a method as asynchronous, enabling the use of await within it.

await _context.Book.ToListAsync( )

  • The await keyword pauses the execution of the method until the awaited task completes, without blocking the thread.
  • The ToListAsync method to creates a List<T> by enumerating it asynchronously.

 // GET: Books/Details/5
 public async Task<IActionResult> Details( int? id ) {
   if ( id == null ) { return NotFound( ); }
   var book = await _context.Book.FirstOrDefaultAsync( m => m.Id == id );
   if ( book == null ) { return NotFound( ); }
   return View( book );
 }

int? id
It means the id might not always have a value, such as optional foreign keys or when the value is not yet assigned.

return NotFound( );
The method creates a NotFoundResult that produces a Status404NotFound response.

FirstOrDefaultAsync
The FirstOrDefaultAsync() method asynchronously returns the first element of a sequence, or a default value if the sequence contains no elements.

m => m.Id == id
It is a lambda expression often used in data access technologies like LINQ (Language Integrated Query) and Entity Framework:


  • Lambda Operator (=>): This separates the input parameters from the expression body.
  • m: This is a parameter representing an object, such as a row in a database table or an item in a list.
  • m.Id: This refers to the “Id” property of the object represented by “m.” This is commonly used for a primary key.
  • ==: This is the equality operator, comparing the value of m.Id with the value of id.
  • id: This is a variable that typically holds the ID you are trying to match.

return View( book );
The View() method can also accept a model object as an argument, which allows you to pass data from the controller to the view for rendering.

 // POST: Books/Create
 [ HttpPost ]
 [ ValidateAntiForgeryToken ]
 public async Task<IActionResult> Create(
     [ Bind( "Id, Title, Genre, Price, PublishDate" ) ] Book book ) {
   if ( ModelState.IsValid ) {
     _context.Add( book );
     await _context.SaveChangesAsync( );
     return RedirectToAction( nameof( Index ) );
   }
   return View( book );
 }

[ HttpPost ]
The [HttpPost] attribute is used to indicate that a particular action method in a controller should only respond to HTTP POST requests.

[ ValidateAntiForgeryToken ]
The [ValidateAntiForgeryToken] attribute is a security feature used to prevent Cross-Site Request Forgery (CSRF) attacks. It ensures that an incoming HTTP request originated from a form on your website rather than a malicious third-party site.

Bind( "Id, Title, Genre, Price, PublishDate" )..;

using ..;

using ..;

using ..;

C:\ASP.NET-workspace\BookStore1\Controllers\BooksController.cs
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Threading.Tasks;
 using Microsoft.AspNetCore.Mvc;
 using Microsoft.AspNetCore.Mvc.Rendering;
 using Microsoft.EntityFrameworkCore;
 using BookStore1.Data;
 using BookStore1.Models;

 namespace BookStore1.Controllers {
   public class BooksController : Controller {
     private readonly BookStore1Context _context;
     public BooksController( BookStore1Context context ) { _context = context; }

     // GET: Books
     public async Task<IActionResult> Index( ) {
       return View( await _context.Book.ToListAsync( ) );
     }

     // GET: Books/Details/5
     public async Task<IActionResult> Details( int? id ) {
       if ( id == null ) { return NotFound( ); }
       var book = await _context.Book.FirstOrDefaultAsync( m => m.Id == id );
       if ( book == null ) { return NotFound( ); }
       return View( book );
     }

     // GET: Books/Create
     public IActionResult Create( ) { return View( ); }

     // POST: Books/Create
     // To protect from overposting attacks,
     //   enable the specific properties you want to bind to.
     // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
     [ HttpPost ]
     [ ValidateAntiForgeryToken ]
     public async Task<IActionResult> Create(
         [ Bind( "Id, Title, Genre, Price, PublishDate" ) ] Book book ) {
       if ( ModelState.IsValid ) {
         _context.Add( book );
         await _context.SaveChangesAsync( );
         return RedirectToAction( nameof( Index ) );
       }
       return View( book );
     }

     // GET: Books/Edit/5
     public async Task<IActionResult> Edit( int? id ) {
       if ( id == null ) { return NotFound( ); }
       var book = await _context.Book.FindAsync( id );
       if ( book == null ) { return NotFound( ); }
       return View( book );
     }

     // POST: Books/Edit/5
     // To protect from overposting attacks,
     //   enable the specific properties you want to bind to.
     // For more details, see http://go.microsoft.com/fwlink/?LinkId=317598.
     [ HttpPost ]
     [ ValidateAntiForgeryToken ]
     public async Task<IActionResult> Edit( int id,
         [ Bind( "Id, Title, Genre, Price, PublishDate" ) ] Book book ) {
       if ( id != book.Id ) { return NotFound( ); }
       if ( ModelState.IsValid ) {
         try {
           _context.Update( book );
           await _context.SaveChangesAsync( );
         }
         catch ( DbUpdateConcurrencyException ) {
           if ( !BookExists( book.Id ) ) { return NotFound( ); }
           else { throw; }
         }
         return RedirectToAction( nameof( Index ) );
       }
       return View ( book );
     }

     // GET: Books/Delete/5
     public async Task<IActionResult> Delete( int? id ) {
       if ( id == null ) { return NotFound( ); }
       var book = await _context.Book.FirstOrDefaultAsync( m => m.Id == id );
       if ( book == null ) { return NotFound( ); }
       return View( book );
     }

     // POST: Books/Delete/5
     [ HttpPost, ActionName( "Delete" ) ]
     [ ValidateAntiForgeryToken ]
     public async Task<IActionResult> DeleteConfirmed( int id ) {
       var book = await _context.Book.FindAsync( id );
       if ( book != null ) { _context.Book.Remove( book ); }
       await _context.SaveChangesAsync( );
       return RedirectToAction( nameof( Index ) );
     }

     private bool BookExists( int id ) {
       return _context.Book.Any( e => e.Id == id );
     }
   }
 }




      “By the time a man is wise enough to watch his step,    
      he’s too old to go anywhere.”    
      — Billy Crystal on aging