Book Manager for Umbraco 8 ‐ MO - FadiZahhar/umbraco8showandtell GitHub Wiki

📁 Models

Book.cs

This class represents the data structure for a book entity in the application.

Key Attributes:

  • Id: Primary key, auto-incremented.
  • Title: Required; maximum length of 150 characters.
  • Author: Required; maximum length of 100 characters.
  • Year: Must be between 1450 and 2100, ensuring realistic publication years.
  • ISBN: Required; must match the pattern 123-1234567890.

Data annotations are used for validation, ensuring data integrity before database operations.


🗃️ Repositories

BookRepository.cs

Handles direct interactions with the database using NPoco and Umbraco's IScopeProvider.

Core Methods:

  • GetAll(): Retrieves all book records.
  • GetById(int id): Fetches a single book by its ID.
  • Insert(Book book): Adds a new book record.
  • Update(Book book): Updates an existing book record.
  • Delete(int id): Removes a book record by ID.
  • Search(string term, int page, int pageSize): Performs a paginated search based on the term across Title, Author, and ISBN fields.

Each method ensures proper scope management, committing transactions where necessary.


🧰 Services

BookService.cs

Acts as an intermediary between controllers and the repository, encapsulating business logic.

Responsibilities:

  • Delegates CRUD operations to the repository.
  • Handles search functionality with pagination.

This separation of concerns promotes maintainability and testability.


🎮 Controllers

BooksPublicController.cs

An Umbraco API controller exposing endpoints for public access.

Endpoints:

  • GetAllBooks(): Returns a list of all books.

This controller can be extended to include more endpoints as needed.


🧩 AngularJS Dashboard

package.manifest

Registers the custom dashboard within Umbraco's backoffice.

Configuration:

  • alias: Unique identifier for the dashboard.
  • view: Path to the HTML template.
  • sections: Specifies the Umbraco section where the dashboard appears.
  • weight: Determines the dashboard's position in the section.
  • javascript: Includes the controller script.
  • css: Includes styling for the dashboard.

dashboard.html

Defines the structure and layout of the dashboard using AngularJS directives.

Features:

  • Displays a list of books with pagination.
  • Provides forms for adding and editing books.
  • Includes search functionality.
  • Offers CSV export capability.

dashboard.controller.js

Manages the dashboard's state and behavior.

Key Functions:

  • loadBooks(): Initializes the book list.
  • searchBooks(): Filters books based on the search term.
  • newBook(): Prepares the form for adding a new book.
  • editBook(book): Loads a book's data into the form for editing.
  • saveBook(form): Validates and submits the form data.
  • deleteBook(id): Removes a book from the list.
  • exportBooks(): Triggers the CSV export.

The controller ensures a responsive and interactive user experience within the Umbraco backoffice.

Overview

The Book Manager is a custom backoffice dashboard for Umbraco 8 that allows administrators to manage a collection of books. It supports CRUD operations, search, pagination, validation, and CSV export.

Built with:

  • Umbraco 8 (C#, ASP.NET MVC, NPoco)
  • AngularJS (v1.8.2)
  • W3.CSS for lightweight styling

Features

  • List books with pagination
  • Search by title, author, or ISBN
  • Create, edit, delete book entries
  • Client and server-side validation
  • CSV export of book list

1. Data Model

File: /Models/Book.cs

using System.ComponentModel.DataAnnotations;
using NPoco;

namespace HighlyDeveloped.Core.Models
{
    [TableName("Books")]
    [PrimaryKey("Id", AutoIncrement = true)]
    public class Book
    {
        public int Id { get; set; }

        [Required]
        [StringLength(150)]
        public string Title { get; set; }

        [Required]
        [StringLength(100)]
        public string Author { get; set; }

        [Range(1450, 2100)] // Reasonable year range for books
        public int Year { get; set; }

        [Required]
        [RegularExpression(@"^\d{3}-\d{10}$", ErrorMessage = "ISBN must be in the format 123-1234567890")]
        public string ISBN { get; set; }
    }
}

2. Migration

File: /Migrations/BooksTableMigration.cs

[Migration("1.0.0", 1, "HighlyDeveloped")]
public class BooksTableMigration : MigrationBase
{
    public override void Migrate()
    {
        if (!_context.Database.TableExists("Books"))
        {
            Create.Table<Book>().Do();
        }
    }
}

3. Composer and Component

Composer: Registers the migration.

[RuntimeLevel(MinLevel = RuntimeLevel.Run)]
public class BookComposer : IUserComposer
{
    public void Compose(Composition composition)
    {
        composition.Components().Append<BookComponent>();
    }
}

Component: Executes the migration.

public class BookComponent : IComponent
{
    private readonly IMigrationPlanExecutor _executor;
    private readonly IScopeProvider _scopeProvider;

    public BookComponent(IMigrationPlanExecutor executor, IScopeProvider scopeProvider)
    {
        _executor = executor;
        _scopeProvider = scopeProvider;
    }

    public void Initialize()
    {
        var plan = new MigrationPlan("HighlyDeveloped");
        plan.From(string.Empty).To<BooksTableMigration>("books-table-migration");
        _executor.Execute(plan);
    }

    public void Terminate() { }
}

4. Repository

File: /Repositories/BookRepository.cs Handles database queries and pagination.

public IEnumerable<Book> GetAll() {...}
public Book GetById(int id) {...}
public void Insert(Book book) {...}
public void Update(Book book) {...}
public void Delete(int id) {...}
public (IEnumerable<Book> Books, int TotalCount) Search(string term, int page, int pageSize) {...}

5. Service Layer

File: /Services/BookService.cs Handles business logic and validation.

public IEnumerable<string> Validate(Book book) {...}
public void Save(Book book) {...}
public void Delete(int id) {...}

6. API Controller

File: /Controllers/BookApiController.cs Used by the Angular frontend.

[HttpGet] public IEnumerable<Book> GetAll() {...}
[HttpPost] public IActionResult PostSave([FromBody] Book book) {...}
[HttpPost] public IActionResult PostDelete([FromBody] int id) {...}
[HttpGet] public IActionResult Search(...) {...}
[HttpGet] public IActionResult ExportCsv() {...}

7. AngularJS Dashboard

Manifest

File: /App_Plugins/BookManager/package.manifest

{
  "dashboards": [
    {
      "alias": "bookManagerDashboard",
      "view": "/App_Plugins/BookManager/dashboard/dashboard.html",
      "sections": [ "content" ],
      "weight": 10,
      "label": "Book Manager"
    }
  ],
  "javascript": [
    "~/App_Plugins/BookManager/dashboard/dashboard.controller.js"
  ],
  "css": [
    "https://www.w3schools.com/w3css/5/w3.css",
    "~/App_Plugins/BookManager/dashboard/dashboard.css"
  ]
}

HTML Template

File: dashboard.html Contains:

  • Book list table
  • Search box and pagination
  • Edit/create form with validation
  • Export and cancel buttons

AngularJS Controller

File: dashboard.controller.js

.controller("BookManagerDashboardController", function ($scope, $http) {
  // vm setup
  // loadBooks, searchBooks, goToPage, editBook, saveBook, deleteBook, cancel, exportBooks
});

Styles

File: dashboard.css Custom styling for:

  • Input field
  • Validation messages
  • Pagination controls

8. CSV Export

Endpoint: /umbraco/backoffice/api/BookApi/ExportCsv Downloads a CSV file with all book data.

Implementation example:

var sb = new StringBuilder();
sb.AppendLine("Id,Title,Author,Year,ISBN");
foreach (var book in books) {
    sb.AppendLine($"{book.Id},{book.Title},{book.Author},{book.Year},{book.ISBN}");
}
return File(Encoding.UTF8.GetBytes(sb.ToString()), "text/csv", "books.csv");

9. Validation Summary

  • Required fields: Title, Author, Year, ISBN
  • ISBN format: 123-1234567890
  • Year: between 1450 and 2100
  • Server-side validation using the service layer
  • Client-side validation using AngularJS

⚠️ **GitHub.com Fallback** ⚠️