Симон Робинсон - C# для профессионалов. Том II
Подробное описание этой области представлено в документации MSDN для классов HttpWebRequest и HttpWebResponse.
Асинхронные запросы страницДополнительным полезным свойством WebRequest вместо WebClient является возможность асинхронного запроса страниц. Это важно, так как в Интернете возможна достаточно длительная задержка между отправкой запроса на хост и началом получения каких-либо данных. Методы, подобные WebClient.DownloadData и WebRequest.GetResponse, не возвращают управление, пока с сервера не вернется ответ. Может оказаться нежелательным, чтобы приложение было связано с ожиданием в течение этого времени. В таком случае попробуйте воспользоваться методами BeginGetResponse() и EndGetResponse(). Они работают асинхронно. Если вызвать BeginGetResponse(), то запрос будет отправлен на хост, а метод немедленно вернет управление, предоставляя делегата типа AsyncCallback. Пока сервер отвечает на запрос, можно будет выполнять другую работу. Подробное описание этих методов можно найти в MSDN.
Отображение выходных данных в виде страницы HTML
Первый пример показывает, что базовые классы .NET существенно облегчают загрузку и обработку данных из Интернета. Однако до сих пор файлы выводились только как простой текст. В приложении желательно часто просматривать файл HTML с помощью интерфейса в стиле Internet Explorer, чтобы установить, как действительно выглядит документ Web. К сожалению, когда писалась эта книга, базовые классы .NET не включали никакой собственной поддержки для управления этими свойствами интерфейса в стиле Internet Explorer. Чтобы сделать это, необходимо либо программным путем вызвать Internet Explorer, либо воспользоваться элементом управления ActiveX WebBrowser, который существовал уже до появления .NET.
Одним из случаев, где интерфейс пользователя выводится в стиле Internet Explorer, является создание приложения C#, которое генерирует или допускает редактирование страниц HTML с последующим выводом сгенерированных страниц пользователю.
Программный запуск процесса Internet Explorer, направленного на заданную страницу Web, можно выполнить с помощью класса Process из пространства имен System.Diagnostics.
Process myProcess = new Process();
myProcess.StartInfо.FileName = "iexplore.exe";
myProcess.StartInfo.Arguments = "http://www.wrox.com";
myProcess.Start();
Однако IE при этом запускается и как отдельное окно, которое на самом деле не соединено и не находится под управлением приложения. Следовательно, хотя этот код приведен здесь для справки, такая техника не подходит для частого применения.
С другой стороны использование элемента управления WebBrowser означает, что выведенный браузер может составить интегральную часть приложения, и приложение получит полный контроль над работой браузера. Этот элемент управления достаточно развит, обладает большим числом методов свойств и событий.
Простейшим способом встроить этот элемент управления с помощью Visual Studio.NET является добавление элемента управления в панель инструментов. Для этого щелкните правой кнопкой мыши на Toolbox в VisualStudio.NET и выберите Customize Toolbox из контекстного меню, что вызывает диалоговое окно, приведенное ниже. Необходимо выбрать вкладку COM Component и щелкнуть на Microsoft Web Browser.
Элемент управления WebBrowser появится теперь в панели инструментов, можно щелкнуть та нем, чтобы поместить его на форму в приложении Windows на C#, так же, как любой другой элемент управления Windows Forms в .NET. Visual Studio.NET автоматически создает весь код взаимодействия COM, необходимый программе C# для работы в качестве клиента с этим элементом управления, чтобы можно было интерпретировать его как просто элемент управления .NET. Это будет продемонстрировано с помощью другого очень короткого примера DisplayWebPage, в котором выводится страница Web с жестко закодированным URI.
DisplayWebPage создается как стандартное приложение Windows C#, элемент управления ActiveX WebBrowser помещается в форму, как описано выше. По умолчанию Visual Studio.NET именует соответствующую переменную axWebBrowser1, и здесь будет оставлено имя по умолчанию. Затем в конструктор Form1 добавляется код:
public Form1()
// Требуется для поддержки Windows Form Designer.
InitializeComponent();
int zero = 0;
object oZero = zero;
string emptyString = "";
object oEmptyString = emptyString;
axWebBrowser1.Navigate("http://www.wrox.com",
ref oZero, ref oEmptyString,
ref oEmptyString, ref oEmptyString);
}
В этом коде используется метод Navigate() элемента управления WebBrowser, который реально посылает запрос HTTP и выводит данные заданного URI. Первый параметр этого метода является строкой, содержащей URL, куда будет совершено перемещение. Остальные параметры соответственно позволяют: задать различные флажки; указать именованную рамку, в которой должен быть выведен браузер; определить любые данные POST, посылаемые с запросом, и дополнительную информацию заголовка HTTP. Используемых по умолчанию нулевых значений и пустых строк будет в данном случае достаточно. Эти параметры задаются в элементе управления как необязательные, но C# не поддерживает необязательные параметры, поэтому нужно определить их явно. Необходимо также явно объявить объектные ссылки для этих переменных, так как они передаются только по ссылке.
Вызов метода Navigate() с параметрами, как показано выше, имеет в принципе тот же результат, как и ввод URL в Internet Explorer для перехода к странице Web. Это единственный код, который необходимо добавить в проект DisplayWebPage вручную. При выполнении этого примера будет получен следующий результат (Visual Studio.NET также использовалась для изменения текста заголовка основной формы).
Отметим, что вывод страницы Web таким образом требует только унаследованного элемента управления WebBrowser, не нужно использовать никакие классы из пространства имен System.Net.
Иерархия классов WebRequest и WebResponse
В этом разделе более подробно рассматривается архитектура классов WebRequest и WebResponse.
Иерархия наследования вовлеченных классов показана на диаграмме.
Диаграмма показывает, что иерархия содержит более двух классов, которые используются в коде. Фактически оба класса WebRequest и WebResponse являются абстрактными, и поэтому нельзя создать экземпляры этих классов. Они существуют как базовые классы для предоставления общей функциональности для работы с запросами и ответами Web независимо от протокола, используемого в данной операции. Любой такой запрос всегда делается с помощью определенного протокола (HTTP, Telnet, FTP, SMTP и т. д.) и выполняется с помощью производного класса для этого протокола. В предыдущем коде, хотя ссылочные переменные были определены как ссылки на базовый класс, метод WebRequest.Create() в действительности давал объект HttpWebRequest, а метод GetResponse() возвращал объект HttpWebResponse тоже в действительности. Почему же этого не видно в коде явно? Ответ заключается в том, что компания Microsoft предоставила механизм на основе фабрики для сокрытия деталей иерархии классов от клиентского кода. Тот факт, что требуется объект, который может иметь дело с протоколом HTTP, очевиден из URI, подставляющего в WebRequest.Create(): http://www.wrox.com. WebRequest.Create() проверяет в URI спецификатор протокола и использует это для создания экземпляра и возврата объекта соответствующего класса. Цель состоит в том, чтобы никогда не использовать конструктор для создания экземпляра объекта WebRequest; таким образом появляется в некоторой степени свобода от необходимости что-либо знать о производных классах. Следует заметить, что теория немного отказывает, если нужно использовать какие-то специальные свойства используемого протокола, которые реализованы как методы производного класса, и в этом случае необходимо выполнить преобразование типа ссылки WebRequest или WebResponse в производный класс.
Теоретически с помощью этой архитектуры можно обрабатывать отправку запросов с помощью любого из распространенных протоколов. Однако компания Microsoft в действительности написала производные классы, охватывающие протоколы HTTP и file://. Если желательно иметь дело с другими протоколами, например, FTP, Telnet или SMTP, то нужно либо воспользоваться API Windows и написать свои собственные классы (которые будут внутренне реализованы с помощью Windows API), или ждать, пока независимые поставщики программного обеспечения напишут подходящие классы .NET.
Служебные классы
В этом разделе будет представлена пара служебных классов, которые могут облегчить программирование Web при работе с двумя распространенными темами Интернета — URI и адреса IP.
URI
Uri и UriBuilder являются двумя классами в пространстве имен System (подчеркнем, что не System.Net) и оба предназначены для представления Uri. Различие между ними состоит в том, что UriBuilder создает URI по заданным строкам для его компонентов, в то время как Uri выполняет синтаксический разбор всего URI.