ASP.NET MVC е платформа, създадена от Microsoft, която служи за изработване на уеб приложения с шаблон за дизайн Модел-Изглед-Контролер (, MVC). Платформата използва C#, HTML, CSS, JavaScript и бази данни и е съвременно средство за уеб приложения, което обаче не замества изцяло уеб формите. Платформата включва нови тенденции в разработката на уеб приложения, притежава много добър контрол върху HTML и дава възможност за създаване на всякакви приложения. ASP.NET MVC може да бъде много лесно тествана и допълвана, защото е изградена от отделни модули, изцяло независими един от друг. Чрез платформата се създават цялостни приложения, които се стартират, а не единични скриптове (като при PHP например).

MVC модели

Модел Моделът представлява част от приложението, което реализира домейн логиката, също известна като бизнес логика. Домейн логиката обработва данните, които се предават между базата данни и потребителския интерфейс. Например, в една система за инвентаризация, моделът отговаря за това дали елемент от склада е наличен. Моделът може да бъде част от заявлението, което актуализира базата данни когато даден елемент е продаден или доставен в склада. Често моделът съхранява и извлича официална информация в базата данни.

Изглед модел (view model) Изглед модела позволява да се оформят няколко изгледа от един или повече модела от данни или източници в един обект. Този модел е оптимизиран за потребление и изпълнение.

MVC модели MVC (model – view – control) предоставя различни видове и начини за това как да бъде изграден даден модел. Практиката е доказала, че поради липсата на много информация, практики и препоръки, е възможно да се получат разминавания за това как да бъде направен модел. Всъщност, истината е, че няма еднотипно решение, което да задоволява всички възникнали проблеми. Тук ще разгледаме някои от основните модели, които се използват, с описание на конкретен пример. Трябва да се отбележи, че това са модели, използвани при решаването на реални практически проблеми.

Модел 1 – Обектен домейн модел използван директно като модел-изглед(view model) Представете си модел, който изглежда по следния начин: public class Motorcycle { public string Make { get; set; } public string Model { get; set; } public int Year { get; set; } public string VIN { get; set; } }

Когато този код премине в изглед, той ни позволява да пишем HTML помощници в стила на нашия избор: <%=Html.TextBox("Make") %> <%=Html.TextBoxFor(m => m.Make) %> Разбира се с този модел по подразбиране може да се върнем обратно при контролера: public ActionResult Save(Motorcycle motorcycle)

Въпреки че този модел е доста опростен и работи изчистено и елегантно, той се „чупи“ много често дори и при по-опростени изгледи. Свързването към домейн модела в този случай не винаги е достатъчно за пълно представяна на изгледа.

Модел 2 – Собствен модел, съдържащ обектния домейн модел Ако разгледаме пак мотоциклета от горния пример, в реалния живот е много по-реалистично изгледът за даден обект да се нуждае от повече от една характеристика, за да бъде представен правилно. Примерно, характеристиките от горния пример Make и Model ще бъдат извиквани от падащи менюта. Ето защо, този модел е предназначен да представи изгледа като съдържател на всички характеристики, необходими за правилното представяне: public class MotorcycleViewModel { public Motorcycle Motorcycle { get; set; } public SelectList MakeList { get; set; } public SelectList ModelList { get; set; } }

В този случай, контролерът има отговорност за това моделът MotorcycleView да е правилно попълнен с данни от хранилищата (Пример: получаване на Motorcycle от база данни, извличане на колекция Make/Model от база данни). Нашите HTML помощници леко се променят, защото сега се отнасят за MotorcycleMake, а не само за Make: <%=Html.DropDownListFor(m => m.Motorcycle.Make, Model.MakeList) %>

Когато формата се публикува, все още е необходимо да има Save() метод: public ActionResult Save([Bind(Prefix = "Motorcycle")]Motorcycle motorcycle)

В този пример трябва атрибутът Motorcycle да се използва като префикс към HTML елемента, от който се интересуваме Този модел е опростен и подходящ за много ситуации. Въпреки това, изгледът става по-сложен, а „чупенето“ отново е проблем тъй като често има разминаване между обектния домейн модел и отдадения модел!

Модел 3 – Собствен модел, съдържащ обичайния модел – изглед Когато изгледът стане по-сложен, обикновено е трудно да се запази обектният модел на домейна в синхрон с работата на изгледа. Ако разгледаме пак горепосочения пример, нека да предположим, че се изисква да се предостави на потребителя поле, в което той да може да добави мотоциклет, ако желае. Когато формата се публикува, контролерът трябва да прецени според стойностите, кой изглед да бъде показан следващ. Последното нещо, което трябва да се направи е да се добави това свойство на нашия домейн – модел, тъй като това е строго изискване.

Нека информацията за мотоциклета да е MotorcycleData: public class MotorcycleData { public string Make { get; set; } public string Model { get; set; } public int Year { get; set; } public string VIN { get; set; } public bool AddAdditionalCycle { get; set; } }

Този модел е доста трудоемък и изисква слой за превеждане, за да се очертаят връзките назад и напред между Motorcycle и MotorcycleData, но в случая усилията си струват дори за по-сложни изгледи. Този модел със сериозно застъпен и препоръчан от авторите на книгата MVC in Action. Идеите са разширени и в публикациите на Jimmy Bogard (един от съавторите на книгата) – How we do MVC – View Models.

В реалния живот, този модел може да е много бърз. Освен че трябва да се очертае връзката между Motorcycle и MotorcycleData, също така може да има номерирана колекция, която да бъде представена с падащо меню. Ако целият този код бъде подаден към контролера, той много бързо ще се бъде напълнен с много код, който се отнася само за изграждането на модел – изгледа, което не е желателно, защото контролерът трябва да не се препълва с излишна информация. Ето защо може да създаден отделен клас, чиято роля да бъде само изграждането на модел – изгледа: public class MotorcycleViewModelBuilder { private IMotorcycleRepository motorcycleRepository;

public MotorcycleViewModelBuilder(IMotorcycleRepository repository) { this.motorcycleRepository = repository;

public MotorcycleViewModel Build() { // code here to fully build the view model // with methods in the repository

Това позволява кодът на контролера да изглежда по следния начин: public ActionResult Edit(int id) { var viewModelBuilder = new MotorcycleViewModelBuilder(this.motorcycleRepository); var motorcycleViewModel = viewModelBuilder.Build(); return this.View(); }

Изгледът в този модел може да изглежда почити като изгледа в модел 2, но тук имаме предимството да знаем, че само преминаваме през данните, от които имаме нужда – нито повече, нито по-малко. Когато формата се публикува обратно, Save() методът в контролера ще изглежда по следния начин: public ActionResult Save([Bind(Prefix ="Motorcycle")]MotorcycleData motorcycleData) { var mapper = new MotorcycleMapper(motorcycleData); Motorcycle motorcycle = mapper.Map(); this.motorcycleRepository.Save(motorcycle); return this.RedirectToAction("Index"); }

Тази имплементация е много подобна на модела описан от Jimmy Bogard, но без AutoMap. AutoMap ни позволява да запазваме част от кода извън контолера, което може да бъде много полезно.

В сложните реални ситуации, някой вариации на Модел 3 са най-добрия избор, тъй като този модел предоставя най-голяма гъвкавост и вариативност на разработчика.

Съображения Как определяме кой е най-подходящият модел в конкретна ситуация? Ето няколко съображения, които да имате предвид:

Повторна употреба на код (Re-use) Модел 1 и модел 2 са подходящи за употреба при повторение на код. Тук трябва да има връзка между изгледа и обектния домейн модел. Това води до по-кратък код, като картографски слой не е задължителен. Обаче, ако изгледът се различава от домейн модела (което е често срещано) модел 1 и модел 2 са неефективни.

Несъответствия Често се получават несъответствия между нашия домейн модел и съображенията на изгледа. В такъв случай модел 3 е най-подходящ.

Картографски слой Ако е използван обичайния модел 3, трябва да сте сигурни, че е създаден модел за картографкси слой. Въпреки че това означава повече код, който трябва да се напише, това предоставя повече гъвкавост, а също така има и библиотеки, които правят написването му по-лесно.

Валидация Има много начини за валидация, като един от най-популярните е използването на библиотеки. Въпреки че типичните валидации (напр. задължителни полета), ще бъдат същите между домейн модела и изгледа, не всички валидации винаги ще съвпадат. Освен това, не винаги ще може да се контролира домейн модела (например в някой разработки домейн моделът е изложен чрез услуги, които разработчиците само използват). Ето защо има ограничения как валидациите да се свържат с тези класове. Възможно е да се използва отделен клас „мета данни“ за валидиране. Ето защо клас 3 предоставя абсолютен контрол над валидирането.

Изводи Дотук разгледаните модели бяха в контекста на ASP.NET MVC. Проблемът с това как най-добре да се справяме с изглед моделите са актуални и при други рамки, като например уеб формите. Ако е възможно да се свържете директно към домейн модела с обикновен клас, това е най-простото и лесно решение. Но когато сложността нараства, отделните модели предоставят разнообразие от възможности за действие.

Контролери и действия Какво са контролери Контролерите са класове, които се създават в MVC приложението. Намират се в папка Controllers. Всеки един клас, който е от този тип, трябва да има име завършващо с наставка „Controller“. Контролерите обработват постъпващите заявки, въведени от потребителя и изпълняват подходящата логика за изпълнение на приложението. Класът контролер е отговорен за следните етапи на обработка: Намиране и извикване на най-подходящия метод за действие (action method) и валидиране, че може да бъде извикан. Взимането на стойности, които да се използват като аргументи в метода за действие. Отстраняване на всички грешки, които могат да възникнат по време на изпълнението метода за действие. Осигуряване на клас WebFormViewEngine по подразбиране за отваряне на страници с изглет от тип ASP.NET.

За да създадем контролер натискаме дясното копче на мишката върху папката „controllers“ в прозореца „solution explorer“ на Visual Studio, избираме „add“ и след това „controller“.

След появяването на прозореца „Add controller“ трябва да се въведе име на контролера. То трябва да завършва с наставката „controller“.

Контролера е клас който се наследява от базовия клас System.Web.Mvc.Controller. Всеки публичен метод в контролера е показан като „controller action“. Ако искаме даден метод да не бъде извикан, трябва да сложим „NonAction“ атрибут върху неговото име. По подразбиране „Index()“ действието е извикано за контролера, когато друго такова не е изрично упоменато. using System; using System.Collection.Generic; using System.Linq; using System.Web; using System.Web.MVC;

namespace ControllerApplication.Controllers { public class TestingController : Controller { // // GET: /Testing/

public ActionResult Index() //Default Action

return View();

Методи за действие В ASP.NET приложения, които не ползват MVC Framework, взаимодействията с потребителя са организирани и контролирани чрез страници. За разлика от това в приложения с MVC framework взаимодействията с потребителя са организирани чрез контролери и методи за действие. Контролерът определя метода за действие и може да включва толкова методи за действие, колкото са необходими.