Данное руководство устарело. Актуальное руководство: Руководство по ASP.NET Core
Прежде чем непосредственно приступить к созданию многоуровнего приложения, сначала построим простое стандартное приложение ASP.NET MVC с монолитной архитектурой, которое потом переделам в трехуровневое.
Это приложение будет имитировать работу магазина смартфонов. Пусть у нас будут определены следующие модели Phone и Order:
public class Phone { public int Id { get; set; } public string Name { get; set; } public string Company { get; set; } public decimal Price { get; set; } public ICollection<Order> Orders { get; set; } } public class Order { public int Id { get; set; } public decimal Sum { get; set; } public string PhoneNumber { get; set; } public string Address { get; set; } public DateTime Date { get; set; } public int PhoneId { get; set; } public Phone Phone { get; set; } }
Модел Phone описывает смартфон, модель Order - заказ на покупку, и объекты этих моделей будут храниться в базе данных. Для взаимодействия с базой данных определен следующий класс контекста:
public class MobileContext : DbContext { public DbSet<Phone> Phones { get; set; } public DbSet<Order> Orders { get; set; } } public class StoreDbInitializer : DropCreateDatabaseAlways<MobileContext> { protected override void Seed(MobileContext db) { db.Phones.Add(new Phone { Name = "Nokia Lumia 630", Company = "Nokia", Price = 220 }); db.Phones.Add(new Phone { Name = "iPhone 6", Company = "Apple", Price = 320 }); db.Phones.Add(new Phone { Name = "LG G4", Company = "lG", Price = 260 }); db.Phones.Add(new Phone { Name = "Samsung Galaxy S 6", Company = "Samsung", Price = 300 }); db.SaveChanges(); } }
Кроме того, здесь также определен инициализатор, который добавляет в БД начальные значения.
Для оформления заказа определена дополнительная модель OrderViewModel:
public class OrderViewModel { public int PhoneId { get; set; } // id телефона public string Address { get; set; } // адрес public string PhoneNumber { get; set; } // номер телефона покупателя }
За логику отвечает HomeController:
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using MonolitMvcApp.Models; namespace MonolitMvcApp.Controllers { public class HomeController : Controller { MobileContext db = new MobileContext(); public ActionResult Index() { return View(db.Phones.ToList()); } public ActionResult MakeOrder(int? id) { if (id == null) return HttpNotFound(); Phone phone = db.Phones.Find(id); if (phone == null) return HttpNotFound(); OrderViewModel orderModel = new OrderViewModel { PhoneId=phone.Id }; return View(orderModel); } [HttpPost] public ActionResult MakeOrder(OrderViewModel orderModel) { if (ModelState.IsValid) { Phone phone = db.Phones.Find(orderModel.PhoneId); if (phone == null) return HttpNotFound(); decimal sum = phone.Price; // если сегодня первое число месяца, тогда скидка в 10% if (DateTime.Now.Day == 1) sum = sum - sum * 0.1m; Order order = new Order { PhoneId=phone.Id, PhoneNumber = orderModel.PhoneNumber, Address=orderModel.Address, Date = DateTime.Now, Sum = sum }; db.Orders.Add(order); db.SaveChanges(); return Content("<h2>Ваш заказ успешно оформлен</h2>"); } return View(orderModel); } protected override void Dispose(bool disposing) { db.Dispose(); base.Dispose(disposing); } } }
Контроллер имеет три метода. Метод Index выводит в представление список смартфонов. GET-версия метода MakeOrder генерирует представление для оформления заказа. POST-версия метода MakeOrder получает введенные данные, и, если все верно, добавляет объект в базу данных. При этом, если текущее число - первое число любое месяца, то применяется скидка в 10%.
И два представления выглядят стандартно. В итоге получается следующая структура проекта:
Таким образом, проект содержит довольно простой и небольшой функционал, и выбранный способ реализации - монолитная архитектура, то есть цельное приложение без разделения на уровни в данном случае вполне подходит, также как он подходит для простых реализаций CRUD-интерфейсов.
Однако если мы работаем над большим приложением, тем более если над ним работаем не только мы, а целая команда, если приложение в будущем будет динамично развиваться и расширяться, то монолитная архитектура вряд ли будет во многих ситуациях лучшим выбором. И в этом случае логично было бы разделить приложение на отдельные компоненты, которые по отдельности проще разрабатывать и расширять.
И теперь создадим то же самое приложение, но уже с применением трехуровневой архитектуры.