Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ASP_NET_MVC_4_Framework_s_primerami_na_C_dlya_p

.pdf
Скачиваний:
25
Добавлен:
19.03.2016
Размер:
17.66 Mб
Скачать

Включить Edit and Continue

Нам нужно включить Edit and Continue в двух местах:

В разделе Edit and Continue меню Debugging (выберите Options из меню Tools Visual Studio); убедитесь, что на Enable Edit and Continue поставлена галочка, как показано на рисунке 12-14.

Рисунок 12-14: Включение Edit and Continue в диалоговом окне Options

В свойствах проекта (выберите DebuggingDemo Properties из Visual Studio меню Project); щелкните раздел Web и убедитесь, что на Enable Edit and Continue поставлена галочка, как показано на рисунке 12-15.

Рисунок 12-15: Включение Edit and Continue в свойствах проекта

301

Изменение проекта

Возможность Edit and Continue несколько придирчива. Есть несколько условий, при которых она не может работать. Одно из таких условий присутствует в методе действия Index класса HomeController: использование динамических объектов. Чтобы обойти это, мы закомментировали строку, которая использует ViewBag в классе HomeController.cs, как показано в листинге 12-6.

Листинг 12-6: Удаление вызова ViewBag из метода Index

using System.Web.Mvc;

namespace DebuggingDemo.Controllers

{

public class HomeController : Controller

{

public ActionResult Index()

{

int firstVal = 10; int secondVal = 0;

int result = firstVal / secondVal; // Это выражение закомментировано

//ViewBag.Message = "Welcome to ASP.NET MVC!"; return View(result);

}

}

}

Мы должны сделать соответствующее изменение в представлении Index.cshtml, как показано в листинге 12-7.

Листинг 12-7: Удаление вызова ViewBag из представления

@model int @{

Layout = null;

}

<!DOCTYPE html> <html>

<head>

<meta name="viewport" content="width=device-width" />

<link href="~/Content/Site.css" rel="stylesheet" type="text/css" /> <title>Index</title>

</head>

<body>

<!-- Этот элемент закомментирован -->

<!--<h2 class="message">@ViewData["Message"]</h2>--> <p>

The calculation result value is: @Model </p>

</body>

</html>

Редактирование и продолжение

Мы готовы к демонстрации возможности Edit and Continue. Выберите Start Debugging из Visual Studio меню Debug. Приложение запустится с отладчиком и будет работать до тех пор, пока не достигнет линии, где мы выполняем несложное вычисление в методе Index. Значение второго параметра равно нулю, что приводит к исключению. В этот момент отладчик останавливается, и появляется всплывающее окно с подсказкой (как показано на рисунке 12-13).

302

Нажмите ссылку Enable editing в окне с подсказкой. В редакторе кода наведите курсор мыши на переменную secondVal и нажмите на значение в появившемся всплывающем окне. Введите 5 в качестве нового значения, как показано на рисунке 12-16.

Рисунок 12-16: Изменение значения переменной

Теперь выберите Continue из Visual Studio меню Debug, чтобы возобновить выполнение приложения. Новое значение, которое вы присвоили переменной, используется для генерации значения переменной result, как показано на рисунке 12-17.

Рисунок 12-17: Результат исправления ошибки при помощи Edit and Continue

Найдите минутку, чтобы понять то, что произошло здесь. Мы запустили программу с ошибкой: это была попытка разделить значение на ноль. Отладчик обнаружил исключение и остановил выполнение программы. Мы отредактировали код, чтобы исправить ошибку, заменив значение переменной на 5. Затем мы сказали отладчику продолжить выполнение программы.

И в этот момент Visual Studio перекомпилировала наше приложение так, чтобы изменения были включены в процесс сборки, заново запустила выполнение программы, воссоздала состояние, которые привело к исключению, а затем продолжила работу, как обычно. В браузере отобразился результат, к которому привели наши изменения.

Без Edit and Continue нам нужно было бы остановить приложение, сделать изменения, скомпилировать приложение и перезапустить отладчик. Затем нам нужно было бы использовать браузер, чтобы повторить шаги, которые мы сделали до момента, когда остановился отладчик. Функция Edit and Continue является достаточно важной. Исправление сложных ошибок может потребовать повторения множества шагов по всему приложению, а возможность протестировать потенциальные исправления без необходимости повторять эти шаги снова и снова может сильно сэкономить время программиста.

303

Резюме

В этой главе мы показали вам структуру MVC проекта Visual Studio и то, как различные части сочетаются друг с другом. Мы также затронули одну из самых важных характеристик MVC фреймворка: соглашений. Это темы, к которым мы будем возвращаться снова и снова в последующих главах, когда мы будем глубже исследовать, как работает MVC фреймворк.

304

Маршрутизация

До введения MVC ASP.NET предполагал, что существует прямая связь между запрашиваемым URLадресом и файлами на жестком диске сервера. Работы сервера заключалась в том, чтобы получить запрос от браузера и доставить выходные данные из соответствующего файла, а именно:

Запрашиваемый URL

Соответствующий файл

http://mysite.com/default.aspx

e:\webroot\default.aspx

http://mysite.com/admin/login.aspx

e:\webroot\admin\login.aspx

http://mysite.com/articles/AnnualReview Файл не найден. Ошибка 404

Этот подход очень хорош для Web Forms, где каждая ASPX страница является и файлом, и ответом на запрос. Но это не имеет смысла для MVC приложения, где запросы обрабатываются методами действия в классах контроллеров и где нет однозначного соответствия с файлами на диске.

Для обработки MVC URL платформа ASP.NET использует систему маршрутизации (роутинга). В этой главе мы покажем вам, как настроить и использовать систему маршрутизации для создания мощной и гибкой обработки URL для ваших проектов. Вы увидите, что система маршрутизации позволяет создавать любые желаемые структуры URL и выражать их в ясной и сжатой форме. Система маршрутизации имеет две функции:

Изучить входящий URL и выяснить, для какого контроллера и действия предназначен запрос. Как и следовало ожидать, мы хотим, чтобы система маршрутизации делала именно это, когда мы получаем запрос клиента.

Создать исходящих URL. Это URL-адреса, которые появляются в HTML документе, показанном нашим представлением, так чтобы было вызвано определенное действие, когда пользователь кликает по ссылке (в этот момент мы снова получаем входящий URL).

Вэтой главе мы сосредоточимся на определении роутов и их использование для обработки входящих запросов, так чтобы пользователь мог достичь контроллеров и действий. Затем, в следующей главе, мы покажем вам, как использовать те же самые маршруты для генерации исходящих URL, которые будут вам нужны для представлений, а также покажем, как настроить систему маршрутизации и использовать ее для области (areas).

Создание проекта для примера

Для демонстрации системы маршрутизации нам нужен проект, к которому мы можем добавить роуты. Мы создали новое MVC приложение, используя шаблон Basic, и назвали проект

UrlsAndRoutes.

Совет

Мы включили в эту главу различные модульные тесты, и если вы хотите воссоздать их, то вам нужно будет выбрать опцию Create a unit test project, когда вы выбираете шаблон Basic, и использовать NuGet, чтобы добавить Moq в проект

юнит тестирования.

Для демонстрации роутов мы собираемся добавить некоторые простые контроллеры в приложение. В этой главе мы хотим только показать способ, которым интерпретируются URL, чтобы вызвать методы действия, поэтому используемые модели представления являются строковыми значениями

305

во ViewBag, который сообщает имена контроллера и метода действия. Во-первых, создайте контроллер Home и установите его содержание, чтобы оно совпадало с тем, что в листинге 13-1.

Листинг 13-1: Содержание контроллера Home

using System;

using System.Collections.Generic; using System.Linq;

using System.Web; using System.Web.Mvc;

namespace UrlsAndRoutes.Controllers

{

public class HomeController : Controller

{

public ActionResult Index()

{

ViewBag.Controller = "Home"; ViewBag.Action = "Index"; return View("ActionName");

}

}

}

Создайте контроллер Customer и с содержанием, как в листинге 13-2.

Листинг 13-2: Содержание контроллера Customer

using System;

using System.Collections.Generic; using System.Linq;

using System.Web; using System.Web.Mvc;

namespace UrlsAndRoutes.Controllers

{

public class CustomerController : Controller

{

public ActionResult Index()

{

ViewBag.Controller = "Customer"; ViewBag.Action = "Index"; return View("ActionName");

}

public ActionResult List()

{

ViewBag.Controller = "Customer"; ViewBag.Action = "List";

return View("ActionName");

}

}

}

Создайте второй контроллер Admin, как в листинге 13-3.

Листинг 13-3: Содержание контроллера Admin

using System;

using System.Collections.Generic; using System.Linq;

using System.Web; using System.Web.Mvc;

namespace UrlsAndRoutes.Controllers

{

public class AdminController : Controller

{

306

public ActionResult Index()

{

ViewBag.Controller = "Admin"; ViewBag.Action = "Index"; return View("ActionName");

}

}

}

Мы определили представление ActionName во всех методах действия этих контроллеров, что позволяет нам определить одно представление и использовать его во всем приложении. Добавьте новое представление с именем ActionName.cshtml в папку /Views/Shared и установите его содержание, чтобы оно соответствовало тому, что показано в листинге 13-4.

Листинг 13-4: Содержание представления ActionName.cshtml

@{

Layout = null;

}

<!DOCTYPE html> <html>

<head>

<meta name="viewport" content="width=device-width" /> <title>ActionName</title>

</head>

<body>

<div>The controller is: @ViewBag.Controller</div> <div>The action is: @ViewBag.Action</div>

</body>

</html>

Если вы запустите приложение, вы увидите содержимое, как на рисунке 13-1.

Рисунок 13-1: Запуск приложения

Введение в URL паттерны

Система маршрутизации использует набор роутов. Эти маршруты совместно составляют URL схему приложения, являющуюся набором URL-адресов, которые ваше приложение будет распознавать и на которые будет реагировать.

Нам не нужно вручную набирать отдельные URL, которые мы будем поддерживать. Вместо этого каждый роут содержит URL паттерн, который сравнивается с входящим URL. Если паттерн

307

соответствует URL, тогда его использует система маршрутизации для обработки этого URL. Давайте начнем с URL для нашего приложения:

http://mysite.com/Admin/Index

URL-адреса могут быть разбиты на сегменты. Это части URL, исключая хост и строку запроса, разделенные символом «/». В URL из примера есть два сегмента, как показано на рисунке 13-2.

Рисунок 13-2: Сегменты URL из примера

Первый сегмент содержит слово Admin, а второй сегмент содержит слово Index. Для нас очевидно, что первый сегмент относится к контроллеру, а второй сегмент – к действию. Но, конечно, мы должны выразить эти отношения таким образом, чтобы система маршрутизации могла это понять. Вот URL паттерн, который делает это:

{controller}/{action}

При обработке входящего запроса работа системы маршрутизации заключается в том, чтобы запрошенный URL подходил паттерну, а также в извлечении значения из URL для переменных сегмента, определенных в шаблоне. Сегментные переменные выражаются при помощи фигурных скобок ({}). Например, в паттерне есть две сегментные переменные с именами controller и action, и поэтому значение сегментной переменной controller будет Admin, а значение переменной сегмента action будет Index.

Мы указываем на соответствие a паттерну, потому что в MVC приложении, как правило, есть несколько роутов, и система маршрутизации сравнивает входящий URL с URL паттерном каждого роута, пока не найдет соответствия.

Примечание

Система маршрутизации не имеет специальных знаний о контроллерах и действиях. Она просто извлекает значения для сегментных переменных и передает их по каналу запросов. А затем в канале обработки запросов, если запрос достигает MVC фреймворка, это значение присваивается переменным controller и action. Именно

поэтому система маршрутизации может быть использована с Web Forms и Web API (Web API рассматривается в главе 25).

По умолчанию URL паттерн будет соответствовать любому URL, который имеет правильное количество сегментов. Например, паттерн {controller}/{action} будет соответствовать любому URL, который имеет два сегмента, как показано в таблице 13-1.

308

Таблица 13-1: Подходящие URL

 

 

 

URL запроса

Переменные сегмента

 

 

 

 

http://mysite.com/Admin/Index

controller = Admin, action = Index

 

 

 

 

http://mysite.com/Index/Admin

controller = Index, action = Admin

 

 

 

 

http://mysite.com/Apples/Oranges

controller = Apples, action = Oranges

 

 

 

 

http://mysite.com/Admin

Нет соответствий: слишком мало сегментов

 

 

http://mysite.com/Admin/Index/Soccer Нет соответствий: слишком много сегментов

Втаблице 13-1 выделены два ключевых вида поведения URL паттернов:

URL паттерны консервативны: они будут соответствовать только тем URL, которые имеют одинаковое число сегментов, что и нужный паттерн. Вы можете увидеть это в четвертом и пятом примерах в таблице.

URL паттерны либеральны. Если URL имеет правильное количество сегментов, паттерн извлечет значение для сегментной переменной, каким бы оно ни было.

Это поведение по умолчанию, которые являются ключом к пониманию того, как работают URL паттерны. Мы покажем вам, как изменить настройки по умолчанию, далее в этой главе.

Как мы уже упоминали, система маршрутизации ничего не знает об MVC приложении, поэтому URL паттерн найдет соответствие, даже если нет контроллера и действия, которые подходят значениям, извлеченным из URL. Мы показали это во втором примере в таблице 13-1. Мы поменяли сегменты URL Admin и Index, поэтому и значения, извлекаемые из URL, также меняются местами, хотя в примере нет никакого контроллера Index.

Создание и регистрация простого роута

Когда у вас есть URL паттерн, вы можете использовать его для определения роута. Роуты находятся в файле RouteConfig.cs, который находится в папке проекта App_Start. Вы можете увидеть исходное содержание, которое Visual Studio определяет для этого файла, в листинге 13-5.

Листинг 13-5: Содержание по умолчанию файла RouteConfig.cs

using System;

using System.Collections.Generic; using System.Linq;

using System.Web; using System.Web.Mvc;

using System.Web.Routing; namespace UrlsAndRoutes

{

public class RouteConfig

{

public static void RegisterRoutes(RouteCollection routes)

{

routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

routes.MapRoute(

309

name: "Default",

url: "{controller}/{action}/{id}", defaults: new

{

controller = "Home", action = "Index",

id = UrlParameter.Optional

}

);

}

}

}

Статический метод RegisterRoutes, который определен в файле RouteConfig.cs, вызывается из файла Global.asax.cs, который устанавливает некоторые из основных функциональных возможностей MVC при запуске приложения. Вы можете увидеть содержимое по умолчанию файла

Global.asax.cs в листинге 13-6, и мы выделили вызов метода RouteConfig.RegisterRoutes,

который сделан из метода Application_Start.

Листинг 13-6: Содержание по умолчанию Global.asax.cs

using System;

using System.Collections.Generic; using System.Linq;

using System.Web; using System.Web.Http; using System.Web.Mvc;

using System.Web.Optimization; using System.Web.Routing; namespace UrlsAndRoutes

{

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

}

}

}

Метод Application_Start вызывается базовой платформой ASP.NET, когда MVC приложение запускается в первый раз, что приводит к вызову метода RouteConfig.RegisterRoutes. Параметром этого метода является значение статического свойства RouteTable.Routes, которое является экземпляром класса RouteCollection (мы опишем его далее).

Совет

Другие вызовы, сделанные методом Application_Start, рассматриваются в других

главах. Мы описываем метод AreaRegistration.RegisterAllAreas в главе 14,

метод WebApiConfig.Register в главе 25, метод

FilterConfig.RegisterGlobalFilters в главе 16 и метод

BundleConfig.RegisterBundles в главе 24.

310

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]