DevDiary



Project 3: Products Page

Main Features


DROPDOWN LIST
The user can filter the list of books via the author's name. It is a form which posts the AuthorID back to the server.

BOOK LIST
The page displays a list of the books in the database.

CART LIST
The page displays a list of the books in the cart which can be updated and is a partial page.

TOTAL COST
The page displays the total cost of the items in the cart. It is a partial page.



Database Schema Diagram

Relational Database Design

There are six tables.

(N) means navigation property.

There are five "One to Many" relationships and one "Many to Many".

BookGenre is a bridge-entity, used for the "Many to Many" relationship between "Book" and "Genre".



Context

Base Controller



BooksController: Products()

ProductsViewModel



BooksBaseViewModel

Repository: GetAuthorList() + GetProducts()



Products View: Drop Down and TotalCost

Products View: List of Books



Products View: Cart Partial View

CartController: _Cart()



Repository: "GetCart()"

Repository: "GetCart()"

This _Cart action method retrieves the full list of cart objects from the repository, loads it to the variable "books" and then sends this object to the partial view.



Partial View: "_Cart"

Rendered HTML for "_Cart"



TotalCostViewModel

Cart Controller: "_TotalCost()"



Partial View: "_TotalCost"

ViewBag vs ViewModel

Initially I used ViewBag to hold the calculated "total price" value and send it to the view.

I replaced this with a ViewModel which only has one property and a constructor.

It inherits from the Base ViewModel however this is not necessary as it doesn't need any of the properties or methods defined in the base ViewModel.



Products View: ActionLink (.../Cart/Add/Id)

ActionLink: Rendered HTML



Products View: ActionLink (.../Cart/Add/Id)

CartController: Add(id), Get Data



CartController: Add(id), If "Cart is NULL"

CartController: Add(id)

var book, holds the data for a specific book object with the id that was passed into the Add() method.

var cart, holds the data for a specifc cart object with the id that was passed into the Add() method.

var cartList, holds a list of all of the cart objects in the cart.

If "var cart" is null then it could not find the item in the cart table so a new cart object is constructed and added to the cart table.



CartController: Add(id), Else "Increment Quantity"

Repository: EditCart(Cart)



CartController: Add(id), Else "Increment Quantity"

Repository: EditCart(Cart)



Added EF Migration (BookShared)

"202106281332275_Initial"

I enabled ef migrations and then added an "initial" migration.

When the database is upgraded, the database is created, empty.

When the database is downgraded, the database is dropped.

The seed method in the configuration puts test data into the database that I'm using locally.

Whenever I deploy this webapp, I comment out the "seed data" in the seed method show below.

This ensures that the test data doesn't interfere with the data in the server database.

I also created a .bak file for the server database in case I need to restore the server database.



202106281332275_Initial.cs

Configuration.cs



KNOWN ISSUES

When adding a book to the cart, all that needs to be updated is the partial view, "_Cart" however currently the whole page is rendered.

On ".../Books/Products" page, the selected dropdown value resets when an item is added to the cart.

Currently there isn't a controller for Authors.

For the CRUD page (.../Books/Index) client and server validation needs to be implemented.

Ajax Calls

To solve the problems described I created a new contoller called "test" and reorgansied the code.

".../Test/Products" - The book table is now a "partial page".

When the add and remove butoons are clicked, Ajax calls reload the "_Cart" parital page.

Also the dropdown filter buttons are also using Ajax calls to reload the "_Book" partial page.

NOTE - The older version of the "Products" page, that doesn't use Ajax to do the post-backs to the server, can be accessed using this URL: .../Main/Products



jQuery: AddToCart

AddToCart Button

All of the buttons belong to the class "btnAdd".

When one of them is clicked, the "_TotalCost" parital page is set to hidden and the id of the book of the corresponding button, is sent to "/Cart/AddToCart".

Once this is completed the "_Cart" partial page is reloaded and the "TotalCost" method is called.

Once the new total cost is calculated, the "_TotalCost" partial page is reloaded.

The remove from cart follows a similar procedure.



jQuery: DropDown Functions

"Filter Books"

When an author is seleced and the "Filter Books" button is clicked, the id of the selected author is loaded to the variable x1.

Then an Ajax call is made and the id is posted to "/Test/_Book".

Once this function has executed, the "_Book" parital page is reloaded and the filtered list appears.



jQuery: DropDown Functions

"Reset Filter"

When the "Reset Filter" button is clicked another Ajax call is made (GET) to "/Test/_Book".

Once this function has executed, the "_Book" parital page is reloaded and the full list of books reloads.



Test: Filter by "String"

I also implemented a search textbox which allows the user to filter the list of books by -

"Book Title"

"Author Name"

"Genre"

This page can be accessed using this URL - .../Test/ProductsTest



Rendered View

jQuery: "Filter Button"



View: ProductsTest

Test Controller: POST Method



Repository: Serach by "Book Title"

Repository: Serach by "Author Name"



jQuery: DropDown Functions

Test Controller: POST Method



Four Controllers

Description

The books controller handles all of the requests for the book CRUD operations.

The cart controller handles all of the requests for the cart. Some of these methods are called by jQuery Ajax.

The main controller handles all of the requests for the main site. None of these action-methods are called by Ajax.

The test controller, contains some action-methods which are accessed via Ajax calls.