Направо към съдържанието

ASP.NET MVC

от Уикипедия, свободната енциклопедия

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

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

Изглед модел (view model)

[редактиране | редактиране на кода]

Изглед модела позволява да се оформят няколко изгледа от един или повече модела от данни или източници в един обект. Този модел е оптимизиран за потребление и изпълнение.[2]

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.[3] Идеите са разширени и в публикациите на Jimmy Bogard (един от съавторите на книгата) – How we do MVC – View Models.[4]

В реалния живот, този модел може да е много бърз. Освен че трябва да се очертае връзката между 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. Проблемът с това как най-добре да се справяме с изглед моделите са актуални и при други рамки, като например уеб формите. Ако е възможно да се свържете директно към домейн модела с обикновен клас, това е най-простото и лесно решение. Но когато сложността нараства, отделните модели предоставят разнообразие от възможности за действие.[5]

Контролери и действия

[редактиране | редактиране на кода]

Какво са контролери

[редактиране | редактиране на кода]

Контролерите са класове, които се създават в MVC приложението. Намират се в папка Controllers. Всеки един клас, който е от този тип, трябва да има име завършващо с наставка „Controller“. Контролерите обработват постъпващите заявки, въведени от потребителя и изпълняват подходящата логика за изпълнение на приложението. Класът контролер е отговорен за следните етапи на обработка:

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

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

Пример за създаване на контролер
Пример за създаване на контролер

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

AddController прозорец
AddController прозорец

Контролера е клас който се наследява от базовия клас 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();
		}
	}
}
NoAction атрибут
NoAction атрибут

[6]

Методи за действие

[редактиране | редактиране на кода]

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

Методи за действие обикновено имат функции, които са пряко свързани с взаимодействието с потребителя. Примери за взаимодействие с потребителите са въвеждане на URL адрес в браузъра, кликване върху линк, и подаването на формуляр. Всяко едно от тези потребителски взаимодействия изпраща заявка към сървъра. Във всеки един от тези случаи, URL адреса от заявката съдържа информация, която MVC Framework използва за да включи метод за действие.[7]

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

		public ActionResult Testing1()
		{
			return View();
		}

		public ActionResult Testing2(string x)
		{
			return View();
		}
	}
}

В посочения горе пример имаме три действия (Index, Testing1, Testing2), които са дефинирани в контролер клас „TestingController“. За да извикаме различни действия, трябва да напишем следното в полето за адреси:

Начин на изписване: /{controller}/{action}/{id}

  • /TestingController/Index :- Извиква Index() действие.
  • /TestingController/Testing1 :- Извиква Testing1() действие.
  • /TestingController/Testing2/pijush :- Извиква Testing2() действие с „pijush“ за Id параметър.
  • /TestingController :- Извиква Index() действие.

Списък резултати от дейстия.

[редактиране | редактиране на кода]

Action Results

  • View():- Представлява ASP.NET MVC изглед т.е., когато вашия браузър връща HTML. Това е най-рапространения „ActionResult“, който може да върне един контролер.
  • PartialView():- Извиква част от ASP.NET MVC изгледа.
  • RedirectToAction():- Пренасочва от едно контролер действие в друго. Параметри с които може да се използва това действие са:
-actionName: Името на действието.
-controllerName: Името на контролера.
-routeValues: Стойностите които са предадени на действието.

Метода RedirectToAction() връща „302 found HTTP“ статус код на браузъра, за да може да направи пренасочването към новото действие. Едно от предимствата на това действие е, че когато се прави пренасочване в браузъра – полето за адреси се обновява с новия URL линк. Недостатък е, че трябва да се направи повторна заявка от браузъра към сървъра.

  • Redirect(): Пренасочва към друг контролер или URL линк.
  • Content(): Данни които постъпват към браузъра. Параметрите, които могат да се използват като аргументи, са:
-string: Изобразява string на браузъра.
-contentype: Типът MIME на данните (по подразбиране за text/html).
-contentEncoding: Текстовото кодиране на данните (например:-Unicode или ASCII)
  • Json(): JavaScript object Notation (JSON) e изобретен от Douglas Crockford като по-лека алтернатива на XML за пращане на данни по интернет в Ajax приложения. Метода Json() използва клас в .NET framework наречен JavaScriptSerializer за да преобразува обект в JSON репрезентация.
  • File(): Връщане на фаил от действие. Този метод приема следните параметри:
-filename, contentType, fileDownloadName, fileContents, fileStream.
  • JavaScript(): Представлява JavaScript фаил.
  • HandleUnknownAction(): Този метод се извиква автоматично когато контролера не може да намери ресурс. По подразбиране метода изкарва грешка „404 resource Not Found“. Съобщението за грашка може да бъде сменено с друго, това обаче изисква да се пренапише контролер класа.

Валидирането на входните данни, въведени от потребителя (user input), позволява да се уверим, че те съответстват на модела на данните в ASP.NET MVC. По този начин се защитава приложението от потребителски грешки или злонамерени потребители. Има много начини да се включи валидиране в едно MVC приложение. Например, може да бъде използвана публично достъпна библиотека за валидиране, като Microsoft Enterprise Library Validation Block.

Как работи валидирането

[редактиране | редактиране на кода]

Когато потребителят потвърди (submit) формуляр(form), данните от формуляра се предават на метод за действие (action method) с помощта на ViewDataDictionary колекция. ViewDataDictionary има ModelState свойство(property), което съдържа колекция от ModelState обекти. За всеки модел, който е дефиниран в MVC приложението, се създава съответния ModelState обект и добавя в колекцията. Действието, което получава данните от формуляра определя правилата за проверка, прилагани към формуляра с данни. Ако правилото е нарушено, действието използва ModelState свойство за да предаде информация за грешка обратно към изгледа.

Пример за валидация

[редактиране | редактиране на кода]

Примерът показва клас Person, който дефинира свойства (properties) за съхраняване на лични данни:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Street { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zipcode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Следното дефинира форма за въвеждане на стойности и създаване на инстанция на класа Person. Ако потребителят въведе невалидна стойност за инстанцията на Person, изгледът се генерира отново, този път със съобщение за грешка, което е подадено на изгледа от свойство на ModelState:

<h2>Create</h2>
<%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>

<% using (Html.BeginForm()) {%>

    <fieldset>
        <legend>Fields</legend>
        <p>
            <label for="Name">Name:</label>
            <%= Html.TextBox("Name") %> Required
            <%= Html.ValidationMessage("Name", "*") %>
        </p>
        <p>
            <label for="Age">Age:</label>
            <%= Html.TextBox("Age") %> Required
            <%= Html.ValidationMessage("Age", "*") %>
        </p>
        <p>
            <label for="Street">Street:</label>
            <%= Html.TextBox("Street") %>
            <%= Html.ValidationMessage("Street", "*") %>
        </p>
        <p>
            <label for="City">City:</label>
            <%= Html.TextBox("City") %>
            <%= Html.ValidationMessage("City", "*") %>
        </p>
        <p>
            <label for="State">State:</label>
            <%= Html.TextBox("State") %>
            <%= Html.ValidationMessage("State", "*") %>
        </p>
        <p>
            <label for="Zipcode">Zipcode:</label>
            <%= Html.TextBox("Zipcode") %>
            <%= Html.ValidationMessage("Zipcode", "*") %>
        </p>
        <p>
            <label for="Phone">Phone:</label>
            <%= Html.TextBox("Phone") %> Required
            <%= Html.ValidationMessage("Phone", "*") %>
        </p>
        <p>
            <label for="Email">Email:</label>
            <%= Html.TextBox("Email") %> Required
            <%= Html.ValidationMessage("Email", "*") %>
        </p>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>

<% } %>
<div>
    <%=Html.ActionLink("Back to List", "Index") %>
</div>

Ако възникне грешка при валидирането, методът за действие извиква метода AddModelError за да добави грешката в свързания обект ModelState. След като се изпълнят правилата за валидиране, методът за действие използва свойството IsValid на колекциата ModelStateDictionary за да се определи дали получената информация е в съответствие с модела:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Person person)
{
    if (person.Name.Trim().Length == 0)
    {
        ModelState.AddModelError("Name", "Name is required.");
    }
    if (person.Age < 1 || person.Age > 200)
    {
        ModelState.AddModelError("Age", "Age must be within range 1 to 200.");
    }
    if ((person.Zipcode.Trim().Length > 0) && (!Regex.IsMatch(person.Zipcode, @"^\d{5}$|^\d{5}-\d{4}$")))
    {
        ModelState.AddModelError("Zipcode", "Zipcode is invalid.");
    }
    if (!Regex.IsMatch(person.Phone, @"((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}"))
    {
        ModelState.AddModelError("Phone", "Phone number is invalid.");
    }
    if (!Regex.IsMatch(person.Email, @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"))
    {
        ModelState.AddModelError("Email", "Email format is invalid.");
    }
    if (!ModelState.IsValid)
    {
        return View("Create", person);
    }

    people.Add(person);

    return RedirectToAction("Index");
}

[8]

Изгледите са тези, които определят как ще бъде визуализиран потребителският интерфейс (UI) на приложението. В ASP.NET MVC се поддържат средства (engines) за генериране на изгледи.

Начин на работа на изгледите

[редактиране | редактиране на кода]

Когато потребителт взаимодейства с изглед, данните се рутират от изгледа до метод за действие, който от своя страна може да създаде друг изглед. Едно MVC приложение може да има няколко контролери, всеки от които може да съдържа множество методи за действие, а всяко действие може да създаде различен изглед. Изгледите са организирани в папки, като името им се определя от това на свързания контролер (например изгледите от HomeController са в папката \Views\Home).

Добавяне на изглед на MVC приложение в Visual Studio

[редактиране | редактиране на кода]
  1. В Solution Explorer, щракнете с десния бутон на мишката върху папката, която носи името на нужния ви контролер. Например ако контролерът е с име HomeController, щракнете с десния бутон върху папката Home.
  2. Натиснете Add, след което View. Отваря се следният диалогов прозорец:
Създаване на Изглед в ASP.NET MVC
Създаване на Изглед в ASP.NET MVC
  1. Попълнете име, вид изглед и т.н, в зависимост от това какъв изглед искате да създадете.
  2. Натиснете Add[9]

Рутирането е метод за валидация и обработка на заявката от потребителя. След като рутирането получи заявката, то проверява дали тази заявка отговаря на рутиращите шаблони и ако бъдат намерени съответствия, първият физически поставен в кода шаблон, отговарящ на дадената заявка, изпълнява функции за подаване на данните от заявката към съответните контролери, действия и параметри.

Как се регистрира и дефинира рутирането

[редактиране | редактиране на кода]

При стартиране на ASP.NET MVC приложението първият файл, който се стартира, се нарича „Global.asax“ и съответно в него първият метод, който се извиква, е с име „Application_start()“. В този метод има фунции за регистрация на Area, WebApi, Filters, Routing и Bundle. Именно тук се регистрира и нашето рутиране (Routing) чрез извикване на класа RoutingConfig, през метода RegisterRoutes и през него се регистрира рутирането в глобалната таблица RouteTable.

public class MvcApplication : System.Web.HttpApplication
{
	protected void Application_Start()
	{
		AreaRegistration.RegisterAllAreas();

		WebApiConfig.Register(GlobalConfiguration.Configuration);
		FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
		RouteConfig.RegisterRoutes(RouteTable.Routes);
		BundleConfig.RegisterBundles(BundleTable.Bundles);
		AuthConfig.RegisterAuth();
	}
}
Конфиг файловете в папка Апп Старт

За да дефинирате рутиранете е нужно да конфигурирате файла RouteConfig.cs, който се намира в папката App_Start заедно с останалите Config файлове.

Тук вече се конфигурира метода RegisterRoutes, който се извиква от „Global.asax“ файла. Този метод използва глобална таблица, която може да бъде извикана отвсякъде в нашето приложение и в нея има методи IgnoreRoute и MapRoute. IgnoreRoute методът се използва за да се пренебрегнат заявки, които не желаем да обработим. Чрез метода MapRoute ние регистрираме нашето рутиране като то си има име, url-шаблон и стойности по подразбиране.

public static void RegisterRoutes(RouteCollection routes)
{
	routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

	routes.MapRoute(
		name: "Default",
		url: "{controller}/{action}/{id}",
		defaults: new {
			controller = "Home",
			action = "Index",
			id = UrlParameter.Optional
		}
	};
}

Шаблоните в рутирането са case-insensitive, което означава, че шаблонът ще разпознае данните без значение дали са с малки или главни букви. Ако при заявката никой от шаблоните не бъде обхванат, то тогава сървърът връща error-404.

Дебъгване на рутирането

[редактиране | редактиране на кода]

ASP.NET MVC ни предоставя готов дебъгер който може да свалим през NuGet packege и в него потърсите RouteDebugger.

Инсталация на дебъгера за рутиране
Инсталация на дебъгера за рутиране

Дебъгерът се появява отдолу на страницата след нейното стартиране.

Изображение на дебъгера
Изображение на дебъгера

Ако желаете той да бъде спрян, е нужно да отворите Web.Config файла на вашето приложение и в него да промените този ред „<add key=“RouteDebugger:Enabled" value="true" />", като смените стойността value да е равна на false (<add key="RouteDebugger:Enabled" value="false" />).

<appSettings>
	<add key="webpages:Version" value="1.0.0.0" />
	<add key="ClientValidationEnabled" value="true" />
	<add key="UnobtrusiveJavaScriptEnabled" value="true" />
	<add key="RouteDebugger:Enabled" value="true" />
</appSettings>

[10]

За пръв път ASP.NET MVC е била представена през октомври 2007 г. от Скот Гътри на първата ALT.NET конференция в Остин, Тексас. Въпреки че Гътри заявява в своя блог,[11] че ASP.NET MVC ще бъде пусната в употреба като напълно поддържана функция на ASP.NET през първата половина на 2008, първата официална версия на продукта се появява на 13 март 2009 г.

През март 2012 г. Скот Гътри съобщава в блога[12] си, че Microsoft са пуснали версия на техния уеб пакет включващ ASP.NET MVC, Web API и ASP.NET Web Pages (още наричан Razor) под лиценза на Apache 2.0.

История на версиите

[редактиране | редактиране на кода]
История на версиите
Дата Версия
13 март 2009 ASP.NET MVC 1.0[13]
16 декември 2009 ASP.NET MVC 2 RC[14]
4 февруари 2010 ASP.NET MVC 2 RC 2[15]
10 март 2010 ASP.NET MVC 2[16]
6 октомври 2010 ASP.NET MVC 3 Beta[17]
9 ноември 2010 ASP.NET MVC 3 RC[17]
10 декември 2010 ASP.NET MVC 3 RC 2[17]
13 януари 2011 ASP.NET MVC 3[17]
13 септември 2011 ASP.NET MVC 4 Developer Preview[18]
14 февруари 2012 ASP.NET MVC 4 Beta[19]
31 май 2012 ASP.NET MVC 4 RC[20]
15 август 2012 ASP.NET MVC 4[21]
26 юни 2013 ASP.NET MVC 5 Preview[22]
  1. Урок „Програмиране с ASP.NET MVC“ // Telerik Academy. Архивиран от оригинала на 2013-08-11. Посетен на 2 февруари 2017.
  2. How to Use ViewModel with ASP.NET MVC | Sampath Lokuge Tech Blog // sampathloku.blogspot.com. Посетен на 24 януари 2022.
  3. ASP.NET MVC in Action arrived at my doorstep today | Programming with Palermo // jeffreypalermo.com. Посетен на 24 януари 2022.
  4. How we do MVC – View models · Los Techies // lostechies.com. Посетен на 24 януари 2022.
  5. geekswithblogs.net, архив на оригинала от 28 август 2013, https://web.archive.org/web/20130828222953/http://geekswithblogs.net/michelotti/archive/2009/10/25/asp.net-mvc-view-model-patterns.aspx, посетен на 1 септември 2013 
  6. Controllers and Actions in ASP.NET MVC - CodeProject // codeproject.com. Посетен на 24 януари 2022.
  7. msdn.microsoft.com
  8. msdn.microsoft.com
  9. msdn.microsoft.com
  10. academy.telerik.com, архив на оригинала от 11 август 2013, https://web.archive.org/web/20130811190421/http://academy.telerik.com/school-academy/2012-2013/programming-with-asp-net-mvc, посетен на 24 август 2013 
  11. ScottGu's Blog - ASP.NET MVC Framework // weblogs.asp.net. Посетен на 24 януари 2022.
  12. ScottGu's Blog - ASP.NET MVC, Web API, Razor and Open Source // weblogs.asp.net. Посетен на 24 януари 2022.
  13. Download ASP.NET MVC 1.0 from Official Microsoft Download Center // go.microsoft.com. Посетен на 24 януари 2022.[неработеща препратка]
  14. ASP.NET MVC 2 RC Released | You’ve Been Haacked // haacked.com. Посетен на 24 януари 2022.
  15. ASP.NET MVC 2 RC 2 Released | You’ve Been Haacked // haacked.com. Посетен на 24 януари 2022.
  16. ScottGu's Blog - ASP.NET MVC 2 Released // weblogs.asp.net. Посетен на 24 януари 2022.
  17. а б в г ASP.NET MVC 3 // asp.net. Посетен на 24 януари 2022.
  18. Redirecting… // haacked.com. Посетен на 24 януари 2022.
  19. www.microsoft.com
  20. blogs.msdn.com
  21. blogs.msdn.com
  22. Getting Started with ASP.NET MVC 5 // asp.net. Посетен на 24 януари 2022.