Введение в asp.net mvc 5

Начало работыGet started

Начните с установки Visual Studio 2017.Start by installing Visual Studio 2017. Затем откройте Visual Studio.Then, open Visual Studio.

Visual Studio — это интегрированная среда разработки (IDE).Visual Studio is an IDE, or integrated development environment. Как и при использовании Microsoft Word для написания документов, для создания приложений используется интегрированная среда разработки.Just like you use Microsoft Word to write documents, you’ll use an IDE to create applications. В Visual Studio есть список, в нижней части которого показаны различные доступные параметры.In Visual Studio, there’s a list along the bottom showing various options available to you. Также есть меню, предоставляющее еще один способ выполнения задач в интегрированной среде разработки.There’s also a menu that provides another way to perform tasks in the IDE. Например, вместо выбора нового проекта на начальной страницеможно использовать строку меню и выбрать файл > Новый проект.For example, instead of selecting New Project on the Start page, you can use the menu bar and select File > New Project.

Presentation Model

Мартин Фаулер описывает на своем сайте другой подход для достижения разделения ответственности, который называется Presentation Model. PresentationModel представляет собой логическое представление пользовательского интерфейса, не опираясь на какие-либо визуальные элементы.

PresentationModel имеет несколько обязанностей:

  1. Содержит логику пользовательского интерфейса:
    Так же, как и презентер, PresentationModel содержит логику пользовательского интерфейса. Когда вы нажимаете на кнопку, это событие направляется в PresentationModel, которая затем решает, что с ним делать.

  2. Предоставляет данные из модели для отображения на экране
    PresentationModel может преобразовывать данные из модели так, чтобы они были легко отображены на экране. Часто информация, содержащаяся в модели, не может непосредственно использоваться на экране. Вам, возможно, сначала потребуется преобразовать данные, их дополнить или собрать из нескольких источников. Это наиболее вероятно, когда у вас нет полного контроля над моделью. Например, если вы получаете данные от сторонних веб-сервисов или же из базы данных существующего приложения.

  3. Хранит состояние пользовательского интерфейса
    Зачастую пользовательский интерфейс должен хранить дополнительную информацию, которая не имеет ничего общего с моделью. Например, какой элемент выбран в данный момент на экране? Какие ошибки валидации произошли? PresentationModel может хранить эту информацию в свойствах.

View может легко извлекать данные из PresentationModel и получать всю необходимую информацию для отображения на экране. Одно из преимуществ такого подхода заключается в том, что вы можете создать логическое и полностью тестируемое представление вашего UI, не полагаясь на тестирование визуальных элементов.

Паттерн Presentation Model никак не описывает, каким образом View использует данные из модели (PresentationModel).

Основные сведения о действиях контроллераUnderstanding Controller Actions

Контроллер предоставляет действия контроллера.A controller exposes controller actions. Действие — это метод контроллера, который вызывается при вводе определенного URL-адреса в адресную строку браузера.An action is a method on a controller that gets called when you enter a particular URL in your browser address bar. Например, представьте, что вы выполните запрос для следующего URL-адреса:For example, imagine that you make a request for the following URL:

В этом случае метод Index () вызывается для класса Продуктконтроллер.In this case, the Index() method is called on the ProductController class. В качестве примера действия контроллера используется метод Index ().The Index() method is an example of a controller action.

Действие контроллера должно быть открытым методом класса Controller.A controller action must be a public method of a controller class. C#по умолчанию методы являются закрытыми методами.C# methods, by default, are private methods

Следует понимать, что любой открытый метод, добавляемый в класс контроллера, предоставляется как действие контроллера автоматически (необходимо соблюдать осторожность, так как действие контроллера может быть вызвано любым пользователем в Вселенной, просто введя правильный URL-адрес в адресную строку браузера).Realize that any public method that you add to a controller class is exposed as a controller action automatically (You must be careful about this since a controller action can be invoked by anyone in the universe simply by typing the right URL into a browser address bar)

Действие контроллера должно удовлетворять некоторым дополнительным требованиям.There are some additional requirements that must be satisfied by a controller action. Метод, используемый в качестве действия контроллера, не может быть перегружен.A method used as a controller action cannot be overloaded. Кроме того, действие контроллера не может быть статическим методом.Furthermore, a controller action cannot be a static method. Кроме того, в качестве действия контроллера можно использовать практически любой метод.Other than that, you can use just about any method as a controller action.

Наиболее частые ошибки

Начинающие программисты очень часто трактуют архитектурную модель MVC как пассивную модель[неизвестный термин] MVC: модель выступает исключительно совокупностью функций для доступа к данным, а контроллер содержит бизнес-логику. В результате — код моделей по факту является средством получения данных из СУБД, а контроллер — типичным модулем, наполненным бизнес-логикой. В результате такого понимания — MVC-разработчики стали писать код, который Pádraic Brady (известный в кругах сообщества «Zend Framework») охарактеризовал как «ТТУК» («Толстые, тупые, уродливые контроллеры»; Fat Stupid Ugly Controllers):

Но в объектно-ориентированном программировании используется[кем?] активная модель[неизвестный термин] MVC, где модель — это не только совокупность кода доступа к данным и СУБД, но и вся бизнес-логика; также, модели могут инкапсулировать в себе другие модели. Контроллеры же, — как элементы информационной системы, — ответственны лишь за:

  • приём запроса от пользователя;
  • анализ запроса;
  • выбор следующего действия системы, соответственно результатам анализа (например, передача запроса другим элементам системы).

Только в этом случае контроллер становится «тонким» и выполняет исключительно функцию связующего звена (glue layer) между отдельными компонентами информационной системы.

Внедрение зависимостей в ASP.NET MVC

Хорошо. Но для того, чтобы следовать всему этому, нужно внедрить зависимости в контроллеры и представления. Как это сделать в ASP.NET MVC? Широко распространена практика внедрения в контроллер через свойства. Эту возможность предоставляют многие библиотеки вроде Autofac или Ninject, но есть и другие варианты, которые следует знать.

Внедрение зависимостей в контроллер через конструктор

Внедрить зависимость в контроллер через конструктор можно двумя способами:

  1. или другой инструмент внедрения зависимостей с поддержкой этой функции.
  2. Написав свою собственную фабрику контроллеров, и использовав внутри неё любой инструмент для разрешения зависимостей.

Внедрение зависимостей во View через публичные свойства

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

(новый класс-предок представления, файл можно разместить рядом с шаблоном)

(Razor-шаблон представления)

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

Логику получения и подготовки данных для отображения, если она слишком сложна, можно написать, перегрузив метод предка представления, и сохранив полученные данные в защищённые поля, которые можно использовать в шаблоне:

или прямо в шаблоне в блоке C#-кода (что на мой взгляд даже лучше, если нет необходимости писать дополнительные методы для преобразования данных модели в подходящий формат):

Так же в базовом классе этого представления можно описать несколько защищенных методов для обработки данных, которые можно потом использовать в шаблоне.

Внедрение зависимостей во View в ASP.NET MVC Core

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

Но для этого необходимо, чтобы этот интерфейс был зарегистрирован в методе класса :

Понятие привязки моделей

Привязка моделей представляет собой элегантный мост между HTTP-запросом и методами C#, определяющими действия. Большинство приложений ASP.NET MVC Framework в той или иной степени полагаются на привязку моделей, в том числе простой пример приложения, созданный в предыдущем разделе. Чтобы увидеть привязку моделей в работе, запустите приложение и перейдите на /Home/Index/1. Результат показан на рисунке ниже:

Указанный URL содержит значение свойства UserId объекта User, который необходимо отобразить, например:

/Home/Index/1

Инфраструктура ASP.NET MVC Framework транслирует эту часть URL и применяет ее в качестве аргумента при вызове метода Index() класса контроллера Home с целью обслуживания запроса:

public ActionResult Index(int id)

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

Процесс, приводящий к привязке моделей, начинается сразу после получения запроса и его обработки механизмом маршрутизации. В этом примере приложения конфигурация маршрутизации не изменялась, поэтому для обработки запроса использовался стандартный маршрут, который среда Visual Studio добавляет в файл /App_Start/RouteConfig.cs. В качестве напоминания, этот стандартный маршрут приведен ниже:

Вопросы определения и работы маршрутов подробно рассматривались ранее, поэтому здесь они повторяться не будут

Для процесса привязки моделей важной частью является необязательная переменная сегмента id. При переходе на URL вида /Home/Index/1 последний сегмент, который указывает интересующий объект User, присваивается переменной маршрутизации id

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

Стандартный активатор действий, ControllerActionInvoker, полагается на связыватели моделей при генерации объектов данных, которые требуются для вызова метода. Связыватели моделей определяются с помощью интерфейса IModelBinder, который показан в примере ниже. Мы еще вернемся к этому интерфейсу позже, когда будет рассматриваться создание специального связывателя модели.

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

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

Связыватель модели отвечает за предоставление значения int, которое может использоваться для вызова метода Index(). Это обычно означает трансформацию некоторого элемента данных запроса (такого как значения формы или строки запроса), но инфраструктура ASP.NET MVC Framework никак не ограничивает способ получения данных.

Позже будут предоставлены примеры специальных связывателей. Кроме того, будут продемонстрированы определенные возможности класса ModelBindingContext, экземпляр которого передается методу IModelBinder.BindModel().

Назначение

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

  1. К одной модели можно присоединить несколько видов, при этом не затрагивая реализацию модели. Например, некоторые данные могут быть одновременно представлены в виде электронной таблицы, гистограммы и круговой диаграммы;
  2. Не затрагивая реализацию видов, можно изменить реакции на действия пользователя (нажатие мышью на кнопке, ввод данных) — для этого достаточно использовать другой контроллер;
  3. Ряд разработчиков специализируется только в одной из областей: либо разрабатывают графический интерфейс, либо разрабатывают бизнес-логику. Поэтому возможно добиться того, что программисты, занимающиеся разработкой бизнес-логики (модели), вообще не будут осведомлены о том, какое представление будет использоваться.

Модель

«Модель» — это постоянное хранилище данных, которое используется по всей структуре. Компонент обеспечивает доступ к данным для просмотра, отбора, записи. По сути это мост между другими компонентами: «Контроллер» и «Представление».

«Модель» не «знает», что происходит с данными дальше. Её задачи — поиск и подготовка данных, передаваемых прочим компонентам MVC, а также обработка их в постоянном хранилище. По сути это «привратник», который стоит возле хранилища данных и не задаёт лишних вопросов, однако принимает все запросы, которые поступают. «Модель» — вершина структуры MVC, без неё невозможна связь между «Представлением» и «Контроллером».

Работа со сложными моделями

Последнее обновление: 31.10.2015

В предыдущей теме мы создали две модели Player и Team и вывели элементы из таблицы Players на страницу. Теперь посмотрим, как
проделать остальные операции с моделями. В общем-то тут будет все то же самое, что и с обычными моделями за тем исключением, что нам надо учитывать
навигационные свойства, которые есть в сложной модели.

Добавление модели

При добавлении модели, имеющий внешний ключ, характерно все то же самое, что и для обычной модели. Единственное дополнение — нам надо также передавать в
представление набор значений для связи внешнего ключа с другой таблицей. Итак, добавим в контроллер следующее действие Create:


public ActionResult Create()
{
    // Формируем список команд для передачи в представление
    SelectList teams = new SelectList(db.Teams, "Id", "Name");
    ViewBag.Teams = teams;
    return View();
}


public ActionResult Create(Player player)
{
    //Добавляем игрока в таблицу
    db.Players.Add(player);
    db.SaveChanges();
    // перенаправляем на главную страницу
    return RedirectToAction("Index");
}

Первый метод обрабатывает GET-запрос и возвращает представление, передавая в него объект SelectList —
список всех команд.

Второй метод получает введенную пользователем в представлении модель и добавляет ее в БД. А теперь создадим представление Create.cshtml:

@model NavigationProperty.Models.Player

@{
    ViewBag.Title = "Добавление игрока";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Добавление нового игрока</h2>

@using (Html.BeginForm())
{
    <fieldset>
        <legend>Футболист</legend>

        <p>
            Имя игрока <br />
            @Html.EditorFor(model => model.Name)
        </p>

        <p>
            Возраст <br />
            @Html.EditorFor(model => model.Age)
        </p>

        <p>
            Позиция на поле  <br />
            @Html.EditorFor(model => model.Position)
        </p>
        <p>
            Команда <br />
            @Html.DropDownListFor(model => model.TeamId, ViewBag.Teams as SelectList)
        </p>

        <p>
            <input type="submit" value="Добавить игрока" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("К списку игроков", "Index")
</div>

Как и в случае с простыми моделями, мы привязываем поля к определенному свойству.

Тут следует лишь отметить создание выпадающего списка, из которого мы выбираем команду. Выбираемое значение в этом списке привязывается
к свойству модели TeamId.

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

Редактирование работает подобным способом. Определим в контроллере следующее действие Edit:


public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return HttpNotFound();
    }
    // Находим в бд футболиста
    Player player = db.Players.Find(id);
    if (player != null)
    {
        // Создаем список команд для передачи в представление
        SelectList teams = new SelectList(db.Teams, "Id", "Name", player.TeamId);
        ViewBag.Teams = teams;
        return View(player);
    }
    return RedirectToAction("Index");
}


public ActionResult Edit(Player player)
{
    db.Entry(player).State = EntityState.Modified;
    db.SaveChanges();
    return RedirectToAction("Index");
}

Здесь также в виде объекта SelectList создается список команд, которые извлекаются из БД. И после получения запроса на редактирование
определенной модели Player контроллер передает эту модель и список команд в представление Edit.cshtml:

@model NavigationProperty.Models.Player
@{
    ViewBag.Title = "Edit";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h2>Изменение игрока</h2>

@using (Html.BeginForm())
{
    <fieldset>
        <legend>Футболист</legend>

        @Html.HiddenFor(model => model.Id)

        <p> Имя игрока <br />
            @Html.EditorFor(model => model.Name)
        </p>

        <p>Возраст <br />
        @Html.EditorFor(model => model.Age)
        </p>

        <p>Позиция на поле  <br />
            @Html.EditorFor(model => model.Position)
        </p>
        <p>Команда <br />
            @Html.DropDownListFor(model => model.TeamId, ViewBag.Teams as SelectList)
        </p>
        <p>
            <input type="submit" value="Сохранить" />
        </p>
    </fieldset>
}
<div>
    @Html.ActionLink("Вернуться к списку футболистов", "Index")
</div>

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

НазадВперед

Создание первого приложенияCreate your first app

На начальной страницевыберите Новый проект.On the Start page, select New Project. В диалоговом окне Новый проект выберите категорию визуальные C# элементы слева, затем веб, а затем выберите шаблон проекта веб-приложение ASP.NET (.NET Framework) .In the New project dialog box, select the Visual C# category on the left, then Web, and then select the ASP.NET Web Application (.NET Framework) project template. Присвойте проекту имя «MvcMovie» и нажмите кнопку ОК.Name your project «MvcMovie» and then choose OK.

В диалоговом окне Создание веб-приложения ASP.NET выберите MVC и нажмите кнопку ОК.In the New ASP.NET Web Application dialog, choose MVC and then choose OK.

Visual Studio использовала шаблон по умолчанию для только что созданного проекта MVC ASP.NET, поэтому у вас есть рабочее приложение, не делая ничего.Visual Studio used a default template for the ASP.NET MVC project you just created, so you have a working application right now without doing anything! Это простой «Hello World!»This is a simple «Hello World!» и это хорошее место для запуска приложения.project, and it’s a good place to start your application.

Нажмите клавишу F5, чтобы запустить отладку.Press F5 to start debugging. При нажатии клавиши F5Visual Studio запускает IIS Express и запускает веб-приложение.When you press F5, Visual Studio starts IIS Express and runs your web app. Затем Visual Studio запустит браузер и откроет домашнюю страницу приложения.Visual Studio then launches a browser and opens the application’s home page

Обратите внимание, что в адресной строке браузера указано и не что-то вроде .Notice that the address bar of the browser says and not something like. Это связано с тем, что всегда указывает на локальный компьютер, который в данном случае выполняет только что созданное приложение.That’s because always points to your own local computer, which in this case is running the application you just built

Когда Visual Studio выполняет веб-проект, для веб-сервера используется случайный порт.When Visual Studio runs a web project, a random port is used for the web server. На рисунке ниже показан номер порта 1234.In the image below, the port number is 1234. При запуске приложения вы увидите другой номер порта.When you run the application, you’ll see a different port number.

Этот шаблон по умолчанию предназначается для , и страниц.Right out of the box this default template gives you , , and pages. На рисунке ниже не показаны ссылки Домашняя страница, сведения о программеи контакт .The image below doesn’t show the Home, About, and Contact links. В зависимости от размера окна браузера может потребоваться щелкнуть значок навигации, чтобы просмотреть эти ссылки.Depending on the size of your browser window, you might need to click the navigation icon to see these links.

Приложение также обеспечивает поддержку для регистрации и входа в систему.The application also provides support to register and log in. Следующим шагом является изменение способа работы этого приложения и немного подробнее о ASP.NET MVC.The next step is to change how this application works and learn a little bit about ASP.NET MVC. Закройте приложение ASP.NET MVC и давайте изменим код.Close the ASP.NET MVC application and let’s change some code.

Список текущих руководств см. в статье рекомендации по MVC.For a list of current tutorials, see MVC recommended articles.

Различия описания концепции шаблона

С развитием объектно-ориентированного программирования и понятия о шаблонах проектирования — был создан ряд модификаций концепции MVC, которые при реализации у разных авторов могут отличаться от оригинальной. Так, например, Эриан Верми в 2004 году описал пример обобщённого MVC.

В предисловии к диссертации «Naked objects» Ричарда Поусона (Richard Pawson), — Трюгве Реенскауг упоминает свою неопубликованную наиболее раннюю версию MVC, согласно которой:

  • Модель относилась к «разуму» пользователя;
  • Под представлением имелся в виду редактор, позволяющий пользователю просматривать и обновлять информацию;
  • Контроллер являлся инструментом для связывания представлений воедино и применялся пользователем для решения его задач.

Два слова об MVC

Применение паттерна MVC заключается в разделении собственно данных, их отображения и обработки действий пользователя по трем компонентам.

Модель (Model)
Собственно данные, методы для работы с данными, изменения и обновления данных.
Представление/Вид (View)
Отображение данных, оформление и другие аспекты презентации модели
Контроллер (Controller)
Реагирует на действия пользователя, интерпретирует данные, введенные пользователем, и информирует модель и производит необходимые манипуляции с моделью и видом.

Между компонентами есть взаимодействия, изображенные стрелочками на рисунке (один из устоявшихся вариантов MVC).

Главный тезис статьи можно сформулировать так:

Дальнейшая часть статьи — обоснование с примерами, почему именно так, а не иначе, и почему устоявшаяся практика MVC для javascript-интерфейсов работает плохо.

Особенности браузера

Никто не говорит о том, что MVC вообще — это плохо. Наоборот, MVC — это хорошо. Но вся штука в том, что при программировании для Web есть как минимум 3 важных особенности.

Паттерн MVC увеличивает количество кода за счет появления дополнительных межкомпонентных коммуникаций. То есть, не «сделай это», а «попроси компонент XXX сделать это и обеспечь его данными».

Будем исходить из предположения, что разрабатываем сложный интерфейс.
В самом деле, если интерфейс заведомо простой (и таким останется) — то лишние паттерны тем более не нужны.

Javascript/DOM в браузере — не самая быстрая платформа, а приложения фактически являются real-time, т.е интерфейс должен реагировать и отображаться по возможности мгновенно, плавно, и не сильно жрать память.

Межкомпонентные коммуникации Model-View добавляют тормозов. Это повод их убрать.

Далее, и модель и вид в javascript, как правило, оперируют данными в одинаковом формате.

То есть, значение в форме — не рисованный объект типа , как это может быть в обычном десктоп-програмировании, не кодированная строка пикселей, а обычный текст.

Поэтому отделение Model от View приводит к излишнему дублированию данных.

Что такое View в javascript-интерфейсах?

Это в первую очередь DOM и CSS. Модель DOM заранее включает в себя следующее:

  • Хранение любых свойств:
    var div = document.createElement('div')
    div.myProperty = 123
    
    //..  и даже ... 
    div.myMethod = function() {
        alert(this.innerHTML)
    }
    
  • Древовидную иерархию — дерево элементов DOM
  • Средства поиска, выборки элементов. Наиболее известнен метод . Сложные CSS-селекторы и XPath постепенно приходят в браузеры, и успешно эмулируются JS-библиотеками.

При этом основные аспекты оформления задаются вообще отдельно от DOM, при помощи CSS.

Вы видите, DOM — это совсем не тот «классический» View, который обычно имеется в виду. Он гораздо мощнее.

Так зачем нам поддерживать иерархию, средства выборки и контейнеры для свойств в специальных javascript-объектах Модели, если с этим замечательно справляется DOM/View ?

Минусы, как и плюсы, связаны с производительностью.

При работе исключительно с javascript, работа идет в едином пространстве интерпретатора javascript. Это куда быстрее, чем обращаться к DOM-объектам, который в Microsoft относятся к COM, в Firefox — к XPCOM, в общем — живут отдельно от javascript-движка.

Эта проблема раньше была очень актуальна для Internet Explorer.

На момент написания статьи она фактически решена как библиотечными средствами (clobbering, учет и зачистка назначаемых DOM-элементам свойств), так и патчами.

В частности, как в IE7, так и в IE6 с обновлениями середины 2007 связка DOM-javascript почти не течет.

При разработке приложений надо смотреть, насколько тесно изменение ее модели (данных) завязано на изменение представления (DOM).

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

Однако обычно обновление данных тесно завязано с обновлением их вида, и это еще один довод к тому, чтобы их не разделять.

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

Современные js-фреймворки (YUI, dojo, jQuery) ликвидируют бОльшую часть утечек памяти.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Adblock
detector