31.3 把输出结果显示为HTML页面
第一个示例说明了.NET基类可以从Internet上下载和处理数据。但是,迄今为止,从Internet上下载的文件都是以纯文本显示的。人们总是希望以Internet Explorer的界面样式查看HTML文件,以便可以看到Web文档的实际面貌。遗憾的是,.NET基类并不包含对Internet Explorer界面样式的控件的内在支持。我们需要编程调用Internet Explorer,或者把Web浏览器用作ActiveX控件。
使用System.Diagnostics命名空间中的Process类,可以编程打开Internet Explorer过程,导航到给定的Web页。
Process myProcess = new Process();
myProcess.StartInfo.FileName = "iexplore.exe";
myProcess.StartInfo.Arguments = "http://www.wrox.com";
myProcess.Start();
但是,上面的代码会把IE作为单独的窗口打开,而应用程序并没有与新窗口相连接,因此不能控制浏览器。
另一方面,把浏览器作为ActiveX控件,可以把浏览器作为应用程序的一个集成部分来显示和控制。Web浏览器控件相当复杂,提供了许多方法、属性和事件。
在采用这些控件时,最简单的方式就是使用 Visual Studio .NET把这个控件添加到工具箱中。为此,右击Visual Studio .NET中的Toolbox,从弹出的关联菜单中选择Customize Toolbox,打开下面的对话框。在对话框中选择COM Component选项卡,选中Microsoft Web Browser,如图31-3所示。
之后,Web Browser控件就会显示在工具箱中。然后,可以像使用其他的.NET控件一样,把它拖放到窗体上。Visual Studio .NET将自动生成把Web浏览器控件保存在应用程序窗体中所需要的所有COM 交互操作代码。下面用另一个示例(即DisplayWebPage)阐明这个技术,该示例将在一个典型的Windows窗体中显示一个从Internet上获得的Web页。
图 31-3
我们把DisplayWebPage创建为标准的C# Windows应用程序,并且把Web Browser ActiveX控件拖放到窗体上。默认状态下,Visual Studio .NET把这个控件命名为axWebBrowser1,然后,把下面的代码添加到Form1构造函数中:
public Form1()
{
// Required for Windows Form Designer support
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);
}
在上面的代码中,使用WebBrowser控件的Navigate()方法,以发送HTTP请求,显示来自给定URI的输出。该方法的第一个参数是包含给定URI的一个字符串,第二个参数用于提供各种各样的标记,以修改浏览器的行为,例如,浏览器是否把新的URI添加到历史列表中。第三个参数包含用于显示资源的目标帧(如果有)名称。第四个参数包含随请求一起发送的POST数据,最后一个参数可以发送附加的HTTP标题信息。在本例中,我们把默认值0和空字符串赋予后面的4个参数,这些参数定义为可选的参数,但是C#不支持可选的参数,因此,需要明确地给出它们。此外,还需要显式地为这些变量声明对象引用,因为它们是按引用传递的。
调用带有上面参数的Navigate()方法的效果等同于把URI键入到Internet Explorer地址栏中。这段代码是惟一需要手动添加到DisplayWebPage项目中的代码。运行DisplayWebPage,可以得到如图31-4所示的结果。
图 31-4
Web Request 和 Web Response 的层次结构
本部分详细讨论Web Request类和Web Response类的底层体系结构。图31-5显示的是相关类的继承层次结构。
图 31-5
这个体系结构不仅仅包含刚才代码中使用的两个类。实际上,WebRequest类和WebResponse类都是抽象的,不能进行实例化。这些基类提供了用于处理Web请求和响应的通用功能,这些功能独立于给定操作所使用的协议。请求总是通过某一协议(例如HTTP、FTP、SMTP等)实现的,并由为该协议而编写的派生类处理。Microsoft称之为“可插入的协议”。在前面的代码中,变量定义为对基类的引用,但是WebRequest.Create()实际上给出了一个HttpWebRequest对象,GetResponse()方法实际上返回的是HttpWebResponse对象。这个基于factory的机制在客户机代码中隐藏了许多细节,以支持基于相同代码的各种协议。
有了WebRequest.Create(),在URI中就不需要专门用于处理HTTP协议的对象。WebRequest.Create()检查URI中的协议说明符,以实例化和返回一个适当类的对象。这样代码就不必了解所使用的派生类或特定协议的信息。在需要访问协议的特定功能时,应使用派生类的属性和方法,此时要把WebRequest或WebResponse的引用转换为派生类。
有了这个体系结构,就应能使用任一通用协议发送请求。但是,Microsoft目前提供的派生类只适用于HTTP、HTTPS和FILES协议。如果要利用其他的协议,例如FTP或SMTP,则需要使用Windows API编写自己的类,或者等候某个软件厂商编写一些相配的.NET类!.NET Framework 2.0版本在发布时应可以处理FTP。