Abychom mohli data, která si vyměňuje klient se serverem, persistovat, potřebujeme několik věcí.
Především potřebujeme databázi a v ní nějaké databázové tabulky. Tabulky budou odpovídat našim business objektům.
V business objektech potřebujeme ještě doplnit toto:
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace PetEShopWebMVC.BusinessObjects { [Table("PE_HOUSE")] public class House { [Key] [Column("ID")] public int ID { get; set; } [Column("DESCRIPTION")] public string Description { get; set; } [Column("WIDTH")] public double Width { get; set; } [Column("LENGTH")] public double Length { get; set; } public House() { } public House(string description, double width, double length) { this.Description = description; this.Width = width; this.Length = length; } } }
public DbSet<House> Houses { get; set; }
Dále vytvoříme interface a repo třídu pro daný business objekt. To je tzv. datová vrstva (DAO).
public interface IHouseRepo { IList<House> GetList(); IList<House> FindList(House house); bool Exists(House house); House Load(House house); void Store(House house); void Add(House house); void Remove(House house); }
Implementace interface-u IHouseRepo je ve třídě HouseRepo.
Dále vytvoříme interface a servisní třídu pro tentýž business objekt. To je tzv. aplikační vrstva (někdy též business logic layer).
using System; using System.Collections.Generic; using PetEShopWebMVC.BusinessObjects; namespace PetEShopWebMVC.Interfaces.Services.Test { public interface IHouseService { House SaveHouse(House house); } }
Implementace interface-u IHouseService je ve třídě HouseService.
Vrstva MVC (model-view-controller) je de facto prezentační vrstva celé aplikace.
V případě use-case-u pro editaci business objektu House použijeme tyto třídy a soubory:
Business objekt House už máme hotový. Jen ho použijeme pro view EditHouse jako model.
Soubor EditHouse.cshtml jsme nechali vygenerovat právě k business objektu House. Tedy by měl zrcadlit vlastnosti našeho domu (popisku, šířku, délku).
Do třídy HouseController přidáme dvě akce (pro HTTP GET a HTTP POST).
První akce (ShowEditHouse) zobrazí prázdný editační formulář.
// GET /houses/edit-house [HttpGet("edit-house")] public IActionResult ShowEditHouse() { return View("/Views/House/EditHouse.cshtml", new House()); }
Druhá akce (EditHouse) zpracuje data z webového formuláře (vypíše je do logu a uloží je do db). Vrací HTTP status code 200, což znamená OK (vše v pořádku).
// POST /House/EditHouse [HttpPost("/houses")] public IActionResult EditHouse([FromForm] House house) { Console.WriteLine($"Descr.: {house.Description} Size: {house.Width}x{house.Length} m"); this.houseService.SaveHouse(house); return new OkResult(); }
Ještě musíme jednotlivé vrstvy naší appky propojit. Využijeme tzv. Dependency Injection (DI):
public class HouseService : IHouseService { private readonly IHouseRepo houseRepo; public HouseService(IHouseRepo houseRepo) { this.houseRepo = houseRepo; } // ... }
[Route("houses")] public class HouseController : Controller { private readonly IHouseService houseService; public HouseController(IHouseService houseService, IAuthService authService) { this.houseService = houseService; this.authService = authService; } // ... }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { // Configure the ORM layer. services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer( Configuration.GetConnectionString("MssqlConnection"))); services.AddDatabaseDeveloperPageExceptionFilter(); // Configure authentication with individual accounts. services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores<ApplicationDbContext>(); // Configure controllers and views. services.AddControllersWithViews(); // Configure the application layer using Dependency Injection (DI). services.AddScoped<IHouseService, HouseService>(); // Configure the data layer using DI. services.AddScoped<IHouseRepo, HouseRepo>(); }