Asp задание границ приложения


Содержание

ASP.Net — введение, жизненный цикл и программа Hello World

ASP.Net — это платформа для веб-разработки, созданная корпорацией Microsoft . Она была выпущена в 2002 году.

Последняя версия ASP.Net — 4.6. предназначена для работы с протоколом HTTP . Это стандартный протокол, используемый во всех веб-приложениях.

ASP.Net-приложения можно создавать на различных .Net-языках . К ним относятся C # , VB.NET и J # .

Из этой статьи об ASP.Net для начинающих вы узнаете:

  • Что такое ASP.Net ?
  • О жизненном цикле ASP.Net ;
  • О жизненном цикле страницы ASP.Net ;
  • Как создать простую программу на ASP.Net .

Что такое ASP.Net?

ASP.Net — это платформа, которая используется для разработки веб-приложений. Базовая архитектура ASP.Net приведена ниже:

Архитектура .Net Framework включает в себя следующие компоненты:

  1. Язык — в .Net для разработки веб-приложений используются VB.net и C# ;
  2. Библиотека — .NET включает в себя набор библиотек стандартных классов. В частности, библиотека Web используется для разработки веб-приложений;
  3. Common Language Runtime (CLR) — общеязыковая инфраструктура или CLI . На ее основе выполняются .Net программы. CLR используется для выполнения ключевых действий. Действия включают в себя обработку исключений и освобождение ресурсов ( Garbage Collection ).

Ключевые характеристики ASP.Net , важные для начинающих:

  • Разделения дизайна и кода — позволяет легче поддерживать приложения ASP.NET . Общий тип файлов ASP.Net — aspx . Предположим, что у нас есть веб-страница с именем MyPage.aspx . К ней должен прилагаться еще один файл с именем MyPage.aspx.cs , содержащий часть кода страницы. Таким образом, Visual Studio создает отдельные файлы для каждой веб-страницы: один для дизайна, а второй для кода.
  • Управление состоянием — ASP.Net позволяет управлять состоянием. HTTP известен, как протокол, не имеющий состояний. Давайте в качестве примера рассмотрим приложение корзины интернет-магазина. Когда пользователь решил, какой товар он хочет купить, он нажимает кнопку « Добавить в корзину ».

Приложение должно запомнить информацию, касающуюся того, что пользователь решил приобрести. Это называется запоминание состояния приложения в текущий момент времени. Протокол HTTP не поддерживает состояний. Когда пользователь переходит на страницу оплаты товара, HTTP не сохраняет информацию о товарах, находящихся в корзине. Чтобы перенести их на страницу оплаты, нужно добавить код. Такая реализация может стать более сложной. Но ASP.Net позволяет управлять состояниями: запоминать товары в корзине и передавать их на страницу оплаты.

  • Кэширование — ASP.Net реализовывает концепцию кэширования. Это улучшает производительность приложения. Кэшируя те страницы, которые часто запрашиваются, их можно держать во временном хранилище. Эти страницы можно быстрее извлечь, уменьшая время отклика. Так что кэширование может значительно повысить производительность приложения.

Жизненный цикл ASP.Net

При изучении ASP.Net mvc 4 для начинающих важно знать жизненный цикл приложения. Когда запускается приложение ASP.Net , выполняется несколько этапов. Эта цепочка составляет жизненный цикл приложения:

  1. Запуск — жизненный цикл приложения ASP.NET начинается, когда пользователь выполняет запрос, направленный на веб-сервер к приложению ASP.Net . Обычно это происходит, когда пользователь переходит на главную страницу приложения в первый раз. В течение этого времени существует метод, называемый Application_Start , который выполняется на веб-сервере. В этом методе для всех глобальных переменных устанавливаются их значения по умолчанию;
  2. Создание объектов — создание на веб-сервере HttpContext , HttpRequest и HttpResponse . HttpContext — это контейнер для объектов HTTPRequest и HTTPResponse . Объект HttpRequest содержит информацию о текущем запросе, включая куки и информацию браузера. Объект HttpResponse содержит ответ, который отправляется клиенту;
  3. Создание HttpApplication — этот объект создается на веб-сервере. Он используется для обработки каждого последующего запроса, адресованного приложению. Предположим, что у нас есть два веб-приложения. Одним из них является приложение корзины, а другое — это новостной сайт. Для каждого приложения создается объект HttpApplication . Все дальнейшие запросы к каждому сайту будут обрабатываться соответствующим экземпляром HttpApplication ;
  4. Сброс — это событие вызывается до удаления экземпляра приложения. В это время можно использовать данный метод, чтобы вручную сбросить любой неуправляемый ресурс;
  5. Конец приложения — на данном этапе приложение окончательно выгружается из памяти.

Жизненный цикл страницы ASP.Net

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

В рамках этой статьи ASP.Net для начинающих рассмотрим последовательность этапов обработки страницы:

  1. Запрос страницы — когда страница запрашивается, сервер проверяет, запрашивается ли она в первый раз. Если да, то страница создается, обрабатывается ответ и отправляется пользователю. Если страница запрашивается не в первый раз, проверяется кэш. Если страница существует в кэше, сохраненный ответ отправляется пользователю;
  2. Запуск страницы — на этом этапе создаются объекты Request и Response . Объект Request используется для хранения информации, которая была отправлена при запросе страницы. Объект Response используется для хранения информации, которая отправляется обратно пользователю;
  3. Инициализация страницы — на этом этапе инициализируются все элементы управления веб-страницы;
  4. Загрузка страницы — страница загружается со всеми значениями по умолчанию. Например, если текстовое поле должно иметь значение по умолчанию, оно загружается во время page load ;
  5. Валидация — в некоторых случаях для определенных форм может быть задана валидация. Например, может запрашиваться подтверждение того, что элемент списка содержит определенный набор значений. Если условие не выполняется, должна выводиться ошибка при загрузке страницы;
  6. Повторная обработка событий — возникает, если страница загружается снова. Это происходит в ответ на предыдущее событие. Если пользователь нажимает на кнопку отправки данных на странице. В этом случае та же страница отображается снова. Тогда вызывается повторный обработчик события;
  7. Отображение страницы — происходит перед тем, как ответ отправляется пользователю. Вся информация о форме сохраняется, а результат отправляется пользователю в виде полной веб-страницы;
  8. Выгрузка — после того, как страница отправляется пользователю, больше нет необходимости хранить объекты веб-формы в памяти. Таким образом, процесс выгрузки включает в себя удаление всех ненужных объектов из памяти.

Программа «Hello World» в ASP.Net

Изучение ASP.Net web forms для начинающих лучше начать с создания простого приложение « Hello, World «. Для этого необходимо выполнить следующие шаги.

Шаг 1: Создание нового проекта в Visual Studio . После запуска Visual Studio нужно выбрать пункт меню Новый> Проект :

Шаг 2: Следующим шагом является выбор типа проекта — веб-приложение ASP.NET . Здесь нужно указать название и расположение проекта.

  1. В диалоговом окне проекта выберите вариант « Веб » в левой панели. А затем « Веб-приложение ASP.Net »;
  2. Задайте имя приложения и место его хранения;
  3. Нажимаем на кнопку « OK », чтобы Visual Studio создал проект.

Шаг 3: В следующем окне нужно выбрать тип веб-приложения ASP.NET , которое должно быть создано. Мы хотим создать простое приложение веб-формы.

  • Выберите тип проекта – « Пустой »;
  • Выберите опцию « Веб-форма ». После этого будут добавлены общие папки. Они необходимы для создания базового приложения веб-формы;
  • В конце нажимаем на кнопку « OK », чтобы Visual Studio создал приложение.

Если вы выполните указанные выше шаги руководства ASP.Net для начинающих, то получите в Visual Studio результат, продемонстрированный на рисунке ниже:

В « Solution explorer » появится приложение DemoApplication . Оно содержит два файла проекта, как показано на рисунке выше. Один из ключевых файлов проекта — это Global.asax.cs . Он содержит информацию конкретного приложения. В этом файле можно инициализировать все переменные, определив для них значения по умолчанию.

Шаг 4: Теперь пришло время добавить в проект файл веб-формы. Это файл, который будет содержать весь код проекта.

  • Кликните правой кнопкой мыши по DemoApplication ;
  • Выберите из контекстного меню пункт Добавить> Веб-форма .

Шаг 5: В следующем окне задайте имя веб-формы. В нашем случае это будет Demo .

Visual Studio автоматически создаст веб-форму Demo и откроет ее.

Шаг 6: Следующим шагом является добавление кода, который позволит отобразить « Hello World «. Это можно сделать, добавив одну строку кода в файл Demo.aspx :

  • Объект Response в ASP.Net используется для передачи информации обратно пользователю. В данном случае мы используем метод Write объекта Response , чтобы написать текст « Hello World «. Маркеры используются для добавления специфического кода ASP.net .

Если вы выполните все шаги, перечисленные в этой статье об ASP.Net mvc для начинающих и запустите созданную программу в Visual Studio , то получите следующий результат:

В окне браузера отображается фраза « Hello, World «.


Лабораторная работа №11 Разработка приложения с помощью технологии asp.Net

Цель работы: изучение среды разработки Web-приложений Visual Studio 2005 и элементов диалога. Cоздание динамических страниц. Рассмотрение структуры проекта.

Теоретические сведения

Microsoft .NET Framework — это платформа для создания, развертывания и запуска web-сервисов и приложений. Она предоставляет высокопроизводительную, основанную на стандартах многоязыковую среду, которая позволяет интегрировать существующие приложения с приложениями и сервисами следующего поколения, а также решать задачи развертывания и использования интернет-приложений. .NET Framework состоит из трех основных частей — общеязыковой среды выполнения (common language runtime), иерархического множества унифицированных библиотек классов и компонентной версии ASP, называемой ASP .NET.

ASP .NET — это часть технологии .NET, используемая для написания мощных клиент-серверных интернет-приложений. Она позволяет создавать динамические страницы HTML. ASP .NET возникла в результате объединения более старой технологии ASP (активные серверные страницы) и .NET Framework. Она содержит множество готовых элементов управления, применяя которые, можно быстро создавать интерактивные web-сайты. Вы также можете использовать сервисы, предоставляемые другими сайтами, прозрачно для пользователей вашего сайта. В общем, возможности ASP .NET ограничены только вашим воображением

В 2000 году на конференции разработчиков в качестве части новой технологии .NET Microsoft представила ASP+. С выходом .NET Framework 1.0 она стала называться ASP .NET.

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

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

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

Платформа .NET Framework предоставляет приложениям среду выполнения, сама непосредственно взаимодействуя с операционной системой. Выше лежит интерфейс ASP .NET-приложений, на котором в свою очередь базируются web-формы (ASP .NET-страницы) и web-сервисы. Интерфейс .NET Framework позволяет стандартизировать обращение к системным вызовам и предоставляет среду для более быстрой и удобной разработки. CLR обеспечивает единый набор сервисов для всех языков.

ASP .NET использует технологию доступа к данным ADO .NET, которая обеспечивает единый интерфейс для доступа к базам данных SQL Server и файлам XML. Кроме того, усиленная модель безопасности позволяет обеспечивать защиту клиента и сервера от несанкционированного доступа.

В 2004 году появилась версия ASP .NET 2.0 (бета-версия, окончательный выход — конец 2005 — начало 2006 гг.). Как утверждается, эта версия позволяет сократить объем кодирования на 70%. Новые возможности версии 2.0 — использование шаблонов дизайна страниц (Master Page), упрощенная локализация web-приложений, более 50 новых серверных элементов управления. Цели, которые преследовали разработчики новой версии, — повысить скорость разработки сайтов, масштабируемость, легкость поддержки и администрирования сайтов, скорость работы сервера. Появилась панель оснастки MMC (консоль управления Microsoft), предоставляющая графический интерфейс для управления настройками ASP .NET. Изменять настройки проекта теперь можно и через web-интерфейс. ASP .NET 2.0 поддерживает работу на 64-битных процессорах. Сервис персонализации (personalization) предоставляет готовое решение для хранения персональных данных, непосредственно характеризующих пользователя сайта, — так называемого профиля пользователя (Profile).

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

Предыдущие версии Visual Studio для проектов ASP .NET требовали наличия на машине разработчика сервера IIS. Теперь сервер встроен в среду разработки.

ASP .NET 2.0 и Visual Studio 2005 предоставляют инструменты для легкого построения локализируемых сайтов, которые определяют предпочитаемый язык пользователя и посылают ему страницы на его языке.

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

В ASP .NET 2.0 встроена технология автоматического обновления кэширования баз данных. Данные, полученные из базы, хранятся на сервере, и он не обращается к базе для обработки повторного запроса. При изменении базы данных кэш обновляет свое содержимое.

ASP .NET — это технология, а не язык, и позволяет программировать на разных языках — С#, Visual Basic, J#. «В платформе .NET все языки равны, но некоторые — равнее» (Дж. Оруэлл). Вот таким языком и является С#, потому что он был специально создан для этой платформы. Программирование C# позволяет в полной мере использовать концепции, методы и паттерны объектно-ориентированной разработки. Язык Visual Basic 8.0 наделен почти теми же возможностями. Чтобы научиться ASP .NET, вам нужно знать основы HTML, а знание asp не обязательно. Оно может даже помешать, так как придется менять образ мышления. Также для понимания желательно знать CSS и JavaScript.

Фоновые задачи с размещенными службами в ASP.NET Core Background tasks with hosted services in ASP.NET Core

Авторы: Luke Latham (Люк Латэм) и Jeow Li Huan (Чжоу Ли Хуан) By Luke Latham and Jeow Li Huan

В ASP.NET Core фоновые задачи реализуются как размещенные службы. In ASP.NET Core, background tasks can be implemented as hosted services. Размещенная служба — это класс с логикой фоновой задачи, реализующий интерфейс IHostedService. A hosted service is a class with background task logic that implements the IHostedService interface. Этот раздел содержит три примера размещенных служб: This topic provides three hosted service examples:

  • Фоновая задача, которая выполняется по таймеру. Background task that runs on a timer.
  • Размещенная служба, которая активирует службу с заданной областью. Hosted service that activates a scoped service. Служба с заданной областью может использовать внедрение зависимостей. The scoped service can use dependency injection (DI).
  • Очередь фоновых задач, которые выполняются последовательно. Queued background tasks that run sequentially.

Пример приложения предоставляется в двух версиях: The sample app is provided in two versions:

  • Веб-узел – удобно использовать для размещения веб-приложений. Web Host – Web Host is useful for hosting web apps. Пример кода, приведенный в этой статье, относится к этой версии примера приложения. The example code shown in this topic is from Web Host version of the sample. Дополнительные сведения см. в статье о веб-узле. For more information, see the Web Host topic.
  • Универсальный узел – — новая возможность в ASP.NET Core 2.1. Generic Host – Generic Host is new in ASP.NET Core 2.1. Дополнительные сведения см. в статье об универсальном узле. For more information, see the Generic Host topic.

Шаблон службы рабочей роли Worker Service template

Шаблон службы рабочей роли ASP.NET Core может служить отправной точкой для написания длительно выполняющихся приложений служб. The ASP.NET Core Worker Service template provides a starting point for writing long running service apps. Чтобы использовать шаблон в качестве основы для приложения размещенных служб, выполните указанные ниже действия. To use the template as a basis for a hosted services app:

  • Visual Studio Visual Studio
  • Visual Studio для Mac Visual Studio for Mac
  • Интерфейс командной строки .NET Core .NET Core CLI
  1. Создайте новый проект. Create a new project.
  2. Выберите службу рабочей роли. Select Worker Service. Выберите Далее. Select Next.
  3. В поле Имя проекта укажите имя проекта или оставьте имя по умолчанию. Provide a project name in the Project name field or accept the default project name. Выберите Создать. Select Create.
  4. В диалоговом окне Создать службу рабочей роли выберите Создать. In the Create a new Worker service dialog, select Create.
  1. Создайте новый проект. Create a new project.
  2. В разделе .NET Core на боковой панели выберите Приложение. Select App under .NET Core in the sidebar.
  3. В разделе ASP.NET Core выберите Рабочая роль. Select Worker under ASP.NET Core. Выберите Далее. Select Next.
  4. Для параметра Требуемая версия .NET Framework выберите .NET Core 3.0 или более поздней версии. Select .NET Core 3.0 or later for the Target Framework. Выберите Далее. Select Next.
  5. Введите имя в поле Имя проекта. Provide a name in the Project Name field. Выберите Создать. Select Create.

Используйте шаблон службы рабочей роли ( worker ) с командой dotnet new из командной оболочки. Use the Worker Service ( worker ) template with the dotnet new command from a command shell. В приведенном ниже примере создается приложение службы рабочей роли с именем ContosoWorker . In the following example, a Worker Service app is created named ContosoWorker . Папка для приложения ContosoWorker создается автоматически при выполнении команды. A folder for the ContosoWorker app is created automatically when the command is executed.

Пакет Package


Ссылка на пакет Microsoft.Extensions.Hosting добавляется неявно для приложений ASP.NET Core. A package reference to the Microsoft.Extensions.Hosting package is added implicitly for ASP.NET Core apps.

Интерфейс IHostedService IHostedService interface

Интерфейс IHostedService определяет два метода для объектов, которые управляются узлом: The IHostedService interface defines two methods for objects that are managed by the host:

StartAsync(CancellationToken) – StartAsync содержит логику для запуска фоновой задачи. StartAsync(CancellationToken) – StartAsync contains the logic to start the background task. Первым вызывается StartAsync : StartAsync is called before:

  • Настраивается конвейер обработки запросов приложения ( Startup.Configure ). The app’s request processing pipeline is configured ( Startup.Configure ).
  • Запускается сервер и активируется IApplicationLifetime.ApplicationStarted. The server is started and IApplicationLifetime.ApplicationStarted is triggered.

Поведение по умолчанию можно изменить таким образом, чтобы StartAsync размещенной службы выполнялся после настройки конвейера приложения и вызова ApplicationStarted . The default behavior can be changed so that the hosted service’s StartAsync runs after the app’s pipeline has been configured and ApplicationStarted is called. Чтобы изменить поведение по умолчанию, добавьте размещенную службу ( VideosWatcher в следующем примере) после вызова ConfigureWebHostDefaults : To change the default behavior, add the hosted service ( VideosWatcher in the following example) after calling ConfigureWebHostDefaults :

StopAsync(CancellationToken) – запускается, когда происходит нормальное завершение работы узла. StopAsync(CancellationToken) – Triggered when the host is performing a graceful shutdown. StopAsync содержит логику для завершения фоновой задачи. StopAsync contains the logic to end the background task. Реализуйте IDisposable и методы завершения (деструкторы) для освобождения неуправляемых ресурсов. Implement IDisposable and finalizers (destructors) to dispose of any unmanaged resources.

Токен отмены использует заданное по умолчанию 5-секундное время ожидания, указывающее, что процесс завершения работы больше не должен быть нормальным. The cancellation token has a default five second timeout to indicate that the shutdown process should no longer be graceful. При запросе отмены происходит следующее: When cancellation is requested on the token:

  • должны быть прерваны все оставшиеся фоновые операции, выполняемые приложением; Any remaining background operations that the app is performing should be aborted.
  • должны быть незамедлительно возвращены все методы, вызываемые в StopAsync . Any methods called in StopAsync should return promptly.

Однако после запроса отмены выполнение задач не прекращается — вызывающий объект ожидает завершения всех задач. However, tasks aren’t abandoned after cancellation is requested—the caller awaits all tasks to complete.

Если приложение завершает работу неожиданно (например, при сбое процесса приложения), StopAsync может не вызываться. If the app shuts down unexpectedly (for example, the app’s process fails), StopAsync might not be called. Поэтому вызов методов или выполнение операций в StopAsync может быть невозможным. Therefore, any methods called or operations conducted in StopAsync might not occur.

Чтобы увеличить время ожидания завершения работы по умолчанию (пять секунд), установите следующие значения: To extend the default five second shutdown timeout, set:

  • ShutdownTimeout при использовании универсального узла. ShutdownTimeout when using Generic Host. Дополнительные сведения можно найти по адресу: Универсальный узел .NET. For more information, see Универсальный узел .NET.
  • Параметр конфигурации узла для времени ожидания завершения работы при использовании веб-узла. Shutdown timeout host configuration setting when using Web Host. Дополнительные сведения можно найти по адресу: Веб-узел ASP.NET Core. For more information, see Веб-узел ASP.NET Core.

Размещенная служба активируется при запуске приложения и нормально завершает работу при завершении работы приложения. The hosted service is activated once at app startup and gracefully shut down at app shutdown. Если во время выполнения задачи в фоновом режиме возникает ошибка, необходимо вызвать Dispose , даже если StopAsync не вызывается. If an error is thrown during background task execution, Dispose should be called even if StopAsync isn’t called.

BackgroundService BackgroundService

BackgroundService — это базовый класс для реализации долго выполняющегося интерфейса IHostedService. BackgroundService is a base class for implementing a long running IHostedService. BackgroundService предоставляет абстрактный метод ExecuteAsync(CancellationToken stoppingToken) для хранения логики службы. BackgroundService provides the ExecuteAsync(CancellationToken stoppingToken) abstract method to contain the service’s logic. stoppingToken активируется при вызове IHostedService.StopAsync. The stoppingToken is triggered when IHostedService.StopAsync is called. Реализация этого метода возвращает значение Task , представляющее все время существования фоновой службы. The implementation of this method returns a Task that represents the entire lifetime of the background service.

Илон Маск рекомендует:  Демонстрация различий свойств innerText, innerHTML, outerText, outerHTML. JavaScript

Кроме того, в необязательном порядке переопределяет методы, определенные в IHostedService , чтобы запустить код запуска и завершения работы службы: In addition, optionally override the methods defined on IHostedService to run startup and shutdown code for your service:

  • StopAsync(CancellationToken cancellationToken) – StopAsync вызывается, когда происходит нормальное завершение работы узла приложения. StopAsync(CancellationToken cancellationToken) – StopAsync is called when the application host is performing a graceful shutdown. cancellationToken возвращается, когда узел решает принудительно завершить работу службы. The cancellationToken is signalled when the host decides to forcibly terminate the service. Если этот метод переопределен, вы должны вызвать (и await ) метод базового класса, чтобы обеспечить правильное завершение работы службы. If this method is overridden, you must call (and await ) the base class method to ensure the service shuts down properly.
  • StartAsync(CancellationToken cancellationToken) – StartAsync вызывается для запуска фоновой службы. StartAsync(CancellationToken cancellationToken) – StartAsync is called to start the background service. cancellationToken возвращается, если процесс запуска прерван. The cancellationToken is signalled if the startup process is interrupted. Реализация возвращает значение Task , представляющее процесс запуска службы. The implementation returns a Task that represents the startup process for the service. Никакие другие службы не запускаются до завершения этого Task . No further services are started until this Task completes. Если этот метод переопределен, вы должны вызвать (и await ) метод базового класса, чтобы обеспечить правильный запуск службы. If this method is overridden, you must call (and await ) the base class method to ensure the service starts properly.

Фоновые задачи с заданным временем Timed background tasks

Для фоновых задач с заданным временем используется класс System.Threading.Timer. A timed background task makes use of the System.Threading.Timer class. Таймер запускает метод DoWork задачи. The timer triggers the task’s DoWork method. Таймер отключается методом StopAsync и удаляется при удалении контейнера службы методом Dispose : The timer is disabled on StopAsync and disposed when the service container is disposed on Dispose :

Служба регистрируется в IHostBuilder.ConfigureServices (Program.cs) с использованием метода расширения AddHostedService : The service is registered in IHostBuilder.ConfigureServices (Program.cs) with the AddHostedService extension method:

Использование службы с заданной областью в фоновой задаче Consuming a scoped service in a background task

Чтобы использовать службы с заданной областью в BackgroundService , создайте область. To use scoped services within a BackgroundService , create a scope. Для размещенной службы по умолчанию не создается область. No scope is created for a hosted service by default.

Служба фоновой задачи с заданной областью содержит логику фоновой задачи. The scoped background task service contains the background task’s logic. В следующем примере: In the following example:

  • Служба является асинхронной. The service is asynchronous. Метод DoWork возвращает значение Task . The DoWork method returns a Task . В демонстрационных целях в методе DoWork ожидается задержка в десять секунд. For demonstration purposes, a delay of ten seconds is awaited in the DoWork method.
  • В службу вставляется ILogger. An ILogger is injected into the service.

Размещенная служба создает область для разрешения службы фоновой задачи с заданной областью, чтобы вызвать ее метод DoWork : The hosted service creates a scope to resolve the scoped background task service to call its DoWork method. DoWork возвращает объект Task , ожидаемый в ExecuteAsync : DoWork returns a Task , which is awaited in ExecuteAsync :

Службы регистрируются в IHostBuilder.ConfigureServices (Program.cs). The services are registered in IHostBuilder.ConfigureServices (Program.cs). Размещенная служба регистрируется с использованием метода расширения AddHostedService : The hosted service is registered with the AddHostedService extension method:

Фоновые задачи в очереди Queued background tasks

В следующем примере QueueHostedService : In the following QueueHostedService example:

  • Метод BackgroundProcessing возвращает объект Task , ожидаемый в ExecuteAsync : The BackgroundProcessing method returns a Task , which is awaited in ExecuteAsync .
  • Фоновые задачи в очереди выводятся из очереди и выполняются в BackgroundProcessing : Background tasks in the queue are dequeued and executed in BackgroundProcessing .
  • Рабочие элементы ожидают остановки службы через StopAsync . Work items are awaited before the service stops in StopAsync .

Служба MonitorLoop обрабатывает задачи постановки в очередь для размещенной службы при выборе на устройстве ввода ключа w : A MonitorLoop service handles enqueuing tasks for the hosted service whenever the w key is selected on an input device:

  • В службу MonitorLoop внедряется IBackgroundTaskQueue . The IBackgroundTaskQueue is injected into the MonitorLoop service.
  • IBackgroundTaskQueue.QueueBackgroundWorkItem вызывается для постановки рабочего элемента в очередь: IBackgroundTaskQueue.QueueBackgroundWorkItem is called to enqueue a work item.
  • Рабочий элемент имитирует долго выполняющуюся фоновую задачу: The work item simulates a long-running background task:
    • Выполняется три 5-секундных задержки ( Task.Delay ). Three 5-second delays are executed ( Task.Delay ).
    • Оператор try-catch перехватывается OperationCanceledException, если задача отменена. A try-catch statement traps OperationCanceledException if the task is cancelled.

Службы регистрируются в IHostBuilder.ConfigureServices (Program.cs). The services are registered in IHostBuilder.ConfigureServices (Program.cs). Размещенная служба регистрируется с использованием метода расширения AddHostedService : The hosted service is registered with the AddHostedService extension method:

В ASP.NET Core фоновые задачи реализуются как размещенные службы. In ASP.NET Core, background tasks can be implemented as hosted services. Размещенная служба — это класс с логикой фоновой задачи, реализующий интерфейс IHostedService. A hosted service is a class with background task logic that implements the IHostedService interface. Этот раздел содержит три примера размещенных служб: This topic provides three hosted service examples:

  • Фоновая задача, которая выполняется по таймеру. Background task that runs on a timer.
  • Размещенная служба, которая активирует службу с заданной областью. Hosted service that activates a scoped service. Служба с заданной областью может использовать внедрение зависимостей. The scoped service can use dependency injection (DI)
  • Очередь фоновых задач, которые выполняются последовательно. Queued background tasks that run sequentially.

Пример приложения предоставляется в двух версиях: The sample app is provided in two versions:


  • Веб-узел – удобно использовать для размещения веб-приложений. Web Host – Web Host is useful for hosting web apps. Пример кода, приведенный в этой статье, относится к этой версии примера приложения. The example code shown in this topic is from Web Host version of the sample. Дополнительные сведения см. в статье о веб-узле. For more information, see the Web Host topic.
  • Универсальный узел – — новая возможность в ASP.NET Core 2.1. Generic Host – Generic Host is new in ASP.NET Core 2.1. Дополнительные сведения см. в статье об универсальном узле. For more information, see the Generic Host topic.

Пакет Package

Добавьте ссылку на метапакет Microsoft.AspNetCore.App или добавьте ссылку на пакет в пакет Microsoft.Extensions.Hosting. Reference the Microsoft.AspNetCore.App metapackage or add a package reference to the Microsoft.Extensions.Hosting package.

Интерфейс IHostedService IHostedService interface

Размещенные службы реализуют интерфейс IHostedService. Hosted services implement the IHostedService interface. Этот интерфейс определяет два метода для объектов, которые управляются узлом: The interface defines two methods for objects that are managed by the host:

StartAsync(CancellationToken) – StartAsync содержит логику для запуска фоновой задачи. StartAsync(CancellationToken) – StartAsync contains the logic to start the background task. При использовании Web Host StartAsync вызывается после запуска сервера и активации IApplicationLifetime.ApplicationStarted. When using the Web Host, StartAsync is called after the server has started and IApplicationLifetime.ApplicationStarted is triggered. При использовании универсального узла StartAsync вызывается до активации ApplicationStarted . When using the Generic Host, StartAsync is called before ApplicationStarted is triggered.

StopAsync(CancellationToken) – запускается, когда происходит нормальное завершение работы узла. StopAsync(CancellationToken) – Triggered when the host is performing a graceful shutdown. StopAsync содержит логику для завершения фоновой задачи. StopAsync contains the logic to end the background task. Реализуйте IDisposable и методы завершения (деструкторы) для освобождения неуправляемых ресурсов. Implement IDisposable and finalizers (destructors) to dispose of any unmanaged resources.

Токен отмены использует заданное по умолчанию 5-секундное время ожидания, указывающее, что процесс завершения работы больше не должен быть нормальным. The cancellation token has a default five second timeout to indicate that the shutdown process should no longer be graceful. При запросе отмены происходит следующее: When cancellation is requested on the token:

  • должны быть прерваны все оставшиеся фоновые операции, выполняемые приложением; Any remaining background operations that the app is performing should be aborted.
  • должны быть незамедлительно возвращены все методы, вызываемые в StopAsync . Any methods called in StopAsync should return promptly.

Однако после запроса отмены выполнение задач не прекращается — вызывающий объект ожидает завершения всех задач. However, tasks aren’t abandoned after cancellation is requested—the caller awaits all tasks to complete.

Если приложение завершает работу неожиданно (например, при сбое процесса приложения), StopAsync может не вызываться. If the app shuts down unexpectedly (for example, the app’s process fails), StopAsync might not be called. Поэтому вызов методов или выполнение операций в StopAsync может быть невозможным. Therefore, any methods called or operations conducted in StopAsync might not occur.

Чтобы увеличить время ожидания завершения работы по умолчанию (пять секунд), установите следующие значения: To extend the default five second shutdown timeout, set:

  • ShutdownTimeout при использовании универсального узла. ShutdownTimeout when using Generic Host. Дополнительные сведения можно найти по адресу: Универсальный узел .NET. For more information, see Универсальный узел .NET.
  • Параметр конфигурации узла для времени ожидания завершения работы при использовании веб-узла. Shutdown timeout host configuration setting when using Web Host. Дополнительные сведения можно найти по адресу: Веб-узел ASP.NET Core. For more information, see Веб-узел ASP.NET Core.

Размещенная служба активируется при запуске приложения и нормально завершает работу при завершении работы приложения. The hosted service is activated once at app startup and gracefully shut down at app shutdown. Если во время выполнения задачи в фоновом режиме возникает ошибка, необходимо вызвать Dispose , даже если StopAsync не вызывается. If an error is thrown during background task execution, Dispose should be called even if StopAsync isn’t called.

Фоновые задачи с заданным временем Timed background tasks

Для фоновых задач с заданным временем используется класс System.Threading.Timer. A timed background task makes use of the System.Threading.Timer class. Таймер запускает метод DoWork задачи. The timer triggers the task’s DoWork method. Таймер отключается методом StopAsync и удаляется при удалении контейнера службы методом Dispose : The timer is disabled on StopAsync and disposed when the service container is disposed on Dispose :

Служба зарегистрирована в Startup.ConfigureServices с методом расширения AddHostedService : The service is registered in Startup.ConfigureServices with the AddHostedService extension method:

Использование службы с заданной областью в фоновой задаче Consuming a scoped service in a background task

Чтобы использовать службы с заданной областью в IHostedService , создайте область. To use scoped services within an IHostedService , create a scope. Для размещенной службы по умолчанию не создается область. No scope is created for a hosted service by default.

Служба фоновой задачи с заданной областью содержит логику фоновой задачи. The scoped background task service contains the background task’s logic. В следующем примере в службу вставляется ILogger: In the following example, an ILogger is injected into the service:

Размещенная служба создает область для разрешения службы фоновой задачи с заданной областью, чтобы вызвать ее метод DoWork : The hosted service creates a scope to resolve the scoped background task service to call its DoWork method:

Службы регистрируются в Startup.ConfigureServices . The services are registered in Startup.ConfigureServices . Реализация IHostedService зарегистрирована с методом расширения AddHostedService : The IHostedService implementation is registered with the AddHostedService extension method:

Фоновые задачи в очереди Queued background tasks

В QueueHostedService фоновые задачи в очереди из очереди выводятся из очереди и выполняются в качестве BackgroundService — базового класса для реализации длительного выполнения IHostedService : In QueueHostedService , background tasks in the queue are dequeued and executed as a BackgroundService, which is a base class for implementing a long running IHostedService :

Службы регистрируются в Startup.ConfigureServices . The services are registered in Startup.ConfigureServices . Реализация IHostedService зарегистрирована с методом расширения AddHostedService : The IHostedService implementation is registered with the AddHostedService extension method:

В классе модели страницы индексов: In the Index page model class:

  • IBackgroundTaskQueue вставляется в конструктор и присваивается Queue . The IBackgroundTaskQueue is injected into the constructor and assigned to Queue .
  • IServiceScopeFactory вставляется и присваивается _serviceScopeFactory . An IServiceScopeFactory is injected and assigned to _serviceScopeFactory . Фабрика используется для создания экземпляров IServiceScope, который используется для создания служб с заданной областью. The factory is used to create instances of IServiceScope, which is used to create services within a scope. Для использования AppDbContext приложения создается область (служба с заданной областью) для записи данных из базы данных в IBackgroundTaskQueue (отдельная служба). A scope is created in order to use the app’s AppDbContext (a scoped service) to write database records in the IBackgroundTaskQueue (a singleton service).

Если нажать кнопку Добавить задачу на странице индексов, выполняется метод OnPostAddTask . When the Add Task button is selected on the Index page, the OnPostAddTask method is executed. QueueBackgroundWorkItem вызывается для постановки рабочего элемента в очередь: QueueBackgroundWorkItem is called to enqueue a work item:

Управление жизненным циклом приложения

Жизненный цикл приложения и запроса

Как правло, для решения большинства задач в ASP.NET MVC не требуется управление жизненным циклом приложения. Однако понимание работы приложения и обработки запроса дает нам дополнительные возможности по настройке веб-приложения.

Жизненный цикл приложения ASP.NET MVC начинается с запуска веб-приложения для обработки HTTP-запросов. И когда приложение завершает свою работу, завершается и его жизненный цикл. Ключевую роль в запуске приложения играет файл Global.asax. Он определяет глобальный класс приложения. Например, стандартное содержимое файла Global.asax может выглядеть следующим образом:

По умолчанию глобальный класс приложения называется MvcApplication. Он наследуется от класса System.Web.HttpApplication . И при поступлении запроса к приложению фреймворк ASP.NET создает объект класса MvcApplication.

Класс приложения поддерживает два метода, которые позволяют управлять жизненным циклом приложения: Application_Start и Application_End . Метод Application_Start вызывается при старте приложения, а метод Application_End — перед завершением его работы.

По умолчанию в классе приложения определяется только метод Application_Start, в котором производится конфигурационная настройка: регистрация маршрутов, фильтров и т.д.

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

При получении запроса приложением опять же создается объект приложения в виде объекта класса HttpApplication, определенного в Global.asax. Для обработки каждого запроса создается свой объект приложения. И затем начинается жизненный цикл запроса. То есть фактически создание объекта приложения происходит два раза — в рамках жизненного цикла приложения и в рамках жизненного цикла запроса. У объекта приложения, который создается для обработки конкретного запроса, методы Application_Start и Application_End не вызываются. Подобная конфигурация облегчает обработку запросов и позволяет сохранять в нестатических глобальных переменных запроса те данные, которые являются специфичными для каждого запроса.

Жизненный цикл запроса предполагает вызов ряда событий в следующей последовательности:

BeginRequest : событие возникает, когда приложение получает новый запрос

AuthenticateRequest/PostAuthenticateRequest : событие AuthenticateRequest возникает при идентификации (аутентификации) пользователя, сделавшего запрос. А после его обработки срабатывает событие PostAuthenticateRequest

AuthorizeRequest/PostAuthorizeRequest : AuthorizeRequest возникает при авторизации запроса, после этого срабатывает событие PostAuthorizeRequest


ResolveRequestCache/PostResolveRequestCache : событие ResolveRequestCache возникает, когда приложение обращается к кэшу для получения данных. При получении данных их кэша затем срабатывает событие PostResolveRequestCache

MapRequestHandler/PostMapRequestHandler : MapRequestHandler срабатывает при определении обработчика запроса. После выбора обработчика срабатывает событие PostMapRequestHandler

AquireRequestState/PostAquireRequestState : событие AquireRequestState возникает при получении данных состояния, связанных с запросом (например, данные сессии). И после него срабатывает событие PostAquireRequestState

PreRequestHandlerExecute/PostRequestHandlerExecute : событие PreRequestHandlerExecute происходит непосредственно перед началом работы обработчика запроса, а событие PostRequestHandlerExecute — после его работы

ReleaseRequestState/PostReleaseRequestState : событие ReleaseRequestState возникает, когда приложению больше не требуются данные, ассоциированные с запросом. И после освобождения этих данных просиходит событие PostReleaseRequestState

UpdateRequestCache : возникает при обновлении данных в кэше

LogRequest/PostLogRequest : событие LogRequest происходит непосредственно перед каждым логгированием, а PostLogRequest — после завершения всех обработчиков событий

EndRequest : возникает при завершении обработки запроса, когда данные для ответа уже готовы к отправке клиенту

PreSendRequestHeaders : возникает перед отправкой HTTP-заголовков браузеру клиента

PreSendRequestContent : возникает после отправки заголовков, но перед отправкой основного содержимого ответа

И если на определенной стадии возникнет ошибка, то сработает событие Error .

Схематично жизненный цикл приложения и запроса можно представить следующим образом:

При необходимости мы можем обработать эти события. Например, в файле Global.asax.

Для этого нам надо определить в классе MvcApplication методы, имеют следующее наименование: Application_[Название_события]. Например, изменим класс в Global.asax следующим образом:

Обработка каждого события сведена в к добавлению информации в методе AddEvent. Для хранения информации о событиях создается список, хранящийся в свойстве Application[«events»] . Объект Application является экземпляром класса HttpApplicationState , который представляет состояние приложение. И таким образом, мы можем определить в нем свойство events.

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

Кроме специальных методов мы также можем обработать события стандартным для C# способом — через подключения обработчиков событий. Для этого изменим класс MvcApplication в Global.asax следующим образом:

С помощью лямбда-выражений устанавливаются обработчики событий (src, args) => AddEvent(«BeginRequest») . В качестве параметров передаются объект, вызвавший событие — src , и параметр EventArgs — args . Результат выполнения метода в контроллере HomeController будет тем же.

Создание простого приложения по вводу данных

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

Набросаем план

Давайте представим себе, что подруга решила провести вечеринку в канун Нового года, и что она попросила нас создать веб сайт, который позволит ее друзьям и знакомым принять приглашение с RSVP (подпись на приглашении, призывающая получателя дать ответ об участии в мероприятии). На сайте должно присутствовать следующее:

  • Главная страница, где отображается информация о вечеринке
  • Форма, которая может быть использована для RSVP
  • Валидация RSVP формы, которая отобразит страницу с благодарностью
  • Заполненный и отправленный ответ о согласии принять участие в вечеринке

В следующих разделах мы будем наращивать MVC проект, который мы создали в начале главы, и добавим эти возможности. Мы можем сделать первый пункт из списка, применив те знания то, которые мы получили ранее, то есть мы можем добавить HTML для наших существующих представлений, где будет дана подробная информация о вечеринке. В листинге 2-7 показаны дополнения, которые мы сделали в файле Views/Home/Index.cshtml .

Листинг 2-7: Отображение информации о вечеринке

Мы на правильном пути. Если вы запустите приложение, вы увидите информацию о вечеринке, ну, вернее, метку-заполнитель (placeholder) для этой информации, но вы можете уловить суть. Пример показан на рисунке 2-12.

Рисунок 2-12: Добавление представления

Проектирование модели данных

В MVC М обозначает модель, и это является самой важной частью приложения. Модель является представлением реальных объектов, процессов и правил, которые определяют объект, известный как домен, нашего приложения. Модель, которая часто упоминается как доменная модель, содержит C# объекты (известные как доменные объекты), которые составляют суть нашего приложения, и методы, которые позволяют нам манипулировать ими. Представления и контроллеры раскрывают домен клиентам в согласованном порядке, и хорошо продуманное MVC приложение начинается с хорошо продуманной модели, которая затем является координационным центром, когда мы добавляем контроллеры и представления.

Нам не нужна сложная модель для приложения PartyInvites , но мы создадим один доменный класс, которые мы назовем GuestResponse . Этот объект будет отвечать за хранение, проверку и подтверждение RSVP.

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

По MVC соглашению классы, которые составляют модель, помещаются в папку Models . Щелкните правой кнопкой мыши по Models в окне Solution Explorer и выберите Add , за которым следует Class , из всплывающего меню. Назовите файл GuestResponse.cs и нажмите кнопку Add , чтобы создать класс. Измените содержимое класса в соответствии с листингом 2-8.

Если у вас нет пункта меню Class , то вы, вероятно, оставили работать отладчик (дебаггер) Visual Studio. Visual Studio ограничивает изменения, которые можно внести в проект, если приложение запущено.

Листинг 2-8: Доменный класс GuestResponse

Вы, возможно, заметили, что свойство WillAttend имеет тип bool? ( Nullable ), то есть оно может быть true , false или null . Мы объясним это в разделе «Добавление валидации» далее в этой главе.

Ссылка на метод действия

Одна из целей нашего приложение заключается во включении RSVP формы, поэтому нам нужно добавить ссылку на нее из нашего представления Index.cshtml , как показано в листинге 2-9.

Листинг 2-9: Добавление ссылки для RSVP формы

Html.ActionLink является вспомогательным методом HTML. MVC Framework разработан с набором встроенных вспомогательных методов, которые удобны для обработки HTML ссылок, текстовых вводных данных, флажков, выборок и даже пользовательских элементов управления. Метод ActionLink принимает два параметра: первый – это текст для отображения в ссылке, а второй – это выполняемое действие, когда пользователь нажимает на ссылку. Мы объясним вспомогательные методы HTML в главах 19-21. На рисунке 2-13 показана ссылка, которую мы добавили.

Рисунок 2-13: Добавление в представление ссылки

Если вы наведете курсор мыши на ссылку в браузере, вы увидите, что ссылка указывает на http://yourserver/Home/RsvpForm . Метод Html.ActionLink проверил конфигурацию URL нашего приложения и определил, что /Home/RsvpForm является URL для действия RsvpForm контроллера HomeController . Обратите внимание, что в отличие от традиционных приложений ASP.NET, URL-адреса MVC не соответствуют физическим файлам. Каждый метод действия имеет свой URL, и MVC использует систему маршрутизации ASP.NET перевести эти URL в действия.

Создание метода действия

Если вы нажмете на ссылку, то увидите ошибку 404 Not Found . Это потому что пока еще мы не создали метод действия, который соответствует URL /Home/RsvpForm . Мы сделаем это путем добавления метода RsvpForm нашему классу HomeController , как показано в листинге 2-10.

Листинг 2-10: Добавление в контроллер нового метода действия

Добавление строго типизированного представления

Мы хотим добавить представление для нашего метода действия RsvpForm , но мы собираемся сделать кое-что больше: то есть создать строго типизированное представление. Строго типизированные представления предназначены для обработки определенного типа доменов. Если мы укажем тип, с которым мы хотим работать (в этом примере GuestResponse ), MVC предоставит дополнительные возможности, чтобы упростить нам задачу.

Убедитесь, что перед работой ваш MVC проект скомпилирован. Если вы создали класс GuestResponse , но не скомпилировали его, MVC не сможет создать строго типизированное представление для данного типа. Чтобы скомпилировать приложение, выберите Build Solution в Visual Studio меню Build .


Щелкните правой кнопкой мыши внутри метода действия RsvpForm и выберите для создания представления Add View из всплывающего меню. В диалоговом окне Add View поставьте галочку на Create a strongly-typed view и выберите опцию GuestResponse из выпадающего меню. Снимите флажок с Use a layout or master page и убедитесь, что Razor выбран в качестве движка представления, и что опция Scaffold template установлена на Empty , как показано на рисунке 2-14.

Рисунок 2-14: Добавление строго типизированного представления

Нажмите кнопку Add , и Visual Studio создаст новый файл с именем RvspForm.cshtml и откроет его для редактирования. Вы можете увидеть первоначальное содержание в листинге 2-12. Как вы заметили, это другой HTML файл, но он содержит Razor выражение @model . Вы сейчас увидите, что это является ключом к строго типизированному представлению и возможностям, которые оно предлагает.

Листинг 2-12: Начальное содержимое файла RsvpForm.cshtml

Построение формы

Теперь, когда мы создали строго типизированное представление, мы можем выстроить содержание RsvpForm.cshtml , чтобы превратить его в HTML форму для редактирования GuestResponse объектов. Измените представление так, чтобы оно соответствовало листингу 2-13.

Листинг 2-13: Создание представления формы

Для каждого свойства класса модели GuestResponse мы используем вспомогательный метод HTML, чтобы обработать подходящий HTML элемент управления input . Эти методы позволяют выбрать свойство, к которому относится элемент input , с помощью лямбда-выражения, например вот так:

Илон Маск рекомендует:  Что такое код pspell_clear_session

Вспомогательный метод HTML TextBoxFor генерирует HTML для элемента input , устанавливает параметр type на text и устанавливает атрибуты id и name на Phone , имя выбранного свойства доменного класса, вот так:

Эта удобная функция работает, потому что наше представление RsvpForm строго типизировано, и мы сказали MVC, что GuestResponse это тот тип, который мы хотим обработать при помощи данного представления, поэтому вспомогательные методы HTML могут понять, какой тип данных мы хотим прочитать, с помощью выражения @model .

Не волнуйтесь, если вы не знакомы с лямбда-выражениями C#. Мы расскажем о них в главе 4, но в качестве альтернативы лямбда-выражениям вы можете обратиться к имени свойства типа модели как к строке, например, вот так:

Мы считаем, что методика лямбда-выражений помогает нам не делать опечаток в имени свойства типа модели, потому что всплывает Visual Studio IntelliSense и позволяет нам выбрать свойство автоматически, как показано на рисунке 2-15.

Рисунок 2-15: Visual Studio IntelliSense для лямбда-выражений во вспомогательных методах HTML

Другим удобным вспомогательным методом является Html.BeginForm , который генерирует элемент HTML формы, настроенный на обратную передачу данных методу действия. Поскольку мы не передали вспомогательному методу никаких параметров, он предполагает, что мы хотим передать обратно тот же URL. Ловким трюком является то, чтобы обернуть это в C# выражение using , вот таким образом:

Обычно, когда оно применяется таким образом, выражение using гарантирует, что объект удаляется, когда выходит из области видимости. Оно широко используется для подключения к базе данных, например, чтобы убедиться, что она закрывается, как только запрос был выполнен. (Это применение ключевого слова using отличается от того, что касается области видимости класса).

Вместо удаления объекта, помощник HtmlBeginForm закрывает HTML элемент form , когда он выходит из области видимости. Это означает, что вспомогательный метод Html.BeginForm создает обе части элемента form , например:

Не волнуйтесь, если вы не знакомы с удалением объектов в C#. Наша цель на данный момент состоит в том, чтобы показать, как создать форму с помощью вспомогательного метода HTML. Вы можете видеть форму в представлении RsvpForm , когда вы запустите приложение и нажмете ссылку RSVP Now . На рисунке 2-16 показан результат.

Рисунок 2-16: Представление RspvForm

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

Обработка форм

Мы не сказали MVC, что мы хотим сделать, когда форма отправляется на сервер. На данный момент нажатие на кнопку Submit RSVP просто удаляет любые значения, которые вы ввели в форму. Это потому что форма отправляется обратно методу действия RsvpForm в контроллере Home , который просто говорит MVC обработать представление еще раз.

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

Чтобы получить и обработать отправленные данные формы, мы собираемся сделать умную и классную вещь. Мы добавим второй метод действия RsvpForm для того, чтобы создать следующее:

  • Метод, который отвечает на HTTP GET запросы: GET запрос является тем, с чем браузер имеет дело после каждого клика по ссылке. Этот вариант действий будет отвечать за отображение начальной пустой формы, когда кто-то первый раз посетит /Home/RsvpForm .
  • Метод, который отвечает на HTTP POST запросы: По умолчанию, формы, обрабатываемые при помощи Html.BeginForm() , отправляются браузером как POST запросы. Этот вариант действий будет отвечать за получение отправленных данные и решать, что с ними делать.

Обработка GET и POST запросов в отдельных методах C# помогает сохранить наш код опрятным, так как оба метода имеют различные обязанности. Оба метода действия вызываются одним и тем же URL, но MVC гарантирует, что будет вызван соответствующий метод в зависимости от того, имеем ли мы дело с GET или с POST запросом. В листинге 2-14 показаны изменения, которые мы должны сделать в классе HomeController .

Листинг 2-14: Добавление метода действия для поддержки POST запросов

Мы добавили атрибут HttpGet для нашего существующего метода действия RsvpForm . Это говорит MVC, что данный метод должен использоваться только для GET запросов. Затем мы добавили перегруженную версию RsvpForm , который принимает параметр GuestResponse и применяет атрибут HttpPost . Атрибут говорит MVC, что новый метод будет иметь дело с POST запросами. Обратите внимание, что мы также импортировали пространство имен PartyInvites.Models – таким образом мы можем обратиться к типу модели GuestResponse без необходимости указывать имя класса. Мы расскажем, как работают наши дополнения в листинге, в следующих разделах.

Использование связывания данных модели

Первый вариант перегруженного метода действия RsvpForm обрабатывает то же представление, что и раньше. Она генерирует форму, показанную на рисунке 2-16. Второй вариант перегруженного метода является более интересным из-за параметра, но, учитывая, что метод действия будет вызываться в ответ на HTTP POST запрос, и что GuestResponse является типом класса C #, то как они объединены?

Ответом является связывание данных модели – чрезвычайно полезная функциональная особенность MVC, когда входные данные разбиваются (парсятся) и пары ключ/значение в HTTP запросе используются для заполнения свойств типа доменной модели. Этот процесс является противоположностью использования вспомогательных методов HTML; это когда при создании данных формы для отправки клиенту, мы генерировали HTML элементы input , где значения атрибутов id и name были получены из названий свойств классов моделей.

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

Модель представления данных является мощной и настраиваемой функцией, которая избавляет от рутины работы напрямую с HTTP-запросами и позволяет нам работать с C# объектами, а не иметь дело со значениями Request.Form[] и Request.QueryString[] . Объект GuestResponse , который передается в качестве параметра нашему методу действия, автоматически заполняется данными из полей формы. Мы рассмотрим подробно модель представления данных, а также в том числе, как ее можно настроить, в главе 22.

Обработка других представлений

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

Этот вызов метода View говорит MVC найти и обработать представление, которое называется Thanks , и передать представлению наш объект GuestResponse . Чтобы создать представление, которое мы указали, щелкните правой кнопкой мыши внутри одного из методов HomeController и выберите пункт Add View из всплывающего меню. Установите имя представления на Thanks , как показано на рисунке 2-17.

Рисунок 2-17: Добавление представления Thanks

Мы собираемся создать еще одно строго типизированное представление, поэтому поставьте галочку на этом пункте в диалоговом окне Add View . Класс данных, который мы выберем для этого представления, должен соответствовать классу, который мы передали представлению при помощи метода View . Поэтому убедитесь, что в выпадающем меню выбран GuestResponse . Убедитесь, что нет галочки на Use a layout or master page , View engine установлен на Razor, а также Scaffold template установлен на Empty .

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

/Views/Home/Thanks.cshtml . Измените новое представление так, чтобы оно соответствовало листингу 2-15: мы выделили то, что нужно добавить.

Листинг 2-15: Представление Thanks

Представление Thanks использует Razor для отображения контента на основе значения свойства GuestResponse , которые мы передали методу View в методе действия RsvpForm . Razor оператор @model определяет тип доменной модели, с которым связано представление. Чтобы получить доступ к значению свойства доменного объекта, мы используем Model.PropertyName . Например, чтобы получить значение свойства Name , мы вызываем Model.Name . Не волнуйтесь, если вам не понятен синтаксис Razor, мы объясним это подробно в главе 5.

Теперь, когда мы создали представление Thanks , у нас есть базовый рабочий пример обработки формы при помощи MVC.

Запустите приложение в Visual Studio, нажмите на ссылку RSVP Now , добавьте в форму данные и нажмите на кнопку Submit RSVP . Вы увидите результат, показанный на рисунке 2-18 (хотя он может отличаться, если ваше имя не Джо, и вы сказали, что не сможете присутствовать).

Рисунок 2-18: Обработанное представление Thanks

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

Сейчас мы подошли к тому, чтобы добавить валидацию в наше приложение. Если бы мы этого не сделаем, наши пользователи смогут ввести бессмысленные данные или даже отправить пустую форму.

В приложении MVC проверка, как правило, применяется к доменной модели, а не к пользовательскому интерфейсу. Это обозначает, что мы определяем наши критерии валидации в одном месте, и они вступают в силу в любом месте используемого класса модели. ASP.NET MVC поддерживает правила проверки, определяемые атрибутами пространства имен System.ComponentModel.DataAnnotations . В листинге 2-16 показано, как эти атрибуты могут быть применены к классу модели GuestResponse .


Листинг 2-16: Применение валидации к классу модели GuestResponse

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

Как отмечалось ранее, мы использовали тип bool? для свойства WillAttend , поэтому мы смогли применить атрибут валидации Required . Если бы мы использовали обычный bool , значение, которое мы могли бы получить благодаря модели представления данных, могло бы быть только true или false , и мы не были бы сказать, выбрал ли пользователь значение. Тип bool? имеет три возможных значения: true , false и null . Значение null будет использовано, если пользователь не выбрал значение, и это заставляет атрибут Required сообщить об ошибке валидации.

Мы можем проверить, была ли ошибка валидации проверкой с помощью свойства ModelState.IsValid в нашем классе контроллера. В листинге 2-17 показано, как это можно сделать в нашем методе действия RsvpForm с поддержкой POST .

Листинг 2-17: Проверка на наличие ошибок при валидации формы

Если ошибки валидации нет, мы говорим MVC обрабатывать представление Thanks , как мы делали ранее. Если ошибка валидации есть, мы вновь обрабатываем представление RsvpForm , вызвав метод View без параметров.

Просто отображать форму, когда есть ошибка, не очень полезно, мы должны дать пользователю некоторую информацию о том, в чем заключается проблема, и почему мы не можем принять его форму. Мы делаем это с помощью вспомогательного метода Html.ValidationSummary в представлении RsvpForm , как показано в листинге 2-18.

Листинг 2-18: Использование вспомогательного метода Html.ValidationSummary

Если ошибок нет, метод Html.ValidationSummary создает скрытый элемент списка в качестве заполнителя в форме. MVC делает метку-заполнитель видимой и добавляет сообщения об ошибке, определяемые атрибутами валидации. Вы можете увидеть, как это выглядит, на рисунке 2-19.

Рисунок 2-19: Сводка результатов валидации

Пользователю не будет показано представление Thanks , пока не будут удовлетворены все правила валидации, которые мы применили к классу GuestResponse . Обратите внимание, что данные, введенные в форму, были сохранены и отображаются снова, когда представление показано со сводкой валидации. Это еще одно преимущество связывания данных.

Если вы работали с ASP.NET Web Forms, вы знаете, что в Web Forms существует понятие «серверные элементы управления», которые сохраняют состояние, сериализуя значения в скрытом поле формы __VIEWSTATE . Связывание данных ASP.NET MVC не привязано к Web Forms концепции серверных элементов управления, обратной передачи данных или View State. ASP.NET MVC не вводит скрытое поле __VIEWSTATE в обрабатываемые HTML страницы.

Выделение невалидных полей

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

Если свойство класса модели не прошло валидацию, вспомогательные методы HTML будут генерировать немного другой HTML. В качестве примера, вот HTML, который генерирует вызов Html.TextBoxFor (х => x.Name) , когда нет ошибки валидации:

А вот HTML, который генерирует тот же вызов, когда пользователь не предоставил значение (что является ошибкой валидации, потому что мы применили атрибут Required свойства Name в классе модели GuestResponse ):

Мы выделили различия. Это вспомогательный метод добавил класс с именем input-validation-error . Мы можем воспользоваться этой функцией, создав таблицу стилей CSS, которая содержит стили для этого класса и других, что применяют различные вспомогательные методы HTML.

Соглашение в MVC проектах заключается в том, что статический контент, такой как таблицы стилей CSS, помещается в папку под названием Content . Мы создали папку Content , нажав правой кнопкой мыши по проекту PartyInvites в Solution Explorer и выбрав из всплывающего меню Add New Folder . Мы создали таблицу стилей, щелкнув правой кнопкой мыши по папке Content , выбрав Add New Item и затем выбрав Style Sheet в диалоговом окне Add New Item . Мы назвали нашу таблицу стилей Site.css , и это имя, которое Visual Studio использует при создании проекта с использованием иного шаблона MVC, а не Empty. Вы можете посмотреть содержимое файла Content/Site.css в листинге 2-19.

Листинг 2-19: Содержимое файла Content/Site.css

Чтобы использовать эту таблицу стилей, мы добавили новую ссылку в раздел head представления RsvpForm , как показано в листинге 2-20. Вы добавляете представлениям элементы link так же, как в обычном статическом HTML файле.

Листинг 2-20: Добавление элемента link в представление RsvpForm

Если вы использовали MVC 3, то могли ожидать, чтобы мы добавим CSS файл к представлению, указав атрибут href как @Href(«

/Content/Site.css») или @Url.Content(«

/Content/Site.css») . С MVC 4 Razor автоматически обнаруживает атрибуты, которые начинаются с

/ , и автоматически вставляет для вас @Href или @Url .

Теперь будет отображаться визуально более очевидная ошибка валидации, если были представлены данные, которые вызвали эту ошибку, как показано на рисунке 2-20.

Рисунок 2-20: Автоматически выделенные ошибки валидации

Завершаем пример

Последнее требование к нашему примеру приложения заключается в том, чтобы отправить имейл с завершенными RSVP нашему другу, организатору вечеринки. Мы могли бы сделать это, добавив метод действия, чтобы создать и отправить по электронной почте сообщение, используя e-mail классы .NET Framework. Вместо этого мы собираемся использовать вспомогательный метод WebMail . Это не входит в рамки MVC, но это позволит нам завершить данный пример, не увязнув в деталях создания других средств отправки электронной почты.

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

Мы хотим, чтобы имейл сообщение было отправлено, когда мы обрабатываем представление Thanks . В листинге 2-21 показаны изменения, которые мы должны сделать.

Листинг 2-21: Использование вспомогательного метода WebMail

Мы добавили Razor выражение, которое использует вспомогательный метод WebMail для настройки информации о нашем сервере электронной почты, включая имя сервера, требует ли сервер SSL соединения и данных учетной записи. После того как мы все настроили, мы используем метод WebMail.Send для отправки электронной почты.

Мы включили весь имейл код в блок try. catch , чтобы мы могли предупредить пользователя, если электронная почта не отправилась. Мы делаем это путем добавления текстового блока к выходным данным представления Thanks . Лучше было бы отобразить отдельное представление ошибки, если сообщение электронной почты не может быть отправлено, но мы хотели не усложнять наше первое MVC приложение.

На границах, приложения не являются объектно-ориентированными

Я получил множество отзывов на мою недавнюю серию постов по Poka-yoke проектированию (я был бы расстроены, если было бы иначе). Множество из этих отзывов касаются различных технологий сериализации или трансляции, используемых обычно на границах приложения: сериализация, XML (де)гидратация (прим. переводчика: тоже самое, что и сериализация), UI-валидация и т.д. Заметьте, что такая трансляция происходит не только по периметру приложения, но также и на уровне сохраняемости (persistence). ORM-ы также являются трасляционными механизмами.
Общим для многих комментариев является утверждение о том, что большая часть технологий сериализации требует наличия конструктора по умолчанию. Например, класс XmlSerializer требует наличия конструктора по умолчанию и публичных, доступных для записи свойств. Большая часть объектно-реляционных преобразователей, которые я изучал, похоже, имеют те же требования. Контролы Windows Forms и WPF (UI – также граница приложения) почти обязаны иметь конструктор по умолчанию. Не нарушает ли это инкапсуляцию? И да и нет.

Объекты на границе
Инкапсуляция, определённо, была бы нарушена, если бы вы экспонировали ваши объекты (доменные) прямо на границе приложения. Рассмотрим простой XML-документ:

В независимости от наличия формального контракта (XSD), мы могли бы договориться о том, что элементы firstName и lastName являются обязательными. Несмотря на такой контракт, я спокойной могу создать документ, который его нарушит:

Мы не можем продвинуть (прим. переводчика: принудить выполнить) этот контракт по той причине, что мы не можем вовлечь в это этап компиляции. Мы можем валидировать ввод (и вывод), но это совсем другой вопрос. Именно по той причине, что мы не можем принудить выполнить контракт, очень просто создать некорректно сформированный ввод. Тот же самый аргумент можно отнести и к формам ввода в UI и любым видам сериализованных байтовых последовательностей. Поэтому мы обязаны рассматривать любой ввод, как ожидаемый.
Это вовсе не новое наблюдение. В книге «Шаблоны корпоративных приложений», Мартин Фаулер описал такие объекты как объекты передачи данных (DTO – Data Transfer Object). Однако, несмотря на название, мы должны понимать, что DTO-объекты – это не совсем объекты. И в этом тоже нет ничего нового. В 2004 году, Дон Бокс сформулировал четыре положения сервисной ориентации. (Да, я знаю, что они уже не в моде и, что люди хотят отправить их на покой, но некоторые из них по-прежнему имеют огромный смысл). В особенности, третье положение является соответствующим данному посту:

Сервисы разделяют схему и контракт, не класс.

Да, и это означает, что они не являются объектами. DTO – это представление куска данных, отображённого на объектно-ориентированной язык. Это всё равно не делает их объектами в смысле инкапсуляции. Такое было бы невозможно представить. Поскольку любой ввод ожидаем, мы не можем продвинуть (поддержать) какие-либо инварианты.
Обычно, как указал на это в комментариях к одному из моих предыдущих постов Крэйг Стантз, даже если входные данные некорректны, мы хотим захватить то, что получили на вводе с целью отображения правильного сообщения об ошибке (этот аргумент также применим к границам между машинами). Это означает, что любой DTO будет иметь очень слабые инварианты (если будет иметь какие-либо вообще).

DTO-объекты не нарушают инкапсуляцию, поскольку они вообще не являются объектами.

Не давайте себя обмануть своим инструментам. .NET-фреймворк очень, очень хочет, чтобы вы считали свои DTO-объекты настоящими объектами.
Это следует из кодогенерации.
Строгая типизация, обеспечиваемая такими авто-генерируемыми классами, даёт ложное чувство безопасности. Вы можете думать, что получаете быструю обратную связь от компилятора, но есть множество возможных ситуаций, в которых вы получите ошибку времени выполнения (самые примечательные – те, которые вы получаете, забыв обновить автоматически сгенерированный код, после обновления схемы).
Ещё худшим результатом представления входных и выходных данных как объектов является то, что множество разработчиков, обманываясь, работают с ними как с реальными моделями объектов. Неизменный результат – анемичная доменная модель.
Всё больше и больше, эта цепочка аргументов приводит меня к заключению, что ментальная модель DTO, которую мы используем последние 10 лет – это тупик.

Что должно происходить на границе приложения
Предположим, что мы пишем объектно-ориентированный код, а те данные на границах – что угодно, кроме объектно-ориентированных объектов. Как нам с ними работать?
Один из вариантов – остаться с тем, что имеем. В этом случае, для заполнения дыры мы должны разработать слой трансляции, который смог бы транслировать DTO-объекты в правильно инкапсулированные доменные объекты. Это тут путь, которому я следую в примерах в моей книге. Однако, это решение, я всё больше подозреваю, не является лучшим. Оно порождает проблемы с поддержкой. (Кстати, такая проблема возникает, когда пишешь книгу: к тому времени как ты завершил, ты знаешь намного больше того, что знал, когда начинал её… Я не то, чтобы осуждаю книгу – это просто не идеально…)
Другая возможность – перестать относиться к данным, как к объектам и начать рассматривать их как структурированные данные, чем они на самом деле и являются. Было бы очень здорово, если бы наш язык программирования имел отдельную концепцию структурированных данных… Интересно, что в то время как C# не умеет ничего такого, F# имеет кучу возможностей для моделирования структур данных, не имеющих поведения. Возможно, это более честный подход к работе с данными… Надо будет поэкспериментировать с этим…
Третий вариант – посмотреть в сторону динамических типов. Дино Эспозито, в своей статье «На острие: Expando-объекты в C# 4.0», обрисовывает динамический подход к потреблению структурированных данных, который сокращает автоматически сгенерированный код и предоставляет легковесный API к структурированным данным. Это также выглядит многообещающим подходом… Это не обеспечивает обратной связи на этапе компиляции, но это в конце концов – лишь ложное чувство безопасности. Мы обязаны прибегнуть к юнит тестам для получения быстрой обратной связи, мы же уже все практикуем TDD, так ведь?
В заключение, вся моя серия об инкапсуляции относится к объектно-ориентированному программированию. Несмотря на наличие множества технологий для представления данных как «объектов», они являются ложными объектами. Даже если мы используем объектно-ориентированный на границе, этот код не имеет ничего общего с объектной ориентацией. Таким образом, правила Poka-yoke проектирования здесь не применимы.
Теперь вернитесь в начало и перечитайте пост, заменяя «DTO» на «Entity» (прим. переводчика: сущность) (или чем-то, чем ваша ORM называет представление строки реляционной таблицы) и вы должны увидеть очертания того, почему объектно-реляционные преобразователи так сомнительны.

Илон Маск рекомендует:  Что такое код jquery

Asp задание границ приложения

Этот текст предназначен для тех, кто никогда не имел дела с ASP и вообще смутно себе представляет возможности программирования на стороне сервера. Я ставил себе задачу создать у читателя общее представление о предмете. Отдельные неточности при этом менее важны — пожалуйста, громко не ругайтесь.

Общие сведения

ASP (Active Server Pages) – это мощная технология от Microsoft, позволяющая легко разрабатывать приложения для WWW. ASP работает на платформе Windows NT и IIS (Internet Information Server), начиная с версии 3, хотя вроде есть реализации на других платформах. ASP – это не язык программирования, это внутренняя технология, позволяющая подключать программы к Web-страницам. Основа успеха ASP – простой скриптовый язык (Visual Basic Script или Java Script) и возможность использования внешних COM-компонент.


Как это все происходит?

Вы пишете программу и складываете в файл на сервере. Браузер клиента запрашивает файл. Файл сначала интерпретируется сервером, на выходе производится HTML-код. Этот HTML посылается клиенту. Файлы с программами имеют расширение .asp. Файлы asp – это обычные текстовые файлы, содержащие исходные тексты программ. Файлы делаются с помощью любого текстового редактора. Каталог, в котором размещены файлы asp должен иметь права на выполнение, так как сервер исполняет эти файлы, когда браузер их запрашивает. Собственно программы пишутся на любом скриптовом языке, который установлен в системе. По умолчанию поддерживаются VBScript и JavaScript. Можно доустановить другие (например, Perl). Если ничего специально не указывать используется VBScript. В дальнейшем будем ссылаться только на него. Программные фрагменты заключаются в скобки . Можно ставить открывающую скобку в начале файла, закрывающую – в конце, все что между ними – программа на Visual Basic’е.

Какие средства есть для программирования?

Web – нормальная среда программирования, если правильно понять, что есть что. В VBScript есть все нормальные конструкции структурного программирования (if, while, case, etc). Есть переменные (описывать не обязательно, тип явно не задается). Поддерживаются объекты. Работа с ними обычная – Object.Property, Object.Method. Есть ряд встроенных объектов (Request, Response, Session, Server, Connection, Recordset). Можно доустанавливать другие компоненты (скачивать, покупать, программировать), например для работы с электронной почтой.

Вывод

Понятия «экран», куда можно выводить данные нет. Все, что надо показать пользователю, выбрасывается в выходной поток на языке HTML. Браузер пользователя интерпретирует этот HTML. Для упрощения вывода существует объект Response . Вывод осуществляется с помощью метода Write .

Так производится запись во внутренний буфер объекта Response. Когда скрипт заканчивает работу, весь буфер выдается клиенту. Надо заметить, что клиент получает «чистый» HTML, таким образом программы на ASP не зависят от клиентского ПО, что очень важно. Если внутри выводимой строки нужно использовать кавычку, кавычка удваивается. Другие методы и свойства Response позволяют управлять выводом. Так Response.Buffer регулирует, получает ли клиент данные по мере из записи в Response, или все сразу по завершении исполнения страницы. Метод Response.Redirect перенаправляет браузер на другую страницу. Чтобы им пользоваться, нельзя до него на странице использовать Response.Write.

Программа на ASP не может явно спросить пользователя о чем-то. Она получает данные из других страниц, либо через URL. Передаваемые параметры помещаются во входной поток и доступны через объект Request . Чтобы передать переменную var в программу test.asp , надо написать:

Чтобы из программы получить значение этой переменной, надо написать:

Несколько переменных разделяется знаком &:

Кроме того, чтобы задавать параметры в URL, можно воспользоваться формами HTML. В вызывающей странице пишем так:

Так это выглядит:

При этом пользователь увидит форму из одного поля ввода (var1), в нем будет значение по умолчанию «default». Второе поле (var2) будет невидимо и будет передавать всегда фиксированное значение «var2value». Кнопка «Submit Form» завершает заполнение формы и передает все переменные на test.asp (action). Если method=»get», переменные передаются через URL (test.asp?var1=default&var2=var2value). Если method=»post», передаются вместе с запросом так, что внешне передача переменных не заметна. В вызываемой программе безразлично, какой метод изпользовался (почти). Если у вас нет специальных аргументов за метод GET, используйте метод POST.

Формы

Формы HTML используются для организации диалога с пользователем. Поддерживаются стандартные элементы управления. Все многообразие задается немногими тэгами:

  • INPUT (с параметром TYPE=)
  • SELECT
  • TEXTAREA

Описание – в документации по HTML.

Взаимосвязь между отдельными страницами

Обычно сервер WWW не хранит состояние приложения, т.е. все запросы взаимонезависимы, и нет стандартного способа понять, что несколько запросов пришли от одного и того же пользователя. Но это очень нужно для разработки полноценных приложений и является одной из главных проблем разработки Web-приложений.

Один из методов решения этой проблемы — cookies . Пользователю при первом обращении выдается специальный идентификатор, после этого браузер пользователя предъявляет этот идентификатор при каждом обращении, и сервер может распознать, что это тот же самый пользователь. Пользователь может отключить cookies, в этом случае этот метод не работает.

ASP, используя cookies, предоставляет программисту более простое средство — объект Session (сессия). Сессия стартует, когда новый пользователь обращается к любому asp-файлу приложения. Сессия заканчивается при отсутствии активности пользователя в течение 20 минут, либо по явной команде. Специальный объект Session хранит состояние сессии. Туда можно записывать переменные, которые доступны из любой страницы в этой сессии. Записать данные в этот объект можно просто:

Считать потом еще проще:

Сессия, таким образом, – это еще один метод передачи данных между страницами. Одна страница пишет данные в сессию, другая – берет потом оттуда.

Наряду с объектом Session существует объект Application . Если сессия создается для каждого нового пользователя, до Application существует в единственном экземпляре, и может использоваться всеми страницами приложения.

Управление приложением

Программисту предоставляется возможность реагировать на 4 события: старт/стоп приложения и старт/стоп каждой сессии. Для реализации этих событий предназначен файл global.asa , который должен располагаться в корневом каталоге приложения. Вот его примерный скелет:

Нужно «просто» вписать Ваш код на соответствующее место. Нужно заметить, что отлаживать код для global.asa довольно непросто, так как он выполняется при очень специфических обстоятельствах (к примеру при старте или остановке сервера).

Использование внешних компонент

Если на сервере установлены дополнительные компоненты, их можно использовать из ASP. Стандартные объекты (например из библиотек ADO (Connection и Recordset) и Scripting (Dictionary, FileSystemObject)) доступны всегда. Установка новой компоненты обычно состоит в копировании dll-файла в каталог на сервере и ее регистрации с помощью программы regsvr32.exe. [В COM+ используется своя процедура инсталляции объектов, это однако не влияет на использования объектов.]

Создать экземпляр объекта можно так:

Class.Object указываются в документации на компоненту. В переменной var запоминается ссылка на созданный экземпляр объекта. Когда объект не нужен, ссылку нужно обнулить с помощью команды:

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

В остальном использование компоненты зависит от самой этой компоненты.

Работа с базами данных

Из ASP можно легко и просто работать с любыми базами данных. Это делается через две промежуточные технологии: ODBC и ADO.

ODBC позволяет организовать доступ к любым базам данных через унифицированный интерфейс с помощью языка SQL. Специфика конкретных СУБД учитывается при помощи специальных драйверов БД. Такие драйверы существуют для всевозможных СУБД (в частности SQL Server, Oracle, Access, FoxPro). Поддержка ODBC обеспечивается на уровне операционной системы Windows (NT). Настройка – через Control Panel/ODBC. Базовым понятием является источник данных или data source. Источник данных – это совокупность сведений о базе данных, включая ее драйвер, имя компьютера и файла, параметры. Чтобы пользоваться базой надо создать источник данных для нее. Важно, чтобы источник данных был «системным», в отличии от «пользовательского». После этого надо лишь знать имя источника данных. [В настоящее время ODBC отступает перед натиском технологии OLE DB. На практике это однако практически ничего не изменяет. Вместо имени источника данных нужно использовать Connection String, в которой указывается имя ODBC-драйвера и все его параметры.]

ADO – это совокупность объектов, доступных из ASP, позволяющих обращаться к источнику данных ODBC [или OLE DB]. Фактически нужны лишь 2 объекта – Connection , представляющий соединение с базой данных и Recordset , представляющий набор записей, полученный от источника. Сначала необходимо открыть соединение, потом к нему привязать Recordset, потом, пользуясь методами Recordset’а, обрабатывать данные. Вот пример:

Если команда SQL не возвращает данных, recordset не нужен, надо пользоваться методом Conn. Execute (SQL_COMMAND).

Если Вы хотите вызывать хранимые процедуры сервера БД с параметрами, нужно воспользоваться объектом Command , который в свою очеред содержит объекты Parameter .

Методики программирования, советы


Описание переменных

VBScript — очень нетребовательный к программисту язык. Так он не требует описывать переменные и не содержит явных типов данных. Все переменные принадлежат одному типу Variant . Из-за отсутствия описаний могут произойти очень трудно обнаруживаемые ошибки. Одна опечатка может стоить полдня поисков.

Однако, есть возможность явно потребовать описания переменных. Для этого первой строкой в ASP-файле нужно написать Option Explicit . После этого обращение к переменной, которая не была объявлена с помощью Dim , вызывает ошибку с указанием номера строки.

Кстати, где расположены описания Dim в процедуре — совершенно не важно. Они могут стоять как до использования переменной, так и после, и даже в цикле. Видимо они отрабатываются препроцессором. Явно задать тип переменной с помощью Dim Var as Typ , как в Visual Basic, все равно нельзя.

Чередование ASP/HTML

Если нужно выдать большой кусок HTML, можно не пользоваться Response.Write. Если в asp-файле встречается кусок текста вне скобок , он трактуется просто как HTML, который надо вывести. Пример:

Обработка ошибок

Для отслеживания ошибок используется специальный объект Err . Он устанавливается в ненулевое значение, если предыдущая команда породила ошибку. Ее можно проверять с помощью If, и таким образом реагировать на ошибки. Чтобы из-за ошибки не прерывалось выполнение программы, в начале нужно включить команду


Включение других файлов

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

Важно: все includes в тексте отрабатываются до исполнения файла. Т.е. даже если include стоит внутри if, то сначала будут включены все includes во всех ветках, и только потом, во время исполнения, будет принятно решение, какую ветку выполнять. Т.е. следующий код не дает условного включения файлов:

Обработка форм

Если надо что-то спросить у пользователя и на основании этого что-то сделать, в простейшем случае создается два файла: один с формой, второй – с ее обработчиком. Обработчик выполняет все действия. Пример:

Рекурсивная обработка форм

Удобный метод состоит в том, чтобы сбор данных и обработку осуществлял один и тот же файл. Для этого пишется asp, в котором есть разные разделы. Специальная переменная отвечает за выбор раздела при запуске. Пример:

Переменные HTTP

Запрос от браузера, кроме запрашиваемой страницы несет еще некоторые данные. Эти данные, например, IP-адрес клиента, доступны через специальные переменные объекта Request. IP-адрес – Request(«REMOTE_ADDR»). Другие — см.документацию (ASPSamp\Samples\srvvar.asp).

Переадресация

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

Только надо следить, чтобы до выполнения команды redirect ничего не было записано в Response (даже коментарии HTML).

Электронная почта

Одна из часто встречающихся задач – отправить электронную почту с Web-страницы. На первый взгляд, можно просто написать

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

Для этого существуют внешние компоненты, есть и бесплатные. Например, компонента Jmail от Dimac. Все, что для нее нужно – это адрес SMTP-сервера. Вот пример ее использования:

Нарушение границы приложения на ASP.NET

Я создаю интегрированную среду тестирования, предназначенную для конкретной группы приложений. В тестовой среде используется инфраструктура тестирования VS. Приложения для тестовых приложений являются веб-клиентами, поэтому тестовая среда должна стать веб-сервером. Чтобы удовлетворить эту потребность, я запускаю Cassini в тестовой среде, которая загружает веб-сайт во время теста. Все прекрасно и работает. Таким образом, процесс выглядит следующим образом:

  1. Испытательная среда запускает Cassini, загружает мой веб-сайт
  2. Тестовая среда запускает приложение испытуемого, которое вызывает мой веб-сайт
  3. В тестовой среде необходимо сравнить фактические изменения содержимого веб-сайта с ожидаемыми изменениями.

Проблема возникает на шаге 3. Моя тестовая среда и Cassini работает в одном приложении, сайт работает в другом. Как я могу прорвать границы приложения?

У меня есть полный контроль над

  • Исходный код тестовой среды
  • Исходный код Кассини
  • Исходный код веб-сайта, загруженный Cassini

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

asp.net integration-testing appdomain cassini

1 ответ

1 Решение user256890 [2011-11-09 13:48:00]

Длительный фоновый процесс в asp.net core

У меня есть web api на asp.net core . По кнопке с формы запускаю фоновую задачу, которая может выполняться до 5 часов.

Проблема такая, что по истечению около 1 часа фоновая задача принудительно завершается.

Сначала фоновую задачу запускал таким способом:

Как видно из кода данные должны сохраняться в таблицу. Если фоновый поток работает меньше часа, то так и происходит. Если больше, то до сохранения не доходит. Сначала, я подумал, что некорректно запускаю фоновый процесс.

Выбрал последний вариант: Фоновые задачи в очереди. Адаптировал под свой проект. Запускаю в режиме отладки F5. И где-то через час происходит тоже самое. Еще заметил, что в режиме отладки в visual studio по истечению часа, она(отладка) завершается(окна Вывод, стек вызовов закрывается), информации об исключениях или ошибках нет никакой, web api по-прежнему доступно. При обновлении страницы в веб-приложении(которое работает с web api ) информация об активной фоновой задаче пропадает и подгружаются из таблицы результаты предыдущей фоновой задачи.

Активные задачи сохраняю вот в таком классе, который объявлен как синглтон сервис.

IT1410: Разработка требований к программному обеспечению

Определение границ — структура, а не смирительная рубашка. Бизнес-требования и понимание того, как клиенты будут использовать продукт, ценны при работе с границами проекта.

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

Помните, каждый раз, когда кто-то выдвигает новое требование, аналитик должен спросить: «Попадает ли оно в рамки проекта?»

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

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

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

Использование бизнес-целей для принятия решений о границах проекта

Бизнес-цели — самый важный фактор, который нужно учитывать, принимая решения о границах проекта. Определите, какие из предложенных функций или пользовательских требований приносят самую большую выгоду с точки зрения бизнес-целей и запланируйте их на самые первые выпуски.

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

Если возможно, оцените количественно вклад функции в достижение бизнес-цели, чтобы решения о границах принимались на основе фактов, а не эмоций. Какой будет вклад новой функции — тысяча, сто тысяч или миллион? Когда топ-менеджер просит добавить новую функцию, которую придумал за выходные, нужно применить численный анализ, чтобы определить, правильно ли бизнес-решение добавить ее в продукт.

Оценка эффекта от изменения границ проекта

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

Обычный результат изменения границ заключается в том, что завершенные действия приходится переделывать. Если при добавлении новой функциональности не увеличиваются выделенные на проект время или ресурсы, часто страдает качество. Задокументированные бизнес-требования облегчают управление изменениями границ проекта при изменении рыночных условий или бизнес-потребностей. Они также облегчают задачу утомленному менеджеру проекта, когда ему нужно сказать «нет» или, по крайней мере, «не сейчас» влиятельным людям, старающимся впихнуть побольше функций в и так напряженный проект.

Концепция и границы в проектах гибкой разработки

Для управления границами проектом гибкой разработки (agile), в котором разработка ведется сериями коротких итераций, нужно применять другой подход. Границы каждой итерации состоят их пользовательских историй, выбранных из динамического резерва (backlog) на основе их относительных приоритетов и расчетной производительности команды в каждой итерации.

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

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

Команда может определить высокоуровневую дорожную карту итераций вначале проекта, но распределение пользовательских историй по итерациям может выполняться вначале каждой итерации. Обращение к бизнес требованиям при определении границ каждой последующей итерации помогает гарантировать, что будет поставлен продукт, отвечающий бизнес-целям. Подобная стратегия может применяться в любом проекте, состоящем из итераций (см. врезку «Управление объемом и разработка по итерациям»).

Управление объемом и разработка по итерациям

Энрике, менеджер проекта в Lightspeed Financial Systems, занимался выпуском интернет-версии ведущего программного продукта Lightspeed для управления портфелем ценных бумаг. Потребовались бы два года для поставки полнофункциональной версии приложения, однако компания должна была дать знать о себе в Интернете уже сейчас. Энрике выбрал прием «разработка по итерациям» и обещал выпускать новую версию каждые 90 дней. Его команда специалистов по маркетингу расставила приоритеты требований к продукту. В спецификацию требований для каждой ежеквартальной версии входил утвержденный набор новых и улучшенных функций, а также список «переходящих» требований низкого приоритета, которые предполагалось реализовать, если позволяло время. Команда Энрике не включала каждое такое требование в каждую версию, но они поставляли новую, стабильную версию каждые три месяца с помощью подхода, который учитывал график и управление границами итерации. График и качество — это естественные ограничения проекта «разработка по графику», а границы итерации представляли собой степень свободы.

Хотя в проектах гибкой разработки обычно и не создается формальный документ концепции и границ, содержимое шаблона на рис. 5-3 и относимо, и обязательно для поставки успешного продукта. Во многих проектах гибкой разработки выполняется начальная (нулевая) итерация планирования для определения общей концепции продукта и других требований проекта.

Бизнес-требования должны определяться во всех проектах разработки ПО независимо от модели разработки. Бизнес-цели описывают ожидаемую выгоду от проекта, а в проекте гибкой разработки они используются для облегчения определения приоритетов резерва (backlog), чтобы добиться максимальной ценности для бизнеса в самых ранних итерациях. Критерии успеха надо определить так, чтобы после развертывания можно было измерить успех и соответствующим образом скорректировать резерв проекта. Положение о концепции содержит долгосрочный план — то, чем должен стать продукт по завершении всех итераций.

Применение бизнес-целей для определения момента завершения проекта

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

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

Однако именно в проектах с итеративной разработкой финальная точка может быть неопределенной. Для каждой итерации определяются ее границы. По мере продвижения проекта резерв незавершенной работы сокращается. Не всегда необходимо реализовать полный набор остающейся функциональности. Критически важно иметь четкие бизнес-цели, чтобы можно было двигаться к их удовлетворению поэтапно, по мере получения информации. Проект готов, когда критерии успеха указывают, что у вас хорошие шансы удовлетворить бизнес-цели. Нечеткие бизнес-цели — гарантия свободного проекта, в котором невозможно определить момент завершения. Финансирующим проект заказчикам это не нравится, потому что непонятно, как в таких проектах определить бюджет, график или план. Клиентам это не нравится, потому что они могут получить решение, которое поставляется в рамках бюджета и графика, но не предоставляет нужных им возможностей. Но этот риск присущ работе над продуктами, которые нельзя точно определить с самого начала, если только вы не уточните бизнес-цели в процессе работы над проектом.

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

Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL