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>();
}