Asp приемы управления приложением


Содержание

Ваше первое ASP.NET 5 веб приложение, созданное при помощи Visual Studio¶

В этом руководстве вы увидите, как создать простое веб приложение при помощи ASP.NET 5. В этом приложении данные будут связаны с базой данных SQL при помощи Entity Framework (EF), а ASP.NET MVC будет поддерживать операции CRUD.

Начальные реквизиты¶

Прежде чем начать, убедитесь, что вы сделали вот это: Установка ASP.NET 5 для Windows. Мы предполагаем, что у вас установлена Visual Studio 2015 и последняя версия среды и инструментария ASP.NET 5.

Дополнительную информацию по установке ASP.NET 5 на других платформах вы можете получить тут: Начинаем.

Создание нового ASP.NET 5 проекта¶

Запустите Visual Studio 2015. Из меню File выберите New > Project.

Выберите шаблон ASP.NET Web Application. Он находится в Installed > Templates > Visual C# > Web. Назовите проект ContosoBooks и нажмите OK.

В диалоговом окне New ASP.NET Project выберите Web Application под ASP.NET 5 Preview Templates. Кроме того, убедитесь, что галочка не стоит на Host in the cloud, и нажмите OK.

Не меняйте метод аутентификации. Оставьте по умолчанию Individual User Accounts.

Запуск приложения по умолчанию¶

После того как Visual Studio закончит создание приложения, запустите его, нажав Debug -> Start Debugging. Как вариант, вы можете нажать F5.

Для инициализации Visual Studio и нового приложения может потребоваться время. После завершения браузер покажет запущенное приложение.

После запуска приложения закройте браузер и нажмите на иконку “Stop Debugging” в Visual Studio, чтобы остановить приложение.

Просмотр проекта¶

В Visual Studio окно Solution Explorer позволяет вам управлять файлами проекта. Шаблон веб приложения, который вы использовали для создания этого приложения, добавляет следующую базовую структуру папок:

Visual Studio создает некоторые начальные файлы и папки для проекта. Вот первичные файлы, с которыми вам стоит ознакомиться:

Имя файла Цель
project.json Присутствие файла project.json определяет проект .NET Execution Environment (DNX). В файле project.json содержится вся информация, которая нужна DNX, чтобы запустить и упаковать ваш проект. Дополнительную информацию, включая файловую схему project.json, вы можете найти тут: see Работа с DNX проектами.
global.json Visual Studio использует этот файл для конфигурации проекта.
appsettings.json Этот файл позволяет вам включать дополнительную информацию о проекте. Дополнительную информацию вы можете получить тут: Конфигурация.
Startup.cs Класс Startup является начальной точкой приложения. В классе Startup должен быть определен метод Configure , кроме того, здесь может быть определен метод ConfigureServices , и он может быть вызван при запуске приложения. Дополнительную информацию вы можете получить тут: Запуск приложения.
Index.cshtml Здесь view содержит HTML для основной страницы.
_Layout.cshtml Здесь view содержит общий HTML для разных страниц веб приложения.
HomeController.cs Этот controller содержит классы, которые обрабатывают входящие запросы браузера, получают модельные данные, а затем определяют шаблоны представлений, которые возвращают ответ браузеру.

Понимание MVC¶

В этом проекте используется MVC. MVC обозначает Model-View-Controller (модель-представление-контроллер). MVC — это паттерн для разработки приложений, и эти приложения хорошо структурированы, их можно протестировать и легко поддерживать. MVC приложения содержат:

  • Models: Классы, которые представляют данные этого приложения, а затем используют логику валидации для связывания бизнес-правил и данных.
  • Views: Шаблонные файлы, которые использует приложение для динамичных HTML ответов.
  • Controllers: Классы, которые обрабатывают входящие браузерные запросы, получают модельные данные, а затем определяют представления, которые возвращают ответ браузеру.

Понимание .NET Core¶

.NET Core 5 — это модальная реализация среды разработки и библиотек, которая включает в себя некоторые аспекты .NET Framework. .NET Core 5 разрабатывается для Windows, Linux и OS X. .NET Core 5 состоит из набора библиотек “CoreFX” и маленькой среды разработки “CoreCLR”. .NET Core имеет открытый исходный код, так что вы можете отслеживать развитие проекта на GitHub. Больше информации вы можете получить тут: Выбор правильного .NET сервера.

Entity Framework¶

Entity Framework (EF) — это ORM (object-relational mapping) фреймворк. Он позволяет работать с реляционными данными как с объектами, и при этом вам нужно писать намного меньше кода для доступа к данным, чем обычно. Используя EF, вы можете работать с запросами при помощи LINQ, затем получать и обрабатывать данные как строго типизированные объекты. LINQ предлагает паттерны для запроса и обновления данных. Использование EF позволяет сфокусироваться на остальной части проекта, а не на основах доступа к данным.

Откройте файл project.json. В разделе dependencies вы увидите следующие строки, связанные с EF:

Здесь показано, что вы можете использовать команды EF из командного окна, а также что пакет EF NuGet включен в ваш проект.

Создание модели данных и скаффолдинг¶

Entity Framework поддерживает парадигму разработки Code First. Code First позволяет определять модели данных при помощи классов. Класс — это конструкция, которая позволяет создавать собственные пользовательские типы, группируя переменные разных типов, методы и события. Классы могут работать с существующей базой данных или генерируют базу данных. В данном руководстве вы начнете с создания entity-классов, которые определяют модели данных для веб приложения. Затем вы создадите контекстные классы, которые управляют entity-классами и дают данным доступ к базе данных. Далее вы настроите EF и заполните базу данных.

Создание entity-классов¶

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

В веб приложении будет две сущности:

Вы определите класс для каждой из них в папке Models в Solution Explorer.

Модельный класс вы можете поместить в любое место вашего проекта. Папка Models — это просто соглашение.

Кликните правой кнопкой мышки по папке Models и выберите Add > New Item. В диалоговом окне Add New Item выберите шаблон Class. В поле Name напишите “Author.cs” и нажмите OK.

Замените код по умолчанию следующим кодом:

Повторите эти шаги для создания другого класса Book со следующим кодом:

Чтобы не уложнять приложение, пусть у каждой книги будет один автор. Свойство Author определяет способ управления отношениями между автором и книгой. В EF этот тип свойства называется navigation property. Когда EF создает схему базы данных, EF автоматически вставляет AuthorID , и это будет вторичным ключом для таблицы Authors.

Скаффолдинг¶

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

Чтобы добавить скаффолдинг кликните правой клавишей мышки по папке Controllers в Solution Explorer. Выберите Add –> New Scaffolded Item.

Если вы не видите опцию New Scaffolded Item, убедитесь, что при создании проекта вы использовали Individual User Accounts.

Из диалогового окна Add Scaffold выберите MVC 6 Controller with views, using Entity Framework, а затем нажмите на кнопку Add.

Далее, в диалоговом окне Add Controller в списке с модельными классами выберите Book (ContosoBooks.Models). Также установите контекстный класс на ApplicationDbContext (ContosoBooks.Models). Флажок на Generate views должен быть установлен. Нажмите на кнопку Add.

Как вы видите, диалоговое окно Add Controller дает вам возможность выбирать опции для создания контроллеров и представлений.

Этот скаффолд создает код, который предоставляет контроллер и набор представлений. В представлениях есть UI и код для создания, чтения, обновления, удаления и перечисления данных из базы данных.

Повторите вышеперечисленные шаги по скаффолдингу, чтобы создать контроллер Author и связанные с ним представления. Используйте модельный класс Author (ContosoBooks.Models) и контекстный класс ApplicationDbContext (ContosoBooks.Models), как показано на следующем рисунке.

В Solution Explorer вы увидите, что новые контроллеры добавлены в папку Controller, а новые представления в папку Views.

Настройка приложения перед добавлением данных¶

Далее, к приложению нужно добавить пакет Microsoft.Extensions.DependencyInjection . В Solution Explorer найдите и откройте project.json. В разделе dependencies в конце раздела пропишите эту строку.

IntelliSense помогает вам, когда вы набираете. Когда вы сохраните project.json, Visual Studio автоматически даст ссылку на новый пакет.

После добавления этой строки раздел dependencies в файле project.json будет выглядеть вот так:


Добавление данных¶

Мы не будем вручную набирать данные — мы используем код, который заполнит базу данных. Добавьте класс SampleData в папке Models со следующим кодом:

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

Далее, в Solution Explorer, откройте файл Startup.cs. Добавьте следующую строку кода в методе Configure:

После этого полный файл Startup.cs будет выглядеть вот так:

Обратите внимание, что в ConfigureServices приложение вызывает Configuration[«Data:DefaultConnection:ConnectionString»] , чтобы получить строку соединения с базой данных. Во время разработки эта настройка идет из файла appsettings.json. Когда вы разворачиваете приложение в производственной среде, вы устанавливаете строку соединения в переменную среды на хосте. Если Configuration API находит переменную среды с тем же ключом, то возвращает переменную среды, вместо того значения, что находится в appsettings.json.

Создание веб приложения¶

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

Из меню Build выберите Build Solution.

Отображается окно Output, и если все прошло успешно, вы увидите соответствующее сообщение.

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

Прежде чем запустить приложение, вы должны создать БД, используя миграцию данных.

Использование миграции данных для создания базы данных¶

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

Откройте Command Prompt в директории проекта (ContosoBooks/src/ContosoBooks).

Чтобы открыть Command Prompt, кликните правой кнопкой мышки по кнопке start в Windows и выберите из меню Command Prompt.

Чтобы найти директорию проекта, кликните правой кнопкой мышки в Visual Studio по имени проекта (ContosoBooks) в Solution Explorer и выберите Open Folder in File Explorer. Скопируйте путь к проекту из File Explorer в Command Prompt. Например, введите следующее из Command Prompt, чтобы сменить директорию:

Убедитесь, что вы перешли к папке ContosoBooks, что в папке src.

Из Command Prompt запустите следующие команды:

Если dnu restore не распознается, вам нужно полностью повторить шаг с начальными реквизитами (или частично). Но сперва вам надо проверить Active версию .NET Version Manager (dnvm). Чтобы сделать это, введите dnvm list в командной строке. Если рядом с какой-либо версией нет *, установите активную версию, то есть, введите dnvm use 1.0.0-rc1-update1 -p , так что нужная версия будет выбрана.

.NET Version Manager (dnvm) — это набор утилит командной строки, которые используются для обновления и конфигурации .NET Runtime.

DNX обозначает .NET Execution Environment. Команда ef указана в файле project.json проекта. Больше информации по dnvm , dnu , and dnx , вы можете получить тут: DNX Overview.

Команда “ add Initial ” создает миграцию “Initial”, которая добавляет в проект код, позволяя EF обновлять схему базы данных. Команда update создает актуальную базу данных. После запуска этой команды папка Migrations будет обновлена:

Если вы хотите получить помощь по EF командам, введите следующее в командной строке: dnx ef -? . Для помощи с командой add введите следующее: dnx ef migrations add -? . А для помощи с командой update — следующее: dnx ef database update -? .

Кроме того, вы сможете увидеть новую базу данных в SQL Server Object Explorer.

Добавление навигации¶

Обновите навигацию для веб приложения. Из Solution Explorer откройте файл Views/Shared/_Layout.cshtml. Найдите следующий код:

Замените выше представленный код вот этим:

Данные изменения добавят ссылку к представлению Books и ссылку к представлению Authors. Вы создали эти представления, когда добавили в проект скаффолдинг.

Создание веб приложения¶

Чтобы убедиться, что все работает, вам снова нужно собрать приложение.

Из меню Build выберите Build Solution.

Локальный запуск веб приложения¶

Запустите приложение, чтобы увидеть, как выглядит вся продукция или категория продуктов.

В Solution Explorer кликните правой клавишей мышки по названию проекта и выберите View -> View in Browser. Либо же просто нажмите F5.

Откроется браузер и покажет приложение. Нажмите на ссылку Books вверху страницы.

Закройте браузер и нажмите на иконку “Stop Debugging” в Visual Studio.

Публикация приложения на Azure¶

В Solution Explorer в Visual Studio кликните правой кнопкой мышки по проекту и выберите Publish.

В окне Publish Web нажмите на Microsoft Azure Web Apps и залогиньтесь на Azure.

После этого нажмите New, чтобы создать на Azure новое приложение.

Назовите сайт, выберите сервисный план, ресурсную группу и регион. Также выберите сервер базы данных, а также имя пользователя и пароль к нему. Если вы уже создавали сервер базы данных, используйте его. После этого нажмите Create.

В Connection в окне Publish Web нажмите Publish.

Прогресс публикации вы можете просмотреть в окне Output или в окне Azure App Service Activity в Visual Studio.

После публикации на Azure ваше приложение, запущенное на Azure, будет отображено в браузере.

Дополнительная информация доступна вот тут: Publishing and Deployment.

Общие сведения о безопасности и поддержка ASP.NET (C#) Security Basics and ASP.NET Support (C#)

Это первый учебник в серии руководств, которые будут рассмотрены приемы проверки подлинности посетителей через веб-формы, предоставление доступа к определенной страницы и функциональность и управление учетными записями пользователей в приложении ASP.NET. This is the first tutorial in a series of tutorials that will explore techniques for authenticating visitors through a web form, authorizing access to particular pages and functionality, and managing user accounts in an ASP.NET application.

Вступление Introduction

Что такое форумы одну вещь, сайты электронной коммерции, электронной почте online веб-сайтов, веб-порталов и сайты социальных сетей, которые общего? What is the one thing forums, eCommerce sites, online email websites, portal websites, and social network sites all have in common? Все они предлагают учетные записи пользователей. They all offer user accounts. Сайты, которые содержат учетные записи пользователей необходимо предоставить несколько служб. Sites that offer user accounts must provide a number of services. Как минимум новый посетители должны иметь возможность создать учетную запись и возвращение посетителей должно быть возможность входа в систему. At a minimum, new visitors need to be able to create an account and returning visitors must be able to log in. Такие веб-приложения можно принимать решения, в зависимости от вошедшего в систему пользователя: некоторые страницы или действия может быть ограничен только для входа в систему пользователей, или для определенного подмножества пользователей. другие страницы может показывать сведения конкретного пользователя, выполнившего или могут более или менее отображаются сведения, в зависимости от того, какой пользователь просматривает страницы. Such web applications can make decisions based on the logged in user: some pages or actions might be restricted to only logged in users, or to a certain subset of users; other pages might show information specific to the logged in user, or might show more or less information, depending on what user is viewing the page.

Это первый учебник в серии руководств, которые будут рассмотрены приемы проверки подлинности посетителей через веб-формы, предоставление доступа к определенной страницы и функциональность и управление учетными записями пользователей в приложении ASP.NET. This is the first tutorial in a series of tutorials that will explore techniques for authenticating visitors through a web form, authorizing access to particular pages and functionality, and managing user accounts in an ASP.NET application. В ходе этих руководствах мы рассмотрим как: Over the course of these tutorials we will examine how to:

  • Определить и входа пользователей на веб-сайт Identify and log users in to a website
  • С помощью ASP. NET framework членство, управление учетными записями пользователей Use ASP.NET’s Membership framework to manage user accounts
  • Создание, обновление и удаление учетных записей пользователей Create, update, and delete user accounts
  • Ограничение доступа к веб-страницы, каталога или определенных функций в зависимости от текущего пользователя Limit access to a web page, directory, or specific functionality based on the logged in user
  • С помощью ASP. NET framework ролей связываемого учетные записи пользователей с ролями Use ASP.NET’s Roles framework to associate user accounts with roles
  • Управление ролями пользователей Manage user roles
  • Ограничение доступа к веб-страницы, каталога или определенные функции, на основе роли пользователя, вошедшего в систему Limit access to a web page, directory, or specific functionality based on the logged in user’s role
  • Настройка и расширение ASP. NET безопасности веб-элементов управления Customize and extend ASP.NET’s security Web controls

Учебных курсах предусмотрена краткая форма изложения и предоставляются поэтапные указания со множеством снимков экранов покажем процесс визуально. These tutorials are geared to be concise and provide step-by-step instructions with plenty of screen shots to walk you through the process visually. Каждое руководство доступно в C# и Visual Basic версии и загрузить полный код, используемый. Each tutorial is available in C# and Visual Basic versions and includes a download of the complete code used. (В этом первом учебнике описываются понятия безопасности с точки зрения высокого уровня и таким образом, не содержит любой соответствующий код.) (This first tutorial focuses on security concepts from a high-level viewpoint and therefore does not contain any associated code.)

В этом руководстве мы рассмотрим важные вопросы безопасности и какие средства доступны в ASP.NET, помогают реализовать форм проверки подлинности, авторизации, учетные записи пользователей и ролей. In this tutorial we will discuss important security concepts and what facilities are available in ASP.NET to assist in implementing forms authentication, authorization, user accounts, and roles. Давайте начнем! Let’s get started!


Безопасность является важным аспектом любого приложения, которое охватывает физический, технологический и политики решения и требуется высокая степень планирования и соответствующих знаний. Security is an important aspect of any application that spans physical, technological, and policy decisions and requires a high degree of planning and domain knowledge. Этой серии руководств не предназначен как руководство по разработке безопасных веб-приложений. This tutorial series is not intended as a guide for developing secure web applications. Вместо этого он предназначен исключительно для форм проверки подлинности, авторизации, учетные записи пользователей и ролей. Rather, it focuses specifically on forms authentication, authorization, user accounts, and roles. Хотя в этой серии рассматриваются некоторые основные понятия безопасности, вращение вокруг этих проблем, другие остаются непросмотренных. While some security concepts revolving around these issues are discussed in this series, others are left unexplored.

Проверка подлинности, авторизации, учетные записи пользователей и ролей Authentication, Authorization, User Accounts, and Roles

Проверки подлинности, авторизации, учетные записи пользователей и ролей являются четыре условия, которые будут использоваться очень часто данной серии учебных курсов, я бы хотел Отвлекитесь и быстро определить эти термины в контексте веб-безопасности. Authentication, authorization, user accounts, and roles are four terms that will be used very often throughout this tutorial series, so I’d like to take a quick moment to define these terms within the context of web security. В модели клиент сервер, например, в Интернете существует множество сценариев, в которых этот сервер должен идентифицировать клиента, выполняющего запрос. In a client-server model, such as the Internet, there are many scenarios in which the server needs to identify the client making the request. Проверка подлинности — это процесс позволяет установить удостоверение клиента. Authentication is the process of ascertaining the client’s identity. Клиент, у которого есть успешно считается проверку подлинности. A client who has been successfully identified is said to be authenticated. Неопознанная клиент считается без проверки подлинности или анонимный. An unidentified client is said to be unauthenticated or anonymous.

Системы безопасной проверки подлинности используют по крайней мере одно из следующих трех аспектов: что-то вы знаете, что-то у вас есть или что-то вы являетесь. Secure authentication systems involve at least one of the following three facets: something you know, something you have, or something you are. Большинство веб-приложений полагаться на то, что клиент узнает, как пароль или ПИН-код. Most web applications rely on something the client knows, such as a password or a PIN. Сведения, используемые для идентификации пользователя — своего имени пользователя и пароль, например — называются учетные данные. The information used to identify a user — her username and password, for example — are referred to as credentials. Этой серии руководств посвящена проверки подлинности форм, который представляет собой модель проверки подлинности, где пользователи Войдите на сайт, указав свои учетные данные в виде веб-страницы. This tutorial series focuses on forms authentication, which is an authentication model where users log in to the site by providing their credentials in a web page form. Мы все испытывать этого типа проверки подлинности, прежде чем. We have all experienced this type of authentication before. Перейдите на сайт электронной коммерции. Go to any eCommerce site. Когда будете готовы выполнить извлечение будет предложено выполнить вход, введя имя пользователя и пароль в текстовые поля на веб-странице. When you are ready to check out you are asked to log in by entering your username and password into textboxes on a web page.

Помимо выявления клиентов, сервер может потребоваться ограничить, какие ресурсы или функциональные возможности доступны в зависимости от клиента, отправившего запрос. In addition to identifying clients, a server may need to limit what resources or functionalities are accessible depending on the client making the request. Авторизация — это процесс определения, имеет ли определенному пользователю полномочия на доступ к определенному ресурсу или функции. Authorization is the process of determining whether a particular user has the authority to access a specific resource or functionality.

Объект учетной записи пользователя — это хранилище для сохранения информации о конкретном пользователе. A user account is a store for persisting information about a particular user. Учетные записи пользователей как минимум необходимо включить сведения, который уникально идентифицирует пользователя, такие как имя пользователя и пароль. User accounts must minimally include information that uniquely identifies the user, such as the user’s login name and password. Вместе с эту важную информацию, учетные записи пользователей могут включать, например: адрес электронной почты пользователя; Дата и время создания учетной записи; Дата и время последнего входа в систему. имя и фамилия; номер телефона; и почтовый адрес. Along with this essential information, user accounts may include things like: the user’s email address; the date and time the account was created; the date and time they last logged in; first and last name; phone number; and mailing address. При использовании проверки подлинности форм, данные учетной записи пользователя обычно хранятся в реляционной базе данных, таких как Microsoft SQL Server. When using forms authentication, user account information is typically stored in a relational database like Microsoft SQL Server.

Веб-приложений, которые поддерживают учетные записи пользователей при необходимости может группировать пользователей в ролей. Web applications that support user accounts may optionally group users into roles. Роль — просто метку, которая будет применена к пользователю и предоставляет абстракцию для определения правила авторизации и функциональные возможности уровня страницы. A role is simply a label that is applied to a user and provides an abstraction for defining authorization rules and page-level functionality. Например веб-сайт может включать роль администратора с помощью правил авторизации, которые запрещают всем, кроме администратора для доступа к определенный набор веб-страниц. For example, a website might include an Administrator role with authorization rules that prohibit anyone but an Administrator to access a particular set of web pages. Кроме того множество страниц, которые доступны для всех пользователей (включая администраторов) может отображать дополнительные данные или обеспечивают дополнительные функциональные возможности при посещении пользователями в роли «Администраторы». Moreover, a variety of pages that are accessible to all users (including non-Administrators) might display additional data or offer extra functionality when visited by users in the Administrators role. С помощью ролей, мы можем определить эти правила авторизации на роли по должностям, а не пользователя по. Using roles, we can define these authorization rules on a role-by-role basis rather than user-by-user.

Проверка подлинности пользователей в приложении ASP.NET Authenticating Users in an ASP.NET Application

Когда пользователь вводит URL-адрес в адрес окно браузера или щелчков мыши на ссылку, браузер выполняет протокола передачи гипертекста (HTTP) запроса на веб-сервер для заданного содержимого, будь то ASP.NET страницы, изображения, JavaScript файл, или любого другого типа содержимого. When a user enters a URL into their browser’s address window or clicks on a link, the browser makes a Hypertext Transfer Protocol (HTTP) request to the web server for the specified content, be it an ASP.NET page, an image, a JavaScript file, or any other type of content. Веб-сервер получает задание возврат запрошенного содержимого. The web server is tasked with returning the requested content. При этом она должна определить ряд вещей, о запросе, включая кто отправил запрос и ли удостоверение имеет права для получения запрошенного содержимого. In doing so, it must determine a number of things about the request, including who made the request and whether the identity is authorized to retrieve the requested content.

По умолчанию браузеры отправляют HTTP-запросов, не хватает каких-либо идентификационных данных. By default, browsers send HTTP requests that lack any sort of identification information. Но если браузер включают сведения о проверке подлинности веб-сервер запускает рабочий процесс проверки подлинности, которая используется для идентификации клиента, выполняющего запрос. But if the browser does include authentication information then the web server starts the authentication workflow, which attempts to identify the client making the request. Действия рабочего процесса проверки подлинности зависят от типа проверки подлинности используется веб-приложением. The steps of the authentication workflow depend on the type of authentication being used by the web application. ASP.NET поддерживает три типа проверки подлинности: Windows, Passport и форм. ASP.NET supports three types of authentication: Windows, Passport, and forms. В этой серии руководств нацелен на проверку подлинности форм, однако давайте уделим пару минут для сравнения и сравните хранилищами пользователей для проверки подлинности Windows и рабочего процесса. This tutorial series focuses on forms authentication, but let’s take a minute to compare and contrast Windows authentication user stores and workflow.

Проверка подлинности с помощью проверки подлинности Windows Authentication via Windows Authentication

Рабочий процесс проверки подлинности Windows использует один из следующих способов проверки подлинности: The Windows authentication workflow uses one of the following authentication techniques:

  • Обычная аутентификация Basic authentication
  • Дайджест-проверка подлинности Digest authentication
  • Встроенная проверка подлинности Windows Windows Integrated Authentication

Все три метода работы примерно таким же образом: когда несанкционированного, поступает анонимный запрос, веб-сервер отправляет обратно ответ HTTP, который указывает, что авторизации является обязательным для продолжения. All three techniques work in roughly the same way: when an unauthorized, anonymous request arrives, the web server sends back an HTTP response that indicates that authorization is required to continue. Затем браузер отображает модальное диалоговое окно, которое запрашивает у пользователя имя пользователя и пароль (см. рис. 1). The browser then displays a modal dialog box that prompts the user for their username and password (see Figure 1). Эта информация отправляется веб-сервере через заголовок HTTP. This information is then sent back to the web server via an HTTP header.

Рис. 1: Модальное диалоговое окно запрашивает у пользователя на ввод учетных данных Figure 1: A Modal Dialog Box Prompts the User for His Credentials

Предоставленные учетные данные проверяются на соответствие Store пользователя веб сервера Windows. The supplied credentials are validated against the web server’s Windows User Store. Это означает, что каждого пользователя, прошедшего проверку подлинности в веб-приложения необходимо иметь учетную запись Windows в вашей организации. This means that each authenticated user in your web application must have a Windows account in your organization. Это распространено в сценариях интрасети. This is commonplace in intranet scenarios. На самом деле при использовании встроенной проверки подлинности Windows в параметр интрасети, браузер автоматически предоставляет веб-сервер с учетные данные, используемые для входа в сеть, тем самым подавляя диалоговое окно, показанное на рис. 1. In fact, when using Windows Integrated Authentication in an intranet setting, the browser automatically provides the web server with the credentials used to log on to the network, thereby suppressing the dialog box shown in Figure 1. Во время проверки подлинности Windows отлично подходит для приложений интрасети, обычно представляется возможным для веб-приложений, так как вы не хотите создавать учетные записи Windows для каждого пользователя, который подписывается на веб-сайте. While Windows authentication is great for intranet applications, it is usually unfeasible for Internet applications since you do not want to create Windows accounts for each and every user who signs up at your site.

Проверка подлинности с помощью проверки подлинности форм Authentication via Forms Authentication

Проверка подлинности форм, с другой стороны, идеально подходит для веб-приложений для Интернета. Forms authentication, on the other hand, is ideal for Internet web applications. Помните, что проверка подлинности forms идентифицирует пользователя путем запроса их вводить свои учетные данные через веб-формы. Recall that forms authentication identifies the user by prompting them to enter their credentials through a web form. Следовательно когда пользователь пытается получить доступ к ресурсу несанкционированного, они автоматически перенаправляются на страницу входа, где они могут ввести свои учетные данные. Consequently, when a user attempts to access an unauthorized resource, they are automatically redirected to the login page where they can enter their credentials. Отправленные учетные данные затем проверяются на соответствие хранилищу пользователей — обычно базы данных. The submitted credentials are then validated against a custom user store — usually a database.

После проверки того, отправленной учетные данные, подлинности форм создается для пользователя. After verifying the submitted credentials, a forms authentication ticket is created for the user. Этот билет указывает, что пользователь прошел проверку подлинности и включает в себя идентификационные данные, такие как имя пользователя. This ticket indicates that the user has been authenticated and includes identifying information, such as the username. Билета проверки подлинности (обычно) хранится в виде файла cookie на клиентском компьютере. The forms authentication ticket is (typically) stored as a cookie on the client computer. Последующих посещениях веб-сайта, поэтому включать билета проверки подлинности в HTTP-запроса, тем самым позволяя веб-приложения для идентификации пользователя, после их входа в систему. Therefore, subsequent visits to the website include the forms authentication ticket in the HTTP request, thereby enabling the web application to identify the user once they have logged in.

Рис. 2 показан рабочий процесс проверки подлинности форм из точки зрения высокого уровня. Figure 2 illustrates the forms authentication workflow from a high-level vantage point. Обратите внимание на то, каким образом компоненты проверки подлинности и авторизации в ASP.NET выступать в качестве двух отдельных сущностях. Notice how the authentication and authorization pieces in ASP.NET act as two separate entities. Система проверки подлинности forms идентифицирует пользователя (или сообщает, что они являются анонимными). The forms authentication system identifies the user (or reports that they are anonymous). Система авторизации является то, что определяет, имеет ли пользователь доступ к запрошенному ресурсу. The authorization system is what determines whether the user has access to the requested resource. Если пользователь не авторизован (как это делается на рис. 2, при попытке посетить ProtectedPage.aspx анонимно), система авторизации сообщает, что пользователь отклонил, вызывая формы системой проверки подлинности, чтобы автоматически перенаправлять пользователя на страницу входа. If the user is unauthorized (as they are in Figure 2 when attempting to anonymously visit ProtectedPage.aspx), the authorization system reports that the user is denied, causing the forms authentication system to automatically redirect the user to the login page.

Как только пользователь успешно выполнил вход, последующие HTTP-запросы включают билета проверки подлинности. Once the user has successfully logged in, subsequent HTTP requests include the forms authentication ticket. Система проверки подлинности форм, просто идентифицирует пользователя, — это система авторизации, определяет ли пользователь доступ к запрошенному ресурсу. The forms authentication system merely identifies the user — it is the authorization system that determines whether the user can access the requested resource.

Рис. 2: Рабочий процесс проверки подлинности форм Figure 2: The Forms Authentication Workflow

Мы будет подробно описано проверки подлинности форм гораздо более подробно в следующих двух учебных курсах,Обзор аутентификации форм и конфигурацию проверки подлинности форм и дополнительные разделы. We will dig into forms authentication in much greater detail in the next two tutorials,An Overview of Forms Authentication and Forms Authentication Configuration and Advanced Topics. Дополнительные сведения о ASP. Параметры проверки подлинности NET, см. в разделе проверки подлинности ASP.NET. For more on ASP.NET’s authentication options, see ASP.NET Authentication.

Ограничение доступа к веб-страниц, каталогов и функциональные возможности страницы Limiting Access to Web Pages, Directories, and Page Functionality

ASP.NET включает два способа определить, имеет ли определенному пользователю полномочия на доступ к определенному файлу или каталогу. ASP.NET includes two ways to determine whether a particular user has authority to access a specific file or directory:

  • Авторизация файлов — поскольку страниц ASP.NET и веб-служб, реализованы как файлы, которые находятся в файловой системе веб сервера, доступ к этим файлам можно указать с помощью списков управления доступом (ACL). File authorization — since ASP.NET pages and web services are implemented as files that reside on the web server’s file system, access to these files can be specified through Access Control Lists (ACLs). Авторизация файлов чаще всего используется с проверкой подлинности Windows, так как списки управления доступом, разрешения, которые применяются к учетным записям Windows. File authorization is most commonly used with Windows authentication because ACLs are permissions that apply to Windows accounts. При использовании проверки подлинности форм, системного уровня операционной системы и файл все запросы выполняются с той же учетной записи Windows, независимо от того, пользователь, посещения веб-узла. When using forms authentication, all operating system- and file system-level requests are executed by the same Windows account, regardless of the user visiting the site.
  • Авторизация URL-адреса-авторизации URL-адрес, разработчик указывает правила авторизации в файле Web.config. Эти правила авторизации указать, что пользователям или ролям получают доступ к, или запрещен доступ к определенным страницам или каталогам в приложении. URL authorization— with URL authorization, the page developer specifies authorization rules in Web.config. These authorization rules specify what users or roles are allowed to access or are denied from accessing certain pages or directories in the application.

Авторизация файла и авторизация URL-адреса определяют правила авторизации для доступа к определенной страницы ASP.NET или для всех страниц ASP.NET из определенного каталога. File authorization and URL authorization define authorization rules for accessing a particular ASP.NET page or for all ASP.NET pages in a particular directory. С помощью этих методов можно указать ASP.NET, чтобы отклонять запросы на определенной странице для конкретного пользователя, или разрешить доступ к определенным пользователям и запретить доступ для всех остальных. Using these techniques we can instruct ASP.NET to deny requests to a particular page for a particular user, or allow access to a set of users and deny access to everyone else. Как насчет сценариях, где все пользователи могут получить доступ к странице, но функциональные возможности страницы зависит от пользователя? What about scenarios where all of the users can access the page, but the page’s functionality depends on the user? Например многие узлы, которые поддерживают учетные записи пользователей имеют страниц, которые отображают различные содержимое или данные для прошедших проверку пользователей и анонимных пользователей. For example, many sites that support user accounts have pages that display different content or data for authenticated users versus anonymous users. Анонимный пользователь может см. в статье ссылки для входа на сайт, тогда как текущий пользователь прошел бы вместо этого см. в разделе сообщения, такие как, Добро пожаловать, Username вместе со ссылкой, чтобы выйти. Еще один пример: при просмотре элемента аукциона вы увидите различные сведения в зависимости от того, являетесь ли вы bidder или один, auctioning элемента. An anonymous user might see a link to log in to the site, whereas an authenticated user would instead see a message like, Welcome back, Username along with a link to log out. Another example: when viewing an item at an auction site you see different information depending on whether you are a bidder or the one auctioning the item.

Такие изменения уровня страницы можно сделать декларативно или программно. Such page-level adjustments can be accomplished declaratively or programmatically. Для отображения разного содержимого для анонимных прошедших проверку подлинности пользователей, просто перетащите элемента управления LoginView на страницу и введите соответствующее содержимое в своих шаблонах AnonymousTemplate и LoggedInTemplate. To show different content for anonymous than authenticated users, simply drag a LoginView control onto your page and enter the appropriate content into its AnonymousTemplate and LoggedInTemplate templates. Кроме того, можно программным способом определить является ли текущий запрос проходит проверку подлинности, кем является пользователь и какие роли они принадлежат к (если таковые имеются). Alternatively, you can programmatically determine whether the current request is authenticated, who the user is, and what roles they belong to (if any). Можно использовать эти сведения затем отображать или скрывать столбцы в сетку или панели на странице. You can use this information to then show or hide columns in a grid or Panels on the page.

Эта серия включает в себя три учебников, посвященных авторизации. This series includes three tutorials that focus on authorization. Авторизация на основе пользователярассматривается ограничение доступа на страницу или страницы каталога для отдельных пользователей; Авторизации на основе ролей рассматривает указания правил авторизации в роли уровня; Наконец, отображение содержимого на основе сейчас войти в систему пользователя руководстве рассматриваются изменения определенного содержимое страницы и функций в зависимости от пользователя, посещающего страницу. User-Based Authorizationexamines how to limit access to a page or pages in a directory for specific user accounts; Role-Based Authorization looks at supplying authorization rules at the role level; lastly, the Displaying Content Based on the Currently Logged In User tutorial explores modifying a particular page’s content and functionality based on the user visiting the page. Дополнительные сведения о ASP. Параметры авторизации NET, см. в разделе авторизации ASP.NET. For more on ASP.NET’s authorization options, see ASP.NET Authorization.

Учетные записи пользователей и ролей User Accounts and Roles

ASP. Проверка подлинности форм NET предоставляет инфраструктуру для пользователей для входа на сайт и их состояние прошедшего проверку подлинности, запоминаются посещений страницы. ASP.NET’s forms authentication provides an infrastructure for users to log in to a site and have their authenticated state remembered across page visits. И авторизации URL-адрес представляет собой платформу для ограничения доступа к определенные файлы или папки в приложении ASP.NET. And URL authorization offers a framework for limiting access to specific files or folders in an ASP.NET application. Тем не менее, ни функция предоставляет средства для хранения учетных записей пользователей и управление ролями. Neither feature, however, supplies a means for storing user account information or managing roles.

До версии ASP.NET 2.0 разработчикам было ответственность за создание собственных хранилищ пользователя и роли. Prior to ASP.NET 2.0, developers were responsible for creating their own user and role stores. Они также были на ком оно висит для разработки пользовательских интерфейсов и написание кода для essential пользователя страниц, связанные с учетной записью, таких как страница входа и страницы, чтобы создать новую учетную запись, среди прочего. They were also on the hook for designing the user interfaces and writing the code for essential user account-related pages like the login page and the page to create a new account, among others. Без любую платформу учетная запись встроенной в ASP.NET, каждый разработчик, реализующего пользователи имели дефектные свои проектные решения на вопросы, например, как хранить пароли и другие конфиденциальные сведения? и какие правила следует я применить к относительно длина пароля и стойкость? Without any built-in user account framework in ASP.NET, each developer implementing user accounts had to arrive at his own design decisions on questions like, How do I store passwords or other sensitive information? and What guidelines should I impose regarding password length and strength?

В настоящее время реализации учетных записей пользователей в приложении ASP.NET очень гораздо проще благодаря структуру членства и встроенный входа веб-элементов управления. Today, implementing user accounts in an ASP.NET application is much simpler thanks to the Membership framework and the built-in Login Web controls. Платформа членства — небольшое число классов в пространства имен System.Web.Security , которые предоставляют функциональные возможности для выполнения задач, связанных с учетной записи пользователя essential. The Membership framework is a handful of classes in the System.Web.Security namespace that provide functionality for performing essential user account-related tasks. Класс ключа в структуру членства является класс членства, который имеет методы, такие как: The key class in the Membership framework is the Membership class, which has methods like:

  • CreateUser CreateUser
  • DeleteUser DeleteUser
  • GetAllUsers GetAllUsers
  • GetUser GetUser
  • UpdateUser UpdateUser
  • ValidateUser ValidateUser

Использует платформу членства модель поставщика, который четко отделяет структуру членства API от его реализации. The Membership framework uses the provider model, which cleanly separates the Membership framework’s API from its implementation. Это позволяет разработчикам использовать общий API, но позволяет им использовать реализацию в соответствии с потребностями своего приложения. This enables developers to use a common API, but empowers them to use an implementation that meets their application’s custom needs. Иными словами класс членства определяет основные функциональные возможности платформы (методы, свойства и события), но фактически не предоставляет никаких сведений о реализации. In short, the Membership class defines the essential functionality of the framework (the methods, properties, and events), but does not actually supply any implementation details. Вместо этого методы класса членства вызвать настроенного поставщика, который является то, что выполняет фактическую работу. Instead, the methods of the Membership class invoke the configured provider, which is what performs the actual work. Например когда вызывается метод CreateUser класс членства, класс членства не знает, сведения о хранилище пользователя. For example, when the Membership class’s CreateUser method is invoked, the Membership class doesn’t know the details of the user store. Он не знает, если пользователи находятся в базе данных или в XML-файл или в какого-либо другие хранилища. It doesn’t know if users are being maintained in a database or in an XML file or in some other store. Класс членства проверяет конфигурацию веб-приложения, чтобы определить, какой поставщик делегировать вызов, и этого класса поставщик отвечает за фактически Создание новой учетной записи пользователя в хранилище пользователя. The Membership class examines the web application’s configuration to determine what provider to delegate the call to, and that provider class is responsible for actually creating the new user account in the appropriate user store. На рис. 3 показано это взаимодействие. This interaction is illustrated in Figure 3.

Корпорация Майкрософт предоставляет два класса поставщика членства в .NET Framework: Microsoft ships two Membership provider classes in the .NET Framework:

  • ActiveDirectoryMembershipProvider -реализует API членства на серверах Active Directory и Active Directory Application Mode (ADAM). ActiveDirectoryMembershipProvider — implements the Membership API in Active Directory and Active Directory Application Mode (ADAM) servers.
  • SqlMembershipProvider -реализует API членства в базе данных SQL Server. SqlMembershipProvider — implements the Membership API in a SQL Server database.

В этой серии руководств посвящена исключительно SqlMembershipProvider. This tutorial series focuses exclusively on the SqlMembershipProvider.

Рис 03: Поставщик модели включает различные реализации легко подключать в платформ (Просмотр полноразмерного изображения) Figure 03: The Provider Model Enables Different Implementations to be Seamlessly Plugged Into the Framework (Click to view full-size image)

Преимущество модели поставщика — что альтернативных реализаций разработки корпорацией Майкрософт, сторонними поставщиками или отдельных разработчиков и легко подключать структуру членства. The benefit of the provider model is that alternative implementations can be developed by Microsoft, third-party vendors, or individual developers and seamlessly plugged into the Membership framework. Например, корпорация Microsoft выпустила поставщик членства для баз данных Microsoft Access. For example, Microsoft has released a Membership provider for Microsoft Access databases. Дополнительные сведения о поставщиков членства, см. Provider Toolkit, который включает Пошаговое руководство поставщиков членства, примеры пользовательских поставщиков, более 100 страниц документации на модели поставщика и Полный исходный код для встроенных поставщиков членства (а именно, ActiveDirectoryMembershipProvider и SqlMembershipProvider). For more information on the Membership providers, refer to the Provider Toolkit, which includes a walkthrough of the Membership providers, sample custom providers, over 100 pages of documentation on the provider model, and the complete source code for the built-in Membership providers (namely, ActiveDirectoryMembershipProvider and SqlMembershipProvider).

ASP.NET 2.0 также появился framework ролей. ASP.NET 2.0 also introduced the Roles framework. Как структуру членства ролей framework строится поверх модели поставщиков. Like the Membership framework, the Roles framework is built atop the provider model. Выполняется через API класс ролей и .NET Framework поставляется с тремя классы поставщика: Its API is exposed via the Roles class and the .NET Framework ships with three provider classes:

  • AuthorizationStoreRoleProvider -управляет сведения о роли в хранилище политик диспетчера авторизации, например Active Directory или ADAM. AuthorizationStoreRoleProvider — manages role information in an authorization-manager policy store, such as Active Directory or ADAM.
  • SqlRoleProvider -реализует роли в базе данных SQL Server. SqlRoleProvider — implements roles in a SQL Server database.
  • WindowsTokenRoleProvider -связывает сведения о роли, на основе группы Windows посетителя. WindowsTokenRoleProvider — associates role information based on the visitor’s Windows group. Этот метод обычно используется с проверкой подлинности Windows. This method is typically used with Windows authentication.

В этой серии руководств посвящена исключительно SqlRoleProvider. This tutorial series focuses exclusively on the SqlRoleProvider.

Поскольку модель поставщика включает единый API Передняя (классы членства и ролей), существует возможность создания функций вокруг API, который не нужно беспокоиться о подробностях реализации — тех обрабатываются поставщиками, выбранные на странице разработчик. Since the provider model includes a single forward-facing API (the Membership and Roles classes), it is possible to build functionality around that API without having to worry about the implementation details — those are handled by the providers selected by the page developer. Этот унифицированный интерфейс API позволяет корпорации Майкрософт и сторонних поставщиков для создания веб-элементы управления, взаимодействующие с платформ членства и ролей. This unified API allows for Microsoft and third-party vendors to build Web controls that interface with the Membership and Roles frameworks. В ASP.NET имеется ряд входа веб-элементов управления для реализации распространенных интерфейсов пользователя учетной записи пользователя. ASP.NET ships with a number of Login Web controls for implementing common user account user interfaces. Например элемент управления Login предлагает пользователю ввести учетные данные, проверяет их, а затем регистрирует их в с помощью проверки подлинности форм. For example, the Login control prompts a user for their credentials, validates them, and then logs them in via forms authentication. Элемента управления LoginView предоставляет шаблоны для показа различные разметки для анонимных пользователей и пользователей, прошедших проверку подлинности, разную разметку в зависимости от роли пользователя. The LoginView control offers templates for displaying different markup to anonymous users versus authenticated users, or different markup based on the user’s role. И элемент управления CreateUserWizard пошаговые пользовательский интерфейс для создания учетной записи пользователя. And the CreateUserWizard control provides a step-by-step user interface for creating a new user account.

Принципы работы различных элементов управления входа взаимодействовать с платформ членства и ролей. Underneath the covers the various Login controls interact with the Membership and Roles frameworks. Большинство элементов управления входа можно реализовать без необходимости писать ни одной строки кода. Most Login controls can be implemented without having to write a single line of code. Мы рассмотрим эти элементы управления более подробно в последующих учебных курсах, включая способы расширения и настройки их функциональность. We will examine these controls in greater detail in future tutorials, including techniques for extending and customizing their functionality.

Сводка Summary

Все веб-приложения, которые поддерживают учетные записи пользователей требуется аналогичные функциональные возможности, например: пользователям для входа и обладает их входа в состояние, запоминаются посещений страницы; веб-страницы для новых посетителей создать учетную запись; и возможность разработчику страницы указать, какие ресурсы, данных и функции доступны какие пользователям или ролям. All web applications that support user accounts require similar features, such as: the ability for users to log in and have their log in status remembered across page visits; a web page for new visitors to create an account; and the ability to the page developer to specify what resource, data, and functionality are available to what users or roles. Задачи проверки подлинности и авторизации пользователей и управления учетными записями пользователей и ролями примечательно просто для выполнения в приложениях ASP.NET благодаря платформ членства и ролей, URL-адрес авторизации и проверки подлинности форм. The tasks of authenticating and authorizing users and of managing user accounts and roles is remarkably easy to accomplish in ASP.NET applications thanks to forms authentication, URL authorization, and the Membership and Roles frameworks.

Во время выполнения нескольких следующих учебных курсах мы рассмотрим эти аспекты путем построения рабочий веб-приложения с нуля в пошаговой форме. Over the course of the next several tutorials we will examine these aspects by building a working web application from the ground up in a step-by-step fashion. В следующих двух учебном курсе мы рассмотрим проверку подлинности форм подробно. In the next two tutorial we will explore forms authentication in detail. Мы увидим, рабочий процесс проверки подлинности форм в действии, проанализируем билета проверки подлинности, обсудить проблемы безопасности и узнать, как настроить систему проверки подлинности форм — все при построении веб-приложение, которое позволяет посетителям вход и выход. We will see the forms authentication workflow in action, dissect the forms authentication ticket, discuss security concerns, and see how to configure the forms authentication system — all while building a web application that allows visitors to log in and log out.

Счастливого вам программирования! Happy Programming!

Дополнительные сведения Further Reading


Дополнительные сведения по темам, обсуждавшимся в этом руководстве см. в следующих ресурсах: For more information on the topics discussed in this tutorial, refer to the following resources:

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

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

Как правло, для решения большинства задач в 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 будет тем же.

ASP.NET 2.0. Обзор новых сервисов, элементов управления и средств (1 часть)

Спустя четыре года после своего выхода ASP.NET стала «золотым стандартом» для Web-приложений, выполняемых на серверах под управлением Windows, а строка runat=»server» прочно вошла в лексикон Web-разработчиков всего мира. Кроме того, ASP.NET позволила очертить контуры будущего Web-программирования — будущего, в котором важное место занимают серверные элементы управления, выполняющие рендеринг HTML-кода и сценариев и вызывающие события. В следующей версии Microsoft .NET Framework ASP.NET 2.0 выйдет из подросткового возраста и станет зрелой платформой. Ее разработчики рассчитывают сократить на 70% и более объем кода, необходимого для решения типичных задач Web-программирования. Добиться этого нелегко, но возможно, поскольку благодаря многочисленным новым сервисам, элементам управления и средствам у ASP.NET 2.0 есть все шансы стать столь же значительным усовершенствованием ASP.NET 1.x, каким ASP.NET 1.x была для ASP. Эта статья — развернутый обзор новшеств в ASP.NET 2.0. Чтобы лучше осветить ключевые средства, я рассмотрю некоторые области более подробно и приведу примеры программ. Все примеры кода скомпилированы и протестированы в версии ASP.NET 2.0, предшествовавшей бета-версии. Возможно, чтобы эти примеры работали в бета-версии, некоторые из них придется изменить.

Эта статья написана на основе предварительной версии ASP.NET 2.0 Community Technology Preview, вышедшей в марте 2004 г. Любая содержащаяся здесь информация может быть изменена.Community Technology Preview, вышедшей в марте 2004 г. Любая содержащаяся здесь информация может быть изменена.

В статье используются следующие технологии: ASP.NET 1.x и C#.

В статье рассматриваются:

  • новые элементы управления, работающие с данными;
  • администрирование и роли;
  • персонализация и темы;
  • написание кода и параметры компиляции.

Master Pages

Один из самых бросающихся в глаза недостатков ASP.NET 1.x — отсутствие поддержки шаблонов страниц. Нельзя определить «эталонную страницу» (master page), от которой наследуют другие страницы. Разработчики решают эту проблему, создавая страницы с помощью пользовательских элементов управления, которые легко воспроизводить на разных страницах. В ASP.NET 2.0 больше не нужно прибегать к таким приемам, поскольку появилось новое средство — Master Pages. Чтобы описать, что такое Master Pages, подойдет термин «визуальное наследование». Сначала вы определяете эталонную страницу, содержащую то, что должно присутствовать на других страницах, и с помощью элементов управления ContentPlaceHolder задаете места, в которые дочерние страницы (subpages) могут помещать свое содержимое. Затем разрабатываете дочерние страницы — ASPX-файлы, ссылающиеся на эталонную страницу через директивы вида:

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

В приложении в листингах и эталонная страница используется, чтобы определить заголовок и колонтитул, показываемые на каждой странице. Дочерняя страница вставляет содержимое между заголовком и колонтитулом, добавляя элемент Content, ссылающийся на ContentPlaceHolder эталонной страницы. Обратите внимание на совпадение ID и ContentPlaceHolderID и на директиву @ Master в эталонной странице.

Листинг 1. Master Pages. Файл Master.master

Листинг 2. Master Pages. Файл Subpage.aspx

Master Pages полностью поддерживается объектной моделью ASP.NET. В класс System.Web.UI.Page добавлено свойство Master, позволяющее дочерним страницам программно обращаться к своим эталонным страницам и определенным в них элементам управления. Допускается вложение эталонных страниц и включение в них контента по умолчанию, который могут переопределять дочерние страницы:

Кроме того, в файле Web.config можно задать эталонную страницу, по умолчанию используемую приложением:

Разработчики дочерних страниц могут переопределять контент, используемый по умолчанию, и создавать собственные эталонные страницы. Изюминка Master Pages в том, что эта технология поддерживается Visual Studio 2005. При загрузке дочерней страницы IDE показывает содержимое, заданное в эталонной странице, блеклым цветом и не разрешает его изменять, а содержимое, заданное в дочерней странице, отображает обычными цветами и разрешает редактировать. Благодаря этому легко понять, где определено содержимое, и, если требуется отредактировать содержимое, относящееся к эталонной странице, вы просто открываете в IDE шаблон страницы.

Более полное описание Master Pages можно найти в статье Фрица Аньена (Fritz Onion), опубликованной в этом номере «MSDN Magazine».

Элементы управления — источники данных

Связывание с данными — замечательная возможность ASP.NET 1.x. Несколько строк кода для связывания с данными, помещенные в нужное место, заменяют массу ASP-кода, выполняющего запрос к базе данных и многократно вызывающего метод Response.Write, чтобы представить результаты запроса в HTML-формате. В ASP.NET 2.0 связывание с данными станет еще проще. Во многих случаях писать код вообще не потребуется благодаря новым элементам управления — источникам данных (элементам источников данных) (data source controls), перечисленным во врезке «Новые элементы управления, планируемые в ASP.NET 2.0″».

Следующая страница DataSource1.aspx, используя связывание с данными в ASP.NET 2.0, показывает выборку из базы данных Pubs (SQL Server):

Элемент SqlDataSource определяет источник данных и выполняемый к нему запрос, а свойство DataSourceID элемента DataGrid ссылается на этот SqlDataSource. При загрузке страницы SqlDataSource выполняет запрос, результаты которого показываются в DataGrid.

Конечно, на практике связывание с данными редко бывает настолько простым. Допустим, вам нужно кэшировать результаты запроса или выполнять запросы к базам данных, указывая параметры, выбираемые в других элементах управления. Страница в листинге 3 использует один SqlDataSource, чтобы заполнить раскрывающийся список названиями стран из таблицы Customers базы данных Northwind, и другой — чтобы заполнить DataGr > указывает, что SqlDataSource элемента управления DataGrid берет значение @country из раскрывающегося списка. Также обратите внимание на атрибуты EnableCaching и CacheDuration элемента SqlDataSource, связанного с выпадающим списком. Эти атрибуты указывают, что результаты запроса SELECT DISTINCT кэшируются в течение 60 секунд.

Табл. 1. Новые элементы управления, планируемые в ASP.NET 2.0
Простые элементы
BulletedList Показывает маркированный список элементов
FileUpload Позволяет закачивать файлы через Web-страницы
HiddenField Представляет скрытые поля ( )
ImageMap Представляет карты изображений (image maps), используемые в HTML
Элементы источников данных
AccessDataSource Для связывания с данными баз Microsoft Access
ObjectDataSource Для связывания с данными классов, реализованных в собственных уровнях доступа к данным
SiteMapDataSource Для связывания с данными XML-карт сайта
SqlDataSource Для связывания с данными баз SQL, использующих провайдеры ADO.NET
XmlDataSource Для связывания с данными XML-документов
Элементы управления регистрацией
Login Интерфейс для входа с указанием имени пользователя и пароля
LoginName Отображает имена аутентифицированных пользователей
LoginStatus Интерфейс для входа и выхода
LoginView Показывает одно представление для пользователей, прошедших аутентификацию, и другое — для не прошедших
ChangePassword Интерфейс для смены паролей
PasswordRecovery Интерфейс для отправки забытых паролей по электронной почте
CreateUserWizard Интерфейс для создания новых учетных записей
Элементы управления страницами
Content Задает содержимое полей подстановки в страницах, наследуемых от Master Pages
DetailsView Отображает в HTML-таблице данные отдельной записи
DynamicImage Представляет динамически сгенерированные изображения
FormView Элемент, связываемый с данными, который поддерживает шаблоны и предоставляет очень гибкий UI
GridView Супер-DataGrid»; отображает наборы записей в виде HTML-таблиц
Menu Показывает выпадающие и восходящие (fly-out) меню
MultiView Разбивает страницу на несколько логических представлений
SiteMapPath Показывает пути к страницам
TreeView Представляет иерархические данные как деревья, узлы которых можно свертывать и развертывать
View Используется совместно с MultiView для определения индивидуальных представлений
Wizard Помогает пользователю пошагово выполнять определенные процедуры
Мобильные элементы управления
Pager Разбивает страницы на части для вывода на устройствах с небольшим экраном
PhoneLink Набирает телефонные номера на устройствах, оснащенных телефоном

Листинг 3. DataSource2.aspx


Эти примеры — лишь малая часть возможностей, предоставляемых элементами источников данных. Например, можно вызывать хранимые процедуры, указывать в качестве параметров запросов значения, получаемые из строк запросов, ввода пользователя, состояния сеанса или cookie, а также задавать, что должен использовать элемент — DataSet или DataReader. Поскольку элементы источников данных обладают функциональностью адаптеров данных, с их помощью можно даже обновлять базы данных. Думаю, к моменту финального выпуска ASP.NET 2.0 появится много материалов, посвященных элементам источников данных. Дино Эспозито (Dino Esposito) рассматривает их значительно детальнее, чем я; см. рубрику «На переднем крае» в этом номере «MSDN Magazine».

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

В ASP.NET 2.0 это выражение можно заменить на:

Помимо оператора Eval ASP.NET 2.0 поддерживает операторы XPath и XPathSelect, которые через XPath-выражения определяют местонахождение данных в XML-документах.

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

Чтобы увидеть, как работают темы и скины, добавьте в код DataSource2.aspx, показанный в листинге 3, сстроку:

Затем обновите страницу.

Теперь придадим странице совершенно другой вид. Добавим элемент и изменим директиву @ Page, указав другую тему:

Новый атрибут Theme директивы @ Page объявляет, что к странице применяется заданная тема. Кроме того, темы можно применять программно через свойство Theme класса Page. Тема (theme) — это набор скинов, а скин (skin) — набор визуальных атрибутов, применяемых к типу элемента управления. BasicBlue и SmokeAndGlass — предопределенные, или глобальные, темы в ASP.NET 2.0. Их файлы содержатся в подкаталогах каталога Microsoft.NETFramework…ASP.NETClientFilesThemes.

Вы можете определить собственные темы и скины и развернуть их в подкаталогах каталога Themes вашего приложения. Каждый подкаталог содержит файлы определенной темы, причем имя темы совпадает с именем подкаталога. Подкаталог с темой содержит один или несколько .skin-файлов и другие ресурсы, используемые темой, например, файлы изображений и таблицы стилей. Определения скинов содержатся в .skin-файлах и во многом аналогичны тэгам, применяемым для объявления экземпляров элементов управления в ASPX-файлах.

Чтобы посмотреть, как это работает, создайте подкаталог Themes в папке, где находится DataSource2.aspx. В каталоге Themes создайте подкаталог ShockingPink. В каталоге ShockingPink создайте .skin-файл и поместите в него следующий фрагмент:

Затем измените директиву @ Page в файле DataSource2.aspx:

В результате получится, несомненно, одна из самых кричащих Web-страниц, которые когда-либо создавались!

ShockingPink.skin задает внешний вид по умолчанию для элементов управления DropDownList и DataGrid. Имена .skin-файлов не обязательно должны совпадать с именами тем, к которым они относятся, хотя часто совпадают. Тема может содержать несколько .skin-файлов, а один .skin-файл может определять атрибуты для любого количества типов элементов управления. Кроме того, в ASP.NET бывают скины по умолчанию и не по умолчанию. Скин без атрибута SkinID по определению является скином по умолчанию. Скины не по умолчанию содержат атрибут SkinID, на который можно ссылаться, указывая SkinID в тэгах элементов управления.

Новые элементы управления

В ASP.NET 2.0 появится около 50 новых типов элементов управления, позволяющих разрабатывать богатый UI, не вникая в тонкости HTML, клиентских сценариев и DOM-модели (Document Object Model) браузера. На врезке «Новые элементы управления, планируемые в ASP.NET 2.0» перечислены элементы управления, которые на момент написания статьи предполагается ввести в ASP.NET 2.0 (в список не включены элементы Web Parts).

Элемент управления DynamicImage упрощает вывод на Web-страницах динамически генерируемых изображений. Раньше разработчикам приходилось писать для динамической генерации изображений собственные HTTP-обработчики или, что хуже, генерировать изображения в ASPX-файлах. Благодаря DynamicImage обе эти методики уходят в прошлое. DynamicImage в коде в листинге 4 используется, чтобы вывести круговую диаграмму. Ключевым является оператор, присваивающий биты изображения массиву ImageBytes элемента управления.

Листинг 4. DynamicImage.aspx

Элемент управления DynamicImage использует новый сервис ASP.NET 2.0 — сервис генерации изображений. Этот сервис можно применять и при динамическом формировании изображений в ASIX-файлах (еще одно новшество ASP.NET 2.0). В примерах к этой статье (доступных на сайте MSDN Magazine) имеется файл DynamicImage.asix, демонстрирующий основы ASIX-файлов. Чтобы его запустить, скопируйте DynamicImage.asix в виртуальный каталог вашего Web-сервера и откройте в браузере.

Еще один интересный и потенциально очень полезный элемент управления, дебютирующий в ASP.NET 2.0, — MultiView. Элемент управления MultiView, используемый совместно с элементами управления View, служит для создания страниц с несколькими логическими представлениями. В любой момент показывается только одно представление (с индексом, равным значению свойства ActiveViewIndex элемента MultiView). Вы можете переходить от одного представления к другому, изменяя индекс активного представления. Элементы MultiView идеально подходят для страниц, где есть ярлычки или другие элементы управления, позволяющие выбирать текущую логическую страницу.

В странице в листинге 5 элемент MultiView используется, чтобы показать два разных представления таблицы Titles базы данных Pubs: одно выводится с помощью GridView, другое — с помощью DetailsView. Переключение между представлениями выполняется выбором элемента из раскрывающегося списка. Заметьте: атрибут AllowPaging тэга позволяет просматривать записи в DetailsView.

Листинг 5. MultiView.aspx

Элементы управления GridView и DetailsView

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

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

Листинг 6. MasterDetail.aspx

Заметьте, что элементы и определяют типы полей элементов управления Gr > в элементах управления DataGrid. Поддерживаемые типы полей перечислены в табл. Особый интерес представляют типы ImageField и DropDownListField, избавляющие разработчиков от необходимости вручную писать код, который выводит в элементах управления DataGrid изображения и раскрывающиеся списки.

Создание веб-приложений без форм

Эта статья основана на предварительной версии платформы ASP.NET MVC. Данные сведения могут быть изменены.
В статье рассматривается:

  • Схема MVC (модель — визуализация — контроллер).
  • Создание контроллеров и представлений.
  • Создание форм и выполнение обратной передачи.
  • Фабрики контроллеров и другие возможности расширения.

Код доступен для загрузки по адресу: MVCFramework2008_03.exe (189 KB)

Я профессионально занимаюсь разработкой уже около 15 лет, а до этого еще лет 10 писал программы ради удовольствия. Как и большинство программистов моего возраста, я начал с 8-битных машин, а потом перешел на платформу ПК. Переходя от системы к системе, по возрастающей, я писал все подряд, начиная с игрушек и заканчивая программами для управления личными данными и контроля внешнего оборудования.
Надо сказать, вначале мои приложения объединяло одно: они все работали локально, на настольном компьютере. В начале 90-х я услышал о такой штуке как Интернет. Замаячила надежда написать веб-приложение, которое сможет вносить записи в карточку учета рабочего времени — тогда бы мне не пришлось каждый раз ехать в офис.
Эта задача оказалась, увы, неразрешимой. В моей настольно-компьютерной голове просто не укладывалось, как выполнить захват при отсутствии состояний. Добавьте к этому далеко не совершенную отладку, сервер под UNIX, на котором у меня не было доступа к корню, чертовы угловые скобки — в общем, я с позором вернулся к разработке программ для настольных компьютеров и занимался ею еще несколько лет.
От веб-программирования я держался в стороне. Разумеется, это важная сторона разработки, но я не понимал самой модели программирования. Затем появились платформы Microsoft® .NET и ASP.NET. Наконец-то мне в руки попало средство, позволяющее работать с веб-приложениями и при этом использовать практически те же приемы разработки, что применялись в локальных программах. Теперь я смогу создавать окна (страницы), привязывать элементы управления к событиям и не маяться с угловыми скобками (слава режиму конструктора!). Лучше всего было то, что ASP.NET сама решила вопрос с отсутствием состояний: появились состояния представления. Я снова стал счастливым программистом. на какое-то время.
С появлением опыта я стал более разборчивым в программировании. Я выработал для себя определенные принципы, которым следовал при работе над приложениями. Два из них выглядят следующим образом.

  • Разделение задач: не смешивай логику интерфейса с поведением элементов.
  • Автоматическое тестирование модулей: всегда проверяй, действительно ли код делает то, что он должен делать.

Эти принципы существуют независимо от используемых технологий. Разделение задач — основной способ снизить сложность проблемы. Если вы на один объект навесите сразу несколько обязанностей, скажем, расчет оставшегося времени работы, форматирование данных, построение графика, то тем самым только затрудните обслуживание приложения. А автоматическое тестирование необходимо потому, что без него невозможно создать качественный код, сохранив при этом душевное равновесие. Особенно если вы обновляете старый проект.
С веб-формами в ASP.NET поначалу очень просто работать, но вот чтобы соблюсти упомянутые принципы, мне пришлось помучиться. Веб-формы целиком и полностью сконцентрированы на интерфейсе. Основной составляющей является страница. Работа начинается с проектирования интерфейса пользователя. Вы перетаскиваете на страницу элементы управления. Возможность слепить логику приложения из обработчиков событий, размещенных на странице (как в Visual Basic® для приложений Windows®), весьма заманчива.
При этом модульное тестирование страниц выполнить очень сложно. Нельзя провести объект-страницу через весь его жизненный цикл, не задействовав всю платформу ASP.NET. Веб-приложения можно тестировать при помощи http-запросов на сервер или при помощи автоматизации обозревателя, однако такое тестирование весьма ненадежно (стоит изменить хоть один идентификатор элемента управления — и все сломается), его сложно настраивать (серверные компоненты на всех компьютерах приходится настраивать абсолютно одинаково), и, кроме того, оно отнимает много времени.
Когда я перешел к относительно сложным веб-приложениям, все эти абстракции, связанные с веб-формами (элементы управления, состояния представления, жизненный цикл страницы), стали больше мешать, чем помогать. У меня все больше времени уходило на настройку привязки данных (и на создание того безумного количества обработчиков, которое требовалось для правильной настройки). Пришлось задуматься над тем, как бы сократить размер состояния представления и ускорить загрузку страниц. Для работы веб-форм необходимо, чтобы по каждому URL-адресу существовал физический файл, а при создании динамических веб-узлов (вики-узлов, к примеру) это возможно не всегда. Создание собственного элемента WebControl (да еще и работоспособного) — процесс многоуровневый, требующий отменного понимания и жизненного цикла страниц, и принципов работы конструктора Visual Studio®.
С тех пор как я пришел в Майкрософт, у меня появилась возможность поделиться тем, что я узнал про болевые точки платформы .NET и про то, как с ними бороться. Совсем недовно я стал участником проекта Patterns & Practices Web Client Software Factory (codeplex.com/websf). Одной из обязательных составляющих приложений, создаваемых нашей группой, является автоматическое тестирование модулей. Для создания тестируемых веб-форм мы предложили использовать шаблон MVP (модель — визуализация — презентатор).
Если коротко, то в схеме MVP логика не размещается на странице. Вместо этого со страницы выполняется обращение к отдельному объекту, презентатору. Объект-презентатор выполняет все необходимые операции в ответ на действия, производимые с представлением, — обычно используя при этом другие объекты (модель) для доступа к данными, для запуска бизнес-логики и т. д. Проделав все необходимое, презентатор обновляет представление. Такой подход расширяет возможности тестирования, поскольку презентатор изолирован от конвейера ASP.NET. Он взаимодействует с представлением через интерфейс, поэтому его можно тестировать отдельно от страницы.
Схема MVP работает неплохо, однако реализовывать ее иногда приходится обходными путями. Нужен отдельный интерфейс представления, нужно большое количество функций передачи событий. Но для обеспечения тестируемости интерфейса веб-форм это, пожалуй, самый лучший вариент. Усовершенствовать его можно, только изменив рабочую платформу.

Схема MVC (модель — визуализация — контроллер)

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

  • Объединение HTTP и HTML (не надо их скрывать).
  • Тестируемость на всех уровнях.
  • Повсеместная расшияремость.
  • Полный контроль над выходными данными.

Новая платформа строится на базе схемы MVC (модель — визуализация — контроллер), отсюда и название — ASP.NET MVC. Схема MVC была придумана еще в 70-х, при разработке Smalltalk. В статье я постараюсь показать, насколько хорошо она соответствует самой природе Интернета. MVC делит пользовательский интерфейс на три разных объекта: контроллер получает входные данные и обрабатывает их, модель содержит логику домена, представление оформляет полученный результат. В контексте веб-приложений входные данные — это HTTP-запрос. Ход обработки запросов показан на рис. 1.

Figure 1 Ход обработки запроса в схеме MVC

В веб-формах этот процесс выглядит совсем по-другому. Там входные данные отправляются на страницу (в представление). Представление отвечает и за обработку входных данных, и за отображение результата. В MVC эти обязанности разделяются.
Сейчас вы, наверное, задаетесь одним из двух вопросов: либо «Ну отлично, а как это применять?», либо «Зачем мне три объекта, если раньше обходились одним?». Оба вопроса вполне осмысленны, и оба можно пояснить на примере. Мы создадим небольное веб-приложение на базе платформы MVC, чтобы продемонстрироватть ее преимущества.

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

Для начала нужно установить Visual Studio 2008 и платформу MVC. На момент написания статьи ее можно найти в составе CTP-версии расширений для ASP.NET, выпущенной в декабре 2007 года (asp.net/downloads/3.5-extensions). Вам понадобится и сами расширения, и набор инструментов MVC Toolkit — в нем есть несколько очень полезных вспомогательных объектов. Когда вы загрузите и установите CTP, в диалоговом окне «Новый проект» появится еще один тип проекта — веб-приложение ASP.NET MVC.
Этот тип проекта несколько отличается от обычного веб-узла или приложения. Шаблон решения создает для веб-приложения другой набор каталогов (см. рис. 2). В каталоге Controllers, к примеру, содержатся классы контроллеров, в каталоге Views (и во всех его вложенных каталогах) — представления.

Figure 2 Структура проекта MVC

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

Класс контроллера по размерам гораздо меньше страницы. Нам в действительности нужно только вывести его из класса System.Web.Mvc.Controller и добавить атрибут [ControllerAction] для операций. Операция — это такой метод, который вызывается в ответ на запрос того или иного URL-адреса. Операции отвечают за всю обработку, необходимую для визуализации представления. Напишем простенькую операцию, передающую имя представлению:

Операция получает имя из URL-адреса, используя параметр id (все подробности через пару минут), сохраняет его в коллекции ViewData и выполняет визуализацию представления, которое мы назвали HiThere.
Прежде чем перейти к обсуждению того, как этот метод вызывается и что он из себя представляет, я хотел бы коснуться вопросов тестирования. Помните мое замечание о том, как сложно тестировать классы веб-форм? Так вот контроллеры тестировать гораздо проще. Создавать экземпляры контроллеров (и вызывать операции) можно напрямую, безо всякой дополнительной инфраструктуры. Для этого не нужен ни HTTP-контекст, ни сервер — только инструменты тестирования. К примеру, добавим к нашему классу модульный тест Visual Studio Team System (VSTS) (см. рис. 3).
Figure 3 Controller Unit Test

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

Создание представления

Разумеется, в конечном итоге нам нужно получить какой-то HTML-код. Переходим к созданию представления HiThere. Для этого создаем в папке Views подпапку с именем Hello. По умолчанию контроллер ищет представление в каталоге Views\ (префикс контроллера получаем, убирая из его имени слово Controller). То есть, представления для контроллера HelloController должны лежать в папке Views\Hello. Теперь наше решение выглядит так, как показано на рис. 4.

Figure 4 Добавление представления в проект

HTML-код представления выглядит так:

Вам, наверное, бросилось в глаза несколько моментов. Нет тегов с атрибутом runat=»server». Нет тегов формы. Элементы управления не объявляются. Все это больше похоже на классический ASP, чем на ASP.NET. Представления MVC отвечают только за порождение выходных данных. Обработчики событий и сложные элементы управления (как в веб-формах) им попросту ни к чему.
В платформе MVC по-прежнему используется формат ASPX — этот язык удобен для создания шаблонов. Если хотите, можете даже использовать фоновый код. Правда, по умолчанию файл фонового кода выглядит так:

В нем нет ни методов Init и load, ни обработчиков событий — только объявление базового класса (кстати, базовым является не класс Page, а класс ViewPage). Для представления MVC больше ничего и не нужно. Запустите приложение, откройте страницу http://localhost: /Hello/HiThere/Chris — и вы увидите примерно то, что показано на рис. 5.

Figure 5 Успешно созданное представление MVC


Если вместо этой картинки у вас на экране появилось сообщение об исключении, паниковать не стоит. Если файл HiThere.aspx в Visual Studio определен как активный документ, нажмите F5 — Visual Studio попытается получить доступ к файлу напрямую. Поскольку в MVC контроллер должен запускаться заранее, до отображения выходных данных, просто перейти к странице не поможет. Измените URL-адрес так, чтобы он совпадал с тем, что показано на рис. 5, и все должно заработать.
Как платформа MVC определяет, что нужно вызвать операцию? В URL-адресе не было даже расширения файла. Ответ кроется в порядке передачи URL-адреса. Взгляните на содержимое файла global.asax.cs (фрагмент из него приведен на рис. 6). Табилица RouteTable содержит коллекцию объектов Route. Каждый из них описывает определенную форму URL-адреса и порядок ее обработки. По умолчанию в таблицу добавляются два объекта Route. Вот первый-то нам и нужен. В нем говорится, что если URL-адрес состоит из трех частей, то первую часть следует считать именем контроллера, выторую — именем операции, а третью — параметром ID:
Figure 6 Route Table

Именно этот объект и обеспечивает вызов метода HiThere. Помните, как выглядел URL-адрес? http://localhost/Hello/HiThere/Chris. Объект Route определил, что Hello — это контроллер, HiThere — операция, Chris — ID. Затем платформа MVC создала экземпляр контроллера HelloController, вызывала метод HiThere и присвоила параметру ID значение Chris.
Стандартный Route умеет многое, но можно создавать и собственные объекты. Допустим, я страдаю гипертрофированной вежливостью и хочу, чтобы мой веб-узел выдавал индивидуальное приветствие, как только посетитель введет свое имя. В начало таблицы маршрутизации я добавляю следующее:

Теперь, стоит открыть страницу http://localhost/Chris, — и на экране появляется мое любимое приветствие.
Как система определила, какой контроллер и какую операцию нужно использовать? Все дело в параметре Defaults. При помощи анонимных конструкций, появившихся в C# 3.0, создается псевдословарь. Параметр Defaults в объекте Route может содержать любую дополнительную информацию. Платформе MVC могут пригодиться записи, относящиеся к контроллеру и операции. Если ни контроллер, ни операция не определены в URL-адресе, платформа использует имена, указанные в параметре Defaults. Вот почему мой запрос был правильно обработан (несмотря на то, что в URL-адресе имена контроллера и операции я не указал).
Еще хочу обратить ваше внимание вот на что. Помните, новый Route мы добавляли в начало таблицы? Если поместить его в конец таблицы, система выдаст ошибку. Маршрутизация работает по принципу живой очереди. При обработке URL-адресов система маршрутизации просматривает таблицу сверху вниз, и используется первый подходящий маршрут. В нашем случае использовался бы стандартный маршрут [контроллер]/[операция]/[id], поскольку для операции и параметры ID выбраны значения по умолчанию. То есть система попыталась бы найти контроллер с именен ChrisController, а поскольку его не существует, возникла бы ошибка.

Пример побольше

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

Figure 7 Редактирование домашней страницы

Логику созданного узла можно посмотреть в коде, приложенном к данной статье. А я хотел бы остановиться на том, каким образом платформа MVC упрощает размещение вики-узла в Интернете. Я начал с проектирования структуры URL-адреса. Он должен был выглядеть так:

  • /[имя_страницы] — отображение страницы с указанным именем.
  • /[имя_страницы]?version=n — отображение указанной версии страницы (0 = текущая версия, 1 = предыдущая и т. д.).
  • /Edit/[имя страницы] — включение режима редактирования для страницы с указанным именем.
  • /CreateNewVersion/[имя_страницы] — сохранение измененной версии.

Для начала просто отобразим вики-страницу. Для этого я создал класс WikiPageController. Затем я добавил операцию ShowPage. первая версия контроллера WikiPageController показана на рис. 8. Медот ShowPage абсолютно прост. Классы WikiSpace и WikiPage представляют, соответственно, набор вики-страниц и отдельную вики-страницу (и ее редакцию). Созданная операция загружает модель и вызывает метод RenderView. Зачем тогда нужна строка «new WikiPageViewData»?
Figure 8 WikiPageController Implementation of ShowPage

Один из способов передачи данных из контроллера в представление был продемонстрирован в предыдущем примере: это словать ViewData. Словари — вещь удобная, но коварная. В них может храниться все что угодно, а технология IntelliSense® к содержимому не применяется. Словарь ViewData относится к типу Dictionary , и поэтому приходится все его содержимое преобразовывать перед использованием.
Если заранее известно, какие данные будут нужны в представлении, можно не использовать словарь, а передать строго типизированный объект ViewData. Я создал простейший объект WikiPageViewData (он показан на рис. 9). Этот объект передает в представление информацию о вики-странице и несколько методов, способных, к примеру, найти версию HTML в разметке вики-страницы.
Figure 9 WikiPageViewData Object

Итак, данные для представления определены. Как их использовать? На странице ShowPage.aspx.cs есть вот такой фрагмент кода:

Обратите внимание, что базовый класс в нашем примере относится к типу ViewPage . Это означает, что свойство ViewData, имеющееся у страницы, относится к типу WikiPageViewData, а не к типу Dictionary, как в предыдущем случае.
Разметка в файле ASPX на самом деле совершенно понятна:

Обратите внимание, что в ссылках на ViewData оператор индексации [] не используется. Объект ViewData строго типизирован, поэтому к свойству можно обращаться напрямую. Никаких преобразований при этом не происходит, так что можно воспользоваться технологией IntelliSense.
Внимательный читатель, наверное, заметил тег в коде. Да, главные страницы действительно можно использовать вместе с представлениями MVC. Более того, главная страница сама может быть представлением. Взгляните на фоновый код главной страницы:

Соответствующая разметка показана на рис. 10. В таком виде главная страница используется те же самые объекты ViewData, что и представление. Базовый класс главной страницы в нашем примере имеет тип ViewMasterPage , значит тип объекта ViewData выбран правильно. Теперь можно добавить теги DIV, чтобы настроить внешний вид страницы, заполнить список версий и, наконец, вставить заполнитель для содержимого.
Figure 10 Site.Master

Еще следует коснуться вызова Html.ActionLink. Это пример вспомогательного класса визуализации. У классов представлений есть два свойства, Html и Url. Каждый из них использует различные методы для порождения фрагментов HTML-кода. В данном случает Html.ActionLink берет объект (здесь — анонимного типа) и проводит его через систему маршрутизации. В результате получается URL-адрес, по которому определяется контроллер и операция. При таком развитии событий ссыка «Редактировать эту страницу» всегда верна — независимо от того, как изменить маршруты.
Ну и наконец, вы, наверное, обратили внимание на то, что ссылки на предыдущие версии страницы пришлось создавать вручную. Текущая версия системы маршрутизации, увы, не способна порождать URL-адреса, если используются строки запросов. В следующих версиях платформы это должно быть исправлено.

Создание форм и выполнение обратной передачи
Теперь рассмотрим операцию EditPage:

Опять же, операция эта довольно проста: она просто отображает представление на указанной странице. С представлением, показанном на рис. 11, ситуация чуть интереснее. Это файл создает HTML-форму, но тегов с атрибутом Runat=»server» в нем нет. Здесь применяется вспомогательный класс Url.Action — он создает URL-адрес, по которому форма выпоняется обратную передачу. Кроме того, несколько раз используются другие вспомогательные классы: TextBox, TextArea, SubmitButton. Ничего неожиданного они не делают, создают HTML-код для различных полей ввода данных.
Figure 11 EditPage.aspx

Одна из самых неприятных проблем веб-программирования — ошибки в формах. Точнее говоря, отображение сообщения об ошибке с сохранением введенных данных. Каждому, наверное, случалось допустить ошибку в форме из 35 полей. После этого видишь кучу сообщений об ошибках — и все приходится заполнять заново. Платформа MVC позволяет сохранять введенные данные в элементе TempData. В случае ошибки они вставляются в форму. Элемент ViewState на самом деле здорово упрощает процедуру повторного заполнения веб-форм, поскольку содержимое элементов управления сохраняется по большей части автоматически.
Было бы здорово проделать то же самое и в MVC. И тут на сцене появляется TempData — это словарь, во многом напоминающий нетипизированный словарь ViewData. Разница состоит в том, что TempData существует только во время выполнения запроса — потом он удаляется. Чтобы понять, как он используется, взгляните на рис. 12 (на операцию NewVersion).
Figure 12 NewVersion Action

Сначала создается объект NewVersionPostData. Это еще один вспомогательный объект, в свойствах и методах которого хранится содержимое передачи и частично выполняется проверка. Для загрузки объекта postData я использую вспомогательную функцию из набора MVC Toolkit. UpdateFrom — это метод расширения, использующий для сопоставления имен полей формы и имен свойств объекта метод отображения. В результате все значения полей загружаются в объект postData. Недостаток метода UpdateFrom в том, что данные из формы он получает при помощи запроса HttpRequest, а это усложняет тестирование модулей.
Первое, что проверяет NewVersion — это операция SubmitAction. Проверка считается пройденной, если пользователь, нажавший кнопку OK, действительно пытался опубликовать отредактированную страницу. Если в операции присутствуют какие-то другие значения, идет перенаправление к операции ShowPage и просто отображается исходная страница.
Если пользователь все же нажал кнопку OK, проверяется свойство postData.Errors. Выполняется несколько тестов применительно к содержимому передачи. Если ошибок не обнаружено, новая версия страницы сохраняется на вики-узле. Гораздо интереснее, если ошибки обнаружены.
В таком случает содержимое объекта PostData записывается в словарь TempData. Затем пользователь возвращается на страницу редактирования. Форма заполняется значениями, сохраненными в словаре TempData.
Сейчас вся эта процедура передачи, проверки и записи в словарь TempData довольно неприятна и слишком много всего приходится делать вручную. В следующих версиях платформы должны появиться вспомогательные методы, которые помогут автоматизировать работу, — по крайней мере проверку словаря TempData. Последнее, что нужно про него вказать: содержимое словаря TempData хранится в сеансе работы пользователя с сервером. Если сеанс завершить, TempData работать не будет.

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

Базовая версия вики-узла работает, но есть несколько мест, которые хотелось бы пригладить. Например, свойство Repository используется для отделения логики вики-узла от физического хранилища. Содержимое может храниться в файловой системе (как в моем примере), в базе данных или где-то еще. Здесь возникают две проблемы.
Во-первых, класс контроллера тесно связан с устойчивым классом FileBasedSpaceRepository. Приходится задавать значение по умолчанию, чтобы в случае отсутствия значения у свойства было что использовать. Более того, путь к файлам на диске тоже задается жестко. Он должен по крайней мере определяться конфигурацией.
Во-вторых, свойство Repository по факту является обязательным: без него объект не работает. Хорошо бы, чтобы репозиторий задавался в параметре конструктора, а не в свойстве. Но в конструктор его добавить нельзя, потому что по требованиям платформы MVC на контроллерах должны использоваться конструкторы без параметров.
К счастью, существует обработчик расширений, способный помочь в такой ситуации: фабрика контроллеров. Как следует из ее называния, фабрика контроллеров создает экземпляры объектов Controller. Нужно создать класс, реализующий интерфейс IControllerFactory, и зарегистрировать его в системе MVC. Фабрики можно регистрировать для отдельных типов контроллеров или для всех контроллеров сразу. На рис. 13 показана фабрика, созданная для контроллера WikiPageController, — она позволяет указать репозиторий в параметре конструктора.
Figure 13 Controller Factory

В этом случае решение проблемы тривиально, а полученные интерфейс позволяет создавать гораздо более функциональные контроллеры (например, контейнеры для введения зависимостей). Так или иначе, теперь у нас все данные, связанные с получением зависимости, существуют в отдельном объекте, которым без труда можно управлять.
Осталось только зарегистрировать фабрику в платформе. При помощи класса ControllerBuilder добавим в файл Global.asax.cs, в метод Application_Start, следующу строку. Добавить ее можно как до, так и после маршрутов.

Теперь фабрика зарегистрирована для контроллера WikiPageController. Если бы в проекте были другие контроллеры, они бы не смогли использовать эту фабрику, поскольку харегистрирована она только для WikiPageController. Если фабрику будут использовать все контроллеры, можно вызвать метод SetDefaultControllerFactory.

Другие точки расширения

Фабрика контроллеров — лишь одна из возможностей расширения платформы. Все описать в статье не получится, поэтому я коснусь только самых примечательных. Во-первых, если в выходных данных должен содержаться не только HTML-код (или если вы не хотите использовать другой механизм создания шаблонов вместо веб-форм), можно заменить фабрику ViewFactory для контроллера. Интерфейс IViewFactory дает полный контроль над процессом порождения выходных данных. Его можно применять для создания RSS, XML и даже графики.
Система маршрутизации, как уже отмечалось, отличается достаточной гибкостью. В ней нет ни одного компонента, присущего исключтельно платформе MVC. Каждый маршрут имеет свойство RouteHandler. До сих пор оно всегда имело значение MvcRouteHandler. Однако можно использовать также интерфейс IRouteHandler и привязать систему маршрутизации к другим веб-технологиям. В следующей версии платформы появится WebFormsRouteHandler, значит в можно будет пользоваться дополнительными технологиями.
Контроллеры не обязательно выводить из класса System.Web.Mvc.Controller. Единственное требование — каждый контроллер должен реализовывать интерфейс IController, в котором есть только один метод (Execute). А дальше вы можете делать все что угодно. С другой стороны, у базового класса Controller есть ряд виртуальных функций, и если их переопределить, можно настроить его поведение:

  • Функции OnPreAction, OnPostAction и OnError позволяют для любой операции задать параметры обработки, выполняемой перед операцией или после нее. OnError — это механизм обработки ошибок.
  • Функция HandleUnknownAction вызывается, когда URL-адрес передается контроллеру, если контроллер не модет выполнить действие, указанное в маршруте. По умолчанию этот метод выдает исключение, но вы можете его настроить на свое усмотрение.

InvokeAction — это метод, способный определить нужную операцию и вызвать ее. Он допускает настройку этой процедуры (например, можно избавиться от атрибута [ControllerAction]).
В классе Controller есть и другие виртуальные методы, но они скорее применяются для тестирования, а не для расширения возможностей. К примеру, метод RedirectToAction является виртуальным, что позволяет вывести из него класс, который в действительности не будет выполнять перенаправление. Это позволяет протестировать операции перенаправления без применения веб-сервера.

Изучение контроллеров и действий

Как вы уже поняли из главы 2, контроллер является одним из компонентов ASP.NET MVC приложения. Это класс, который содержит один или более одного открытого метода (действия), соответствующего конкретному URL-адресу. Эти действия выполняют в вашем приложении функции «клея», соединяя вместе данные, взятые из модели, и пользовательский интерфейс приложения (представление). В связи с этим важно понимать, как работают эти действия. В этом разделе вы получите лучшее понимание того, как работают методы действия контроллера, поскольку мы вкратце исследуем строение контроллера и рассмотрим, что обычно должно входить в состав метода действия этого контроллера. Но для начала давайте напомним себе, как выглядит действие контроллера. Ниже представлено действие Index нашего GuestbookController .

Листинг 4-1: Действие Index контроллера GuestbookController

Строка 1: Наследуется от Controller

Строка 4: Открытый метод действия

Наш контроллер включает в себя класс, унаследованный от класса Controller и содержащий открытые методы, которые определяют действия. В главе 2 мы упоминали о том, что все контроллеры должны быть унаследованы от базового класса Controller , но это не совсем верно – контроллеры необязательно должны быть унаследованы от базового класса Controller , но для фреймворка необходимо, чтобы контроллеры, по крайней мере, реализовывали интерфейс класса IController или они не смогут обрабатывать веб-запросы. Для того чтобы понять, как же фреймворк решает, должен ли конкретный класс рассматриваться в качестве контроллера, давайте рассмотрим подробнее интерфейс IController .

IController и базовые классы контроллера

Интерфейс IController определяет самый основной элемент контроллера – метод под названием Execute , который в качестве параметра получает объект RequestContext :

Самый простой вид контроллера мог бы реализовать этот интерфейс, а затем переписать некоторый HTML для добавления отклика.

Листинг 4-2: Реализация интерфейса IController вручную

Строка 1: Реализует IController

Строка 3: Определяет метод Execute

Строка 5: Записывает HTML для отклика

Данный контроллер реализует интерфейс IController путем определения метода Execute . Внутри этого метода мы можем напрямую получить доступ к объектам HttpContext , Request и Response . Такой способ определения контроллеров очень близок к метаязыку, но не очень полезен. Мы не можем отображать представления напрямую и прекращаем смешивать процесс отображения с логикой контроллера посредством написания HTML прямо внутри контроллера. Кроме того, мы не принимаем во внимание все полезные возможности фреймворка, например такие, как безопасность (которую мы рассмотрим в главе 8), связывание данных модели (глава 10) и результаты действий (глава 16). Мы также потеряли возможность определять метод действия – все запросы к этому контроллеру управляются методом Execute .

На самом деле маловероятно, что вам потребуется реализовывать интерфейс IController , потому что сама по себе такая возможность не особенно полезна (но такая возможность присутствует на тот случай, если по каким-то причинам вам будет необходимо пренебречь большинством других возможностей фреймворка). Чаще всего вместо этого вы будете выполнять наследование от базового класса. Существует два базовых класса, от которых вы можете унаследовать контроллер – ControllerBase и Controller .

Наследование от класса ControllerBase

Класс ControllerBase напрямую реализует интерфейс IController , но содержит инфраструктуру, необходимую для нескольких возможностей, которые мы уже рассматривали. Например, класс ControllerBase содержит свойство ViewData , которое, как вы видели ранее, может быть использовано для передачи данных в представление. Тем не менее, сам по себе класс ControllerBase не очень полезен – мы все еще не можем отображать представления или использовать методы действий. За это уже отвечает класс Controller .

Наследование от класса Controller

Класс Controller наследуется от класса ControllerBase , поэтому в него включены все свойства, определенные в классе ControllerBase (к примеру, свойство ViewData ), но в тот же время данный класс добавляет значительное количество дополнительных функциональных возможностей. Этот класс содержит ControllerActionInvoker , который знает, как выбирать метод, который необходимо выполнить, на основании URL-адреса, и определяет такие методы, как метод View , который, как вы уже видели, может использоваться для отображения представления в рамках действия контроллера. Это тот класс, от которого вы будете наследовать свои классы при создании своих собственных контроллеров (и который мы будем продолжать использовать в этой книге в дальнейшем). В большинстве случаев нет причины выполнять наследование напрямую от ControllerBase или IController , но полезно знать, что они существуют, поскольку они играют важную роль в MVC конвейере.

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

Что представляет собой метод действия

Из главы 2 вы узнали, что методы действия – это открытые методы класса контроллеров (в действительности, правила определения того, должен ли метод рассматриваться в качестве действия, несколько сложнее – мы рассмотрим эти правила в главе 16). Чаще всего метод действия возвращает экземпляр ActionResult (к примеру, ViewResult при вызове return View() ). Но методы действия не обязаны возвращать экземпляры ActionResult . Например, действие могло бы возвращать результат void и напрямую записывать код отклика (подобно SimpleController в листинге 4.2.):

Того же результата можно было бы достичь путем возврата фрагмента HTML напрямую из действия контроллера:

Так можно поступить, потому что ControllerActionInvoker гарантирует, что возвращаемое значение действия всегда будет преобразовываться в ActionResult . Если действие уже возвращает ActionResult (например, ViewResult ), то в этом случае этот метод просто вызывается. Тем не менее, если действие возвращает значение другого типа (в данном примере – типа String ), то возвращаемое значение преобразовывается в объект ContentResult , который просто переписывает HTML для добавления отклика. Выходной результат будет таким же, как и при использовании ContentResult напрямую:

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

Помимо отображения разметки или возврата представления существуют другие доступные типы результатов действий. Например, вы можете перенаправить веб-браузер пользователя на другую страницу, возвращая RedirectToRouteResult (который вы использовали при вызове метода RedirectToAction в листинге 2.7 главы 2) или возвращая содержимое других типов, к примеру, JSON (который мы рассмотрим в главе 7, когда будем изучать Ajax-функциональность).

Также для того чтобы открытые методы контроллера не являлись действиями, вы можете использовать NonActionAttribute :

NonActionAttribute является примером селектора метода действия, который может использоваться для переопределения применяемой по умолчанию технологии, при которой название метода совпадает с названием действия. NonActionAttribute – самый простой вид селектора, который не допускает доступа к методу посредством URL. Вы уже встречались с еще одним примером селектора действия в главе 2 – селектор HttpPostAttribute , который гарантирует, что действие отвечает только на запросы HTTP POST.


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

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

Теперь давайте рассмотрим, какого вида логика должна присутствовать внутри метода действия.

Событийно-управляемое программирование

В основу Windows положен принцип событийного управления. Это значит, что и сама система, и приложения после запуска ожидают действий пользователя и реагируют наних заранее заданным образом. Любое действие пользователя (нажатие клавиши на клавиатуре, щелчок кнопкой мыши, перемещение мыши) называется событием. Структура программы, управляемой событиями, изобра­жена нарис. 14.1.

Рис. 14.1. Структура программы, управляемой событиями

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

Сообщения поступают в общую очередь, откуда распределяются по очередям приложений. Каждое приложение содержит цикл обработки сообщений, который выбирает сообщение из очереди и через операционную систему вызывает подпрограмму, предназначенную для его обработки (рис. 14.2). Таким образом Windows-приложение состоит из главной программы, обеспечивающей инициализанию и завершение приложения, цикла обработки сообщений и набора обработчиков событий.

Рис. 14.2. Структура Windows-приложения

Среда Visual Studio.NET содержит удобные средства разработки Windows-npи ложений, выполняющие вместо программиста рутинную работу — создание шаб лонов приложения и форм, заготовок обработчиков событий, организацию цик ла обработки сообщений и т. д. Рассмотрим эти средства.

Шаблон Windows-приложения

Создадим новый проект (File ► New ► Project), выбрав шаблон Windows Application (рис. 14.3). После более длительных раздумий, чем для консольного приложе­ния, среда сформирует шаблон Windows-приложения. Первое отличие, которое бросается в глаза, — вкладка заготовки формы Form1.cs[Design], расположенная в основной части экрана. Форма представляет собой окно и предназначена для размещения компонентов (элементов управления) — меню, текста, кнопок, спи­сков, изображений и т. д.

Рис. 14.3. Выбор шаблона проекта

Среда создает не только заготовку формы, но и шаблон текста приложения. Пе­рейти к нему можно, щелкнув в окне Solution Explorer (View ► Solution Explorer) правой кнопкой мыши на файле Form1.cs и выбрав в контекстном меню команду View Code. При этом откроется вкладка с кодом формы, который, за исключе­нием комментариев, приведен в листинге 14.1. Представлять себе, что написано в вашей программе, весьма полезно, поэтому давайте внимательно рассмотрим этот текст.

Листинг 14.1.Шаблон Windows-приложения

ASP.NET Core: Создание серверных служб для мобильных приложений

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

Первый цикл статей можно найти здесь.

Мобильные приложения могут без труда обмениваться данными с серверными службами ASP.NET Core. Здесь можно скачать образец кода серверных служб.

В данном материале в качестве клиента используется приложение Xamarin Forms ToDoRest. Оно включает отдельные клиенты для устройств под Android, iOS и Windows. По ссылке выше вы найдёте руководство, которое поможет создать приложение (и установить необходимые бесплатные инструменты Xamarin), а также сможете скачать образец решения Xamarin. В него входит проект двух служб ASP.NET веб-API, на замену которым приходит приложение ASP.NET Core из этой статьи (со стороны клиента изменения не понадобятся).

Функции

Приложение ToDoRest поддерживает составление списков, добавление, удаление и обновление элементов To-Do. Каждый элемент наделён своим идентификатором, названием, примечаниями и свойством, которое указывает, выполнен ли элемент.

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

Коснитесь значка +, чтобы открыть диалоговое окно для добавления элементов:

Коснитесь элемента в главном списке, чтобы открыть диалоговое окно для редактирования названия, примечания и статуса выполнения, либо чтобы удалить элемент:

Этот образец по умолчанию использует сервисные службы, размещённые по адресу developer.xamarin.com, и позволяет выполнять только чтение. Чтобы самостоятельно протестировать его с приложением ASP.NET Core, которое будет создано в следующем разделе и будет работать на вашем компьютере, нужно обновить константу RestUrl . Перейдите к проекту ToDoREST и откройте файл Constants.cs. Замените RestUrl на IP-адрес вашего компьютера (это не должен быть localhost или 127.0.0.1, поскольку адрес используется из эмулятора устройства, а не из вашего ПК). Также добавьте номер порта (5000). Чтобы службы работали на устройстве, не забудьте выключить брандмауэр, блокирующий доступ к этому порту.

Создание проекта ASP.NET Core

Создайте новое веб-приложение ASP.NET Core в Visual Studio. Выберите шаблон веб-API и отключите аутентификацию. Присвойте проекту имя ToDoApi.

Приложение должно отвечать на все запросы к порту 5000. Добавьте в Program.cs .UseUrls(«http://*:5000») , чтобы получить следующий результат:

Примечание: обязательно запустите приложение напрямую, а не через IIS Express, который по умолчанию игнорирует не локальные запросы. Выполните dotnet run из командной строки либо выберите название приложения из раскрывающегося меню Debug Target на панели инструментов Visual Studio.

Добавьте класс модели для представления элементов To-Do. Отметьте обязательные поля с помощью атрибута [Required] :

Методам API необходим способ обработки данных. Используйте тот же интерфейс IToDoRepository , что и в образце Xamarin:

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

Настройте реализацию в Startup.cs:

Теперь можно перейти к созданию ToDoItemsController.

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

Добавьте к проекту новый контроллер ToDoItemsController. Он должен унаследовать свойства от Microsoft.AspNetCore.Mvc.Controller. Добавьте атрибут Route , чтобы указать, что контроллер обработает запросы, которые выполнены к путям и начинаются с api/todoitems . Токен [controller] в маршруте заменяется названием контроллера (без суффикса Controller); это особенно полезно для глобальных маршрутов. Подробнее о маршрутизации.

Для работы контроллера необходим параметр IToDoRepository; запросите экземпляр этого типа через конструктор контроллера. В среде выполнения этот экземпляр будет предоставлен благодаря поддержке платформы для внедрения зависимости.

Этот API поддерживает четыре команды HTTP для операций создания, чтения, обновления и удаления (CRUD) в источнике данных. Самая простая операция — Read (чтение), она соответствует запросу HTTP Get.

Чтение элементов

Чтобы запросить список элементов, выполните запрос GET к методу List . Атрибут [HttpGet] в методе List указывает, что это действие должно обрабатывать только запросы GET. Маршрут для этого действия — это маршрут, указанный на контроллере. Вам не обязательно использовать название действия в качестве части маршрута. Нужно лишь убедиться, что каждое действие обладает уникальным и однозначным маршрутом. Маршрутизацию атрибутов для создания конкретных маршрутов можно применять на уровне как контроллера, так и метода.

Метод List выдает код ответа 200 OK и список всех элементов ToDo, сериализованных как JSON.

Вы можете протестировать новый метод API с помощью ряда инструментов, например Postman, как показано ниже:

Создание элементов

По соглашению, создание новых элементов данных сопоставляется с командой HTTP POST. К методу Create применен атрибут [HttpPost]; кроме того, метод принимает параметр ID и экземпляр ToDoItem . Такие командные атрибуты, как [HttpPost] , могут принять строку маршрута (в этом примере ). Результат будет таким же, что и при добавлении атрибута [Route] к действию. Поскольку аргумент item будет передан в теле POST, этот параметр украшается атрибутом [FromBody] .

Внутри метода проверяется, правильно ли составлен элемент и существовал ли он ранее в хранилище данных; если ошибок нет, он добавляется с помощью репозитория. ModelState.IsValid выполняет проверку модели; это следует сделать в каждом методе API, который принимает вводимые пользователем данные.

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

Чтобы проверить добавление новых элементов, используйте Postman: выберите команду POST, которая предоставляет новый объект в формате JSON в теле запроса. Также добавьте заголовок запроса, который указывает Content-Type для application/json .

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

Обновление элементов

Изменять записи можно с помощью запросов HTTP PUT. Кроме того, метод Edit практически идентичен Create . Помните, что если запись не будет найдена, действие Edit выдаст ответ NotFound (404).

Чтобы протестировать Postman, измените команду на PUT и добавьте ID обновляемой записи в URL. Укажите данные обновляемого объекта в теле запроса.

При успешном выполнении метод выдает ответ NoContent (204), обеспечивая тем самым согласованность с существующим API.

Удаление элементов

Для удаления записей нужно сделать запросы DELETE к сервису и передать ID удаляемого элемента. После этих обновлений запросы для несуществующих элементов получат ответы NotFound , а успешный запрос — ответ NoContent (204).


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

IT Notes

четверг, 26 августа 2010 г.

Основы Asp.Net – Часть 3

В этой статье мы создадим наше первое приложение на ASP.NET.

Первое приложение ASP.NET

Перед тем как завершить эту вводную часть, давайте произведем следующую операцию: откроем файл default.htm и внесем в него следующие изменения (не забудем добавить к расширению файла ASP букву x):

Затем изменим расширение нашего файла ASP на * .aspx и запустим наше при­ложение снова. Как можно убедиться, все будет работать так же, как и раньше.

Нас можно поздравить! Мы только что создали первое приложение ASP.NET. Это было не очень сложно — достаточно было изменить расширение файла классических ASP с * .asp на *.aspx. Вывод напрашивается сам собой — то, что мы ис­пользовали в нашем файле классических ASP, используется и в ASP.NET. Одна­ко, конечно же, в ASP.NET достаточно много отличий от технологии классичес­ких ASP. Многие из этих различий (как и общие возможности ASP и ASP.NET) мы сейчас рассмотрим.

Некоторые проблемы классических ASP

Классические ASP — это очень популярная архитектура создания web-приложе­ния, однако она не лишена недостатков. Главный недостаток классических ASP заключается в том, что в них используются языки скриптов. Несмотря на всяческие хитрые приемы (например, кэширование откомпилированных скриптов для более быстрого повторного выполнения), языки скриптов — это большой проиг­рыш как в производительности (поскольку они являются интерпретируемыми), так и в возможностях (поскольку в них не поддерживаются многие технологии объектно-ориентированного программирования).

Еще одно неудобство классических ASP связано с тем, что в них код HTML смешан с кодом скриптов. В принципе, классические ASP позволяют размещать код HTML отдельно от кода скриптов, но суть дела от этого не меняется: логика представления (код HTML) не отделена от бизнес-логики (то есть от собственно исполняемого кода).

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

Некоторые преимущества ASP.NET

В ASP.NET устранены многие недостатки классических ASP. Например, в файлах ASP.NET (*.aspx) языки скриптов не используются. Вместо этого мы можем применять обычные полнофункциональные языки программирования, такие как С#, JScript.NET или Visual Basic.NET. В результате любые богатейшие возможности объектно-ориентированного программирования можно применять непосредственно в web-приложениях. На страницах ASP.NET можно использовать как типы из библиотеки базовых классов .NET, так и типы из пользовательских сборок.

Кроме того, в приложениях ASP.NET количество кода, которое приходится писать вручную, резко сокращается. Например, при помощи серверных объектов WebControls мы можем автоматически генерировать код элементов управления HTML, который будет передаваться браузеру пользователя. Другие объекты WebControls могут быть использованы для реализации проверки вводимых пользователем данных (в результате нам не нужно будет создавать браузерные клиентские скрипты вручную).

Кроме этого, применение ASP.NET предоставляет в распоряжение разработчика множество мелких, но очень привлекательных удобств. Например, создание приложений ASP.NET производится в стандартной среде разработки Visual Stu­dio.NET, возможности которой (в том числе в отношении удобства отладки) дале­ко превосходят то, что было реализовано в Visual InterDev.

Пространства имен ASP.NET

в библиотеке базовых классов .NET предусмотрено множество пространств имен, которые имеют отношение к созданию web-приложений. Эти пространства имен можно отнести к трем основным группам: основные элементы web-приложений (например, типы для работы с протоколом НТТР, типы системы безопасности и т. п.), элементы графического интерфейса (элементы управления WebForms) и web­-службы (о них речь пойдет немного позднее). Исчерпывающее рассмотрение каждой из этих групп потребовало бы нескольких отдельных книг, однако с главными типа­ми этих пространств имен мы познакомимся и поработаем на примерах. Наиболее важные пространства имен, типы из которых используются для создания приложений ASP.NET, представлены в табл. 2.

Таблица 2. Пространства имен ASP.NET

Пространство имен Описание

System.Web в этом пространстве имен определены наиболее важные типы для организации взаимодействия между браузером и web-сервером (запрос и ответ, работа с cookie, передача файлов и т.п.)

System.Web.Caching В этом пространстве имен представлены типы для поддержки кэширования при работе web-приложений

System.Web.Configuration Типы этого пространства имен позволяют настроить web-приложение в соответствии с файлами конфигурации проекта

System.Web.Security Реализация системы безопасности web-приложений

System.Web.Services В этих пространствах имен представлены типы для

System.Web.Services.Description построения web-служб

System.Web.UI Типы этих пространств имен нужны для построения System.Web.UI.WebControls графического интерфейса пользователя web-приложений

Наиболее важные типы пространства имен System.Web

В пространстве имен System.Web определен минимальный набор типов, которые позволяют организовать взаимодействие между браузером клиента и web-серве­ром. Перечень этих типов представлен в табл. 3.

HttpResponse Объекты этого класса используются для создания ответа НТТP, передаваемого web-сервером клиенту (например, страниц HTML)

Таблица 3. Наиболее важные типы пространства имен System.Web

HttpAppication Этот класс определяет члены, которые являются общими для всех приложений ASP.NET. Класс, производный от HttpAppication, определен в файле global.asax

HttpAppicationState Этот класс позволяет определять общую информацию приложения ASP.NEТ для множества запросов, сеансов и каналов передачи данных

HttpBrowserCapabilities Этот класс позволяет собирать информацию о возможностях браузера, при помощи которого клиент обращается к web-серверу

HttpCookie Обеспечивает безопасный способ для работы с множеством объектов НПР cookie

HttpRequest Объекты этого класса обеспечивают прием информации, передаваемой клиентом

HttpResponse Объекты этого класса используются для создания ответа НТТP, передаваемого web-сервером клиенту (например, страниц HTML)

Приложение и сеанс подключения пользователя

Web-приложение — это набор взаимосвязанных файлов, которые расположены в виртуальном каталоге. В ASP.NET предусмотрен тип HttpApplication, который представляет методы, свойства и события, общие для всех web-приложений. В файле global.asax определен тип Global, который является производным от HttpApplication.

С классом HttpApplication тесно связан класс HttpApplicationState. Этот класс позволяет предоставлять общую информацию приложения в совместное использование множеству сеансов подключения. Сеанс подключения (session) можно рассматривать как взаимодействие одного пользователя в данный конкретный момент с web-приложением. Например, если с нашим приложением Cars в дан­ный конкретный момент работает 20 000 пользователей, то это значит, что к нему открыто 20 000 сеансов.

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

В классических ASP понятия приложения и сеанса представлены двумя отдельными типами (Application и Session). В ASP.NET они представлены вложенными типами HttpApplicationState и HttpSessionState, доступ к которым производится через свойства Application и Session типов, производных от Page.

Создание простого, web-приложения на С#

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

Первое, что нужно сделать, — создать новый проект С#, выбрав для него шаблон WebApplication. Мы назовем этот проект FirstWebApplication.

После того как создание проекта будет завершено, перед нами откроется шаблон времени разработки. Этот шаблон действует, как обычный шаблон Windows Forms, представляя графический интерфейс создаваемого нами файла *.aspx. Главное отличие заключается в том, что мы используем элементы управления не Windows Forms, а Web Form Controls, основанные на коде HTML. Обратите также внимание, что по умолчанию этой странице присвоено имя WebForm1. Учитывая, что к этой странице будут обращаться «из внешнего мира», лучше переименовать ее в default.aspx.

Если же мы откроем Internet Services Manager, то сможем убедиться, что на сервере IIS появился новый виртуальный каталог FirstWebAppLication. Как можно убедиться, каждый файл, который мы добавим в наш проект, будет по­мещен в этот виртуальный каталог. Физически этому виртуальному каталогу будет соответствовать каталог FirstWebAppLication в подкаталоге :\Inetpub\wwwгооt.

Исходный файл * .aspx

Если мы откроем автоматически сгенерированный файл *.aspx, то найдем в нем минимальный набор тегов с единственной формой:

Управление консольным приложением

Я пишу программу, которая будет обращаться к консольному приложению, и будет выводить у себя то, что консольная выводит в консоль. Как такое сделать? чтобы не было видно консольного приложения

а не проще что-то типа лога сделать и пихать в отдельный файл? или еси так не хочешь, то просто завести массив char *log; и в него всё пихать

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

Anton Vatchenko
Самое первое, что напрашивается — переопределить файловые дескрипторы этой программы, так, чтобы она выводила не в stdout, а в файл. Но в винде это усложняется тем, что файловый объект может быть только файлом(он не может быть, скажем, FIFO трубой). Придётся извращатся с флагами. В UNIX всё проще — там можно создать фаловый обьект типа FIFO pipe и работать с ним, как с обычным файлом — ожидание того, как консольное приложение запишет что-либо в файл будет производиться автоматически; ну и тому подобные специфические операции будут происходить на уровне системы, а не приложения. В случае с виндой, придётся всё это реализовывать самому.

А если это реализуется на C под Windows? Чем хоть пользоваться? Какими функциями?

Anton Vatchenko
Смотри в сторону функции system

Предположим, надо запустить некое консольное приложение, чтобы свой вывод оно писало в файл:

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

Но, честно говоря, меня терзает сомнение, что этот метод слишком извратный, и есть более элегантное решение.

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