适用于:
ASP.NET 2.0
Visual Web Developer 2005 Express Edition
摘要:学习如何将 JavaScript 与 ASP.NET 2.0 应用程序配合使用。
本页内容
简介
将 JavaScript 添加到服务器控件
执行简单的按钮翻转
设置控件焦点
使用较大的 JavaScript 函数
Page.ClientScript.RegisterStartupScript() 方法
Page.ClientScript.RegisterClientScriptBlock() 方法
将 JavaScript 放到单独的文件 (.js) 中
结论
简介
Web 开发人员一直在通过将服务器端处理和客户端处理结合使用来解决浏览器的限制。客户端的工作逻辑和应用程序进程可使基于浏览器的应用程序看起来响应更及时且更“快速”。过去,对于客户端开发来说,大多数开发人员使用 JavaScript,并将此编程语言混合到了他们知名的 Microsoft Active Server 页面与服务器端 Microsoft Visual Basic Scripting Edition 或 Microsoft JScript 代码中。现在,有了 Microsoft ASP.NET 及其提供的新模型,Web 开发人员往往想知道如何在他们的 ASP.NET 页面中正确使用 JavaScript 函数。
在先前的一篇 MSDN 文章中,我曾经介绍过如何在 ASP.NET 1.x 应用程序中有效地使用 JavaScript。不过,在 ASP.NET 2.0 简介中,您会发现完成此项任务的方法已发生了改变。因此,重新回顾一下如何更好地创建使用 JavaScript 的 ASP.NET 应用程序是很重要的。本文将介绍一些现在可用的以前 JavaScript 函数的使用方法。完成该任务有多种方法,本文将介绍各种可能的方法。本文还将通过一些简短的示例介绍一些在 ASP.NET 页面中对 JavaScript 的一些较为常见的使用方法。
将 JavaScript 添加到服务器控件
将 JavaScript 添加到位于 ASP.NET 页面中的某个特定服务器控件是非常简单的。我们以按钮服务器控件为例。如果您使用任一 Microsoft Visual Studio 2005 将 Button HTML 服务器控件(HtmlInputButton 类)拖放到某个页面中,并将其作为服务器控件运行,则应具有以下代码结构:
<input id="Button1" type="button" value="button" runat="server" />
这是一个普通按钮,可通过 ASP.NET 页面的代码分离或服务器端脚本以编程方式对其进行控制。例如,要在生成页面时指定按钮文本,只需在该元素变成 HTML 服务器控件(右键单击该控件,然后选择 Run As Server Control(作为服务器控件运行))后使用该按钮的 value 属性即可。
Visual Basic
Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Button1.Value = DateTime.Now.ToString() End Sub
C#
protected void Page_Load(object sender, EventArgs e) { Button1.Value = DateTime.Now.ToString(); }
这段代码只是在页面上提供了一个按钮,该按钮的文本为日期和时间。
需要特别注意的是,此处的 ASP.NET 页面是从生成该页面的服务器来获取时间的。因此,如果 Web 服务器位于美国中央时区 (CST -6 GMT) 的某个位置,则无论请求此页面的人位于何处,他们都将获得相同的时间。
如果想要此按钮显示查看该页面的人所在时区的时间,又该如何呢?完成此项任务的最简单方法就是在客户端使用 JavaScript。
就此列举一例,我们要将终端用户(Web 页面的查看者)的计算机时间置于一个按钮 Web 服务器控件上。以下代码显示了如何完成该任务:
Visual Basic
<%@ Page Language="VB" %> <script runat="server"> Protected Sub Button1_Click(ByVal sender As Object, _ ByVal e As System.EventArgs) Response.Write("回发!") End Sub </script> <html > <head runat="server"> <title>使用 JavaScript</title> </head> <body onload="javascript:document.forms[0]['Button1'].value=Date();"> <form id="form1" runat="server"> <div> <asp:Button ID="Button1" runat="server" Text="按钮" OnClick="Button1_Click" Font-Bold="True" Font-Names="Verdana" Font-Size="Larger" /> </div> </form> </body> </html>
C#
<%@ Page Language="C#" %> <script runat="server"> protected void Button1_Click(object sender, EventArgs e) { Response.Write("回发!"); } </script> <html > <head runat="server"> <title>使用 JavaScript</title> </head> <body onload="javascript:document.forms[0]['Button1'].value=Date();"> <form id="form1" runat="server"> <div> <asp:Button ID="Button1" runat="server" Text="按钮" OnClick="Button1_Click" Font-Bold="True" Font-Names="Verdana" Font-Size="Larger" /> </div> </form> </body> </html>
在此小段代码中,要注意按钮的一些属性在被发送到客户端浏览器之前是如何指定给服务器端的。本例中,按钮上文本的字体被更改为具有特定大小的粗体 Verdana。客户端接收到按钮的 HTML 代码后,客户端 JavaScript 即会将该按钮的文本更改为终端用户计算机上的当前时间。针对整个页面生成的 HTML 代码如下:
<html > <head><title> 使用 JavaScript </title></head> <body onload="javascript:document.forms[0]['Button1'].value=Date();"> <form name="form1" method="post" action="Default.aspx" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTY3NzE5MjIyMGRkVUxVdzEWBhD7U89t7JKIkQc6Cko=" /> </div> <div> <input type="submit" name="Button1" value="" id="Button1" style="font-family:Verdana;font-size:Larger;font-weight:bold;" /> </div> <div> <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgK394SHCAKM54rGBtsX8d2S8MO7sf02DOAiquFyBkeY" /> </div></form> </body> </html>
单击该按钮仍会出现一个回发(通过 Response.Write 命令查看),当重新呈现此页面时,按钮控件上会显示新时间。结果如图 2 所示。
在本例中,我们通过 onload 属性将一些 JavaScript 直接置于页面的 <body> 元素中。对于 onload 属性的值,我们特意指向了第一个 <form> 节(因为在 HTML 中可能会有多个 form)中名为 Button1 的 HTML 元素。
虽然使用此方法来添加一些 JavaScript 以便与 ASP.NET Web 服务器控件配合使用很简单,但是我们也可以很容易地将一个 JavaScript 命令添加到按钮本身,如以下部分代码示例所示:
Visual Basic
<%@ Page Language="VB" %> <script runat="server"> Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Button1.Attributes.Add("onclick", _ "javascript:alert('多加注意!!!')") End Sub </script> <html > <head runat="server"> <title>使用 JavaScript</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Button id="Button1" runat="server" Font-Bold="True" Font-Names="Verdana" Font-Size="Larger" Text="单击我!"></asp:Button> </div> </form> </body> </html>
C#
<%@ Page Language="C#" %> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { Button1.Attributes.Add("onclick", "javascript:alert('多加注意!!!')"); } </script> <html > <head runat="server"> <title>使用 JavaScript</title> </head> <body> <form id="form1" runat="server"> <div> <asp:Button id="Button1" runat="server" Font-Bold="True" Font-Names="Verdana" Font-Size="Larger" Text="单击我!"></asp:Button> </div> </form> </body> </html>
使用服务器控件的 attribute 属性将附加的 JavaScript 添加到控件特定的控件是一种很好的方式。本例中,通过将 Attribute.Add 属性与脚本关键字和脚本本身(两者均表示为字符串值)配合使用添加了 JavaScript。
执行简单的按钮翻转
一谈到 Web 页面上的按钮,Web 开发人员想要为按钮赋予的较为常见的功能就是翻转效果。翻转效果就是当终端用户将其鼠标置于 Web 页面的某个按钮上时(并不单击该按钮),该按钮的颜色和形状将发生改变。对于具有多个按钮的 Web 页面而言,该功能尤为有用,从使用角度而言这是很有用的,会在终端用户单击按钮之前通知其要对该按钮执行单击操作了。
在服务器控件出现之前,该操作很容易实现,现在,尽管有了服务器控件,也不是那么困难。执行类似操作的代码如下:
Visual Basic
<%@ Page Language="VB" %> <script runat="server"> Protected Sub ImageButton1_Click(ByVal sender As Object, _ ByVal e As System.Web.UI.ImageClickEventArgs) Label1.Text = "回发!" End Sub </script> <html > <head runat="server"> <title>使用 JavaScript</title> </head> <body> <form id="form1" runat="server"> <div> <p> <asp:ImageButton id="ImageButton1" onmouseover="this.src='button2.gif'" onclick="ImageButton1_Click" onmouseout="this.src='button1.gif'" runat="server" ImageUrl="button1.gif"></asp:ImageButton> </p> <p> <asp:Label id="Label1" runat="server" /> </p> </div> </form> </body> </html>
C#
<%@ Page Language="C#" %> <script runat="server"> protected void ImageButton1_Click(object sender, ImageClickEventArgs e) { Label1.Text = "回发!"; } </script> <html > <head runat="server"> <title>使用 JavaScript</title> </head> <body> <form id="form1" runat="server"> <div> <p> <asp:ImageButton id="ImageButton1" onmouseover="this.src='button2.gif'" onclick="ImageButton1_Click" onmouseout="this.src='button1.gif'" runat="server" ImageUrl="button1.gif"></asp:ImageButton> </p> <p> <asp:Label id="Label1" runat="server" /> </p> </div> </form> </body> </html>
这次我们不通过 <body> 元素将 JavaScript 指定给服务器控件,而是使用控件的 onmouseover 和 onmouseout 事件。对于每个事件,我们均指定一个 JavaScript 值。onmouseover 事件表示终端用户将其鼠标置于控件上方的操作,而 onmouseout 表示终端用户将其鼠标从控件上方移开的操作。在本例中,我们希望当鼠标置于按钮上方时会显示一张图像,而在当加载页面后与当将鼠标从按钮移开后会显示原始图像。
如果您正在直接使用该类控件,而不是像我们在 <body> 元素中使用 JavaScript 时那样在 form 中指定控件,您可以使用 this 关键字,其后紧跟您试图更改的属性。
设置控件焦点
ASP.NET 2.0 现在包括了为其中的一个 HTML 表单元素设置(光标的)焦点的功能。在 ASP.NET 2.0 之前,您必须亲自使用 JavaScript 来完成同样的任务。例如,如果您的 ASP.NET 1.x 页面中有多个文本框,则可通过在页面的 <body> 标记中使用以下代码来使页面在加载后将焦点设置为第一个 TextBox 控件。
<body onload="document.forms[0]['TextBox1'].focus();">
通过使用该构造代码,当页面被加载后,包含 ID TextBox1 的元素将获得焦点,从而使终端用户能够开始直接输入文本,而无需通过鼠标来定位焦点。
ASP.NET 2.0 通过添加 Focus() 方法使得该任务变得非常简单。现在,您可以通过下面的代码来完成对 TextBox 控件的焦点设置:
Visual Basic
Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) TextBox1.Focus() End Sub
C#
protected void Page_Load(object sender, EventArgs e) { TextBox1.Focus(); }
浏览器加载使用此方法的页面后,光标即已经被置于了文本框的内部,等待您开始键入文本。因此,您不必将鼠标移到相应的位置即可开始在表单中输入信息。Focus() 方法使您可以动态地将终端用户的光标置于指定的表单元素中(不仅仅是 TextBox 控件,而可以是从 WebControl 类派生而来的任何服务器控件)。
使用较大的 JavaScript 函数
既然我们可以在 HTML 元素内部嵌入部分 JavaScript,甚至可以以动态方式使用 JavaScript 和 Web 服务器控件,那么如何将全部 JavaScript 函数置于您的代码中呢?
可通过多种方法来完成此任务,我们将介绍几种可在 ASP.NET 代码中使用的较为常见的方法。在本文中,我们将介绍如何使用新的 Page.ClientScript 属性。在 ASP.NET 2.0 之前,您需要使用 RegisterStartupScript 和 RegisterClientScriptBlock 方法。现在,这两个方法已被淘汰。在 ASP.NET 1.x 中注册脚本的两种可能方法均需要使用一组关键字/脚本参数。由于涉及到了两个独立的方法,因此极有可能会出现一些关键字名称冲突。Page.ClientScript 属性本身就可以完成所有的脚本注册,从而使您的代码少出错。
Page.ClientScript.RegisterStartupScript() 方法
最初可用的选项之一就是使用一个可实现此功能的 .NET 类来注册脚本块。第一个是 RegisterStartupScript 方法。当您有一个想要在页面加载时启动的 JavaScript 函数时,最好使用该类。就此列举一例,在 Visual Studio 2005 中创建一个包含两个按钮的 ASP.NET 页面。Button1 和 Button2 分别为这两个按钮的 ID。然后,在 Page_Load 事件内部嵌入以下代码。
Visual Basic
Page.ClientScript.RegisterStartupScript(Me.GetType(), "MyScript", _ "function AlertHello() { alert('你好,ASP.NET'); }", True) Button1.Attributes("onclick") = "AlertHello()" Button2.Attributes("onclick") = "AlertHello()"
C#
Page.ClientScript.RegisterStartupScript(this.GetType(), "MyScript", "function AlertHello() { alert('你好,ASP.NET'); }", true); Button1.Attributes["onclick"] = "AlertHello()"; Button2.Attributes["onclick"] = "AlertHello()";
RegisterStartupScript 方法的两个可能结构如下:
-
RegisterStartupScript (type, key, script)
-
RegisterStartupScript (type, key, script, script tag specification)
在上例中,您指定了类型 Me.GetType()、关键字及包含的脚本,然后是一个值为 True 的布尔值(以便 .NET 自动使用 <script> 标记将脚本嵌入 ASP.NET 页面中)。
在 Page_Load 事件中使用该代码会在浏览器中生成以下 HTML 代码(为简明起见,已删除了一些 HTML 代码):
<html > <head><title> 使用 JavaScript </title></head> <body> <form name="form1" method="post" action="Default.aspx" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJMTM4ODA1MjE5D2QWAgIED2QWBAIBDw9kFgIeB29uY2xpY2s FDEFsZXJ0SGVsbG8oKWQCAw8PZBYCHwAFDEFsZXJ0SGVsbG8oKWRk+DQIaJpw5 A7pyhzP8dxf/JGUSbA=" /> </div> <div> <input type="submit" name="Button1" value="Button" onclick="AlertHello();" id="Button1" /> <input type="submit" name="Button2" value="Button" onclick="AlertHello();" id="Button2" /> </div> <div> <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAwK4yNWFBwKM54rGBgK7q7GGCHwBEr6DyGutQ/egvNrB3OYhCwM4" /> </div> <script type="text/javascript"> <!-- function AlertHello() { alert('你好,ASP.NET'); }// --> </script> </form> </body> </html>
使用该 ASP.NET 页面时,请注意,在页面的底部、表单 (</form>) 的最后,嵌入了一个 JavaScript 函数。
应为页面上的所有 JavaScript 指定唯一的关键字,这一点十分重要(这可通过该方法中要求的 key 参数来实现)。如果多个 JavaScript 具有相同的关键字名称,则只会在页面中嵌入第一个 JavaScript。
Page.ClientScript.RegisterClientScriptBlock() 方法
现在,我们通过使用 Page.ClientScript.RegisterClientScriptBlock 方法来创建一个更好版本的按钮翻转示例。先前的翻转按钮示例有一个问题,即当终端用户的鼠标置于按钮图像上时,必须通过单独的请求从服务器检索翻转图像。较好的翻转按钮情况是,按钮的翻转图像已经下载并存储到了浏览器的高速缓存中,以便当终端用户将鼠标置于按钮上时,会立即显示翻转图像。要完成该任务,我们必须构建一个 JavaScript 函数。以下示例介绍了该 JavaScript 函数以及如何使用 RegisterClientScriptBlock 方法将该函数置于页面中。就本例而言,代码分离只需要一个 Page_Load 事件及一个针对 ImageButton 服务器控件的按钮单击事件。
Visual Basic
Protected Sub Page_Load(ByVal sender As Object, _ ByVal e As System.EventArgs) Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), _ "MyScript", _ "if (document.images) {" & _ "MyButton = new Image;" & _ "MyButtonShaded = new Image;" & _ "MyButton.src = 'button1.gif;" & _ "MyButtonShaded.src = 'button2.gif;" & _ "}" & _ "else {" & _ "MyButton = '';" & _ "MyButtonShaded = '';" & _ "}", True) ImageButton1.Attributes.Add("onmouseover", _ "this.src = MyButtonShaded.src;" & _ "window.status='是的!请单击此处!';") ImageButton1.Attributes.Add("onmouseout", _ "this.src = MyButton.src;" & _ "window.status='';") End Sub Protected Sub ImageButton1_Click(ByVal sender As Object, _ ByVal e As System.Web.UI.ImageClickEventArgs Label1.Text = "回发!" End Sub
C#
<%@ Page Language="C#" %> <script runat="server"> protected void Page_Load(object sender, EventArgs e) { Page.RegisterClientScriptBlock("MyScript", _ "if (document.images) {" + "MyButton = new Image;" + "MyButtonShaded = new Image;" + "MyButton.src = 'button1.gif;" + "MyButtonShaded.src = 'button2.gif;" + "}" + "else {" + "MyButton = '';" + "MyButtonShaded = '';" + "}", true); ImageButton1.Attributes.Add("onmouseover", "this.src = MyButtonShaded.src;" + "window.status='是的!请单击此处!';"); ImageButton1.Attributes.Add("onmouseout", "this.src = MyButton.src;" + "window.status='';"); } protected void ImageButton1_Click(object sender, ImageClickEventArgs e) { Label1.Text = "回发!"; } </script> <html > <head runat="server"> <title>使用 JavaScript</title> </head> <body> <form id="form1" runat="server"> <div> <p> <asp:ImageButton id="ImageButton1" onmouseover="this.src='button2.gif'" onclick="ImageButton1_Click" onmouseout="this.src='button1.gif'" runat="server" ImageUrl="button1.gif"></asp:ImageButton> </p> <p> <asp:Label id="Label1" runat="server" /> </p> </div> </form> </body> </html>
使用此代码时,浏览器的 HTML 输出将如下所示:
<html > <head id="Head1"><title> 使用 JavaScript </title></head> <body> <form name="form1" method="post" action="Default.aspx" id="form1"> <div> <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTcyMTcwOTQ2NA9kFgICBA9kFgICAQ8PZBYEHgtvbm1 vdXNlb3ZlcgVCdGhpcy5zcmMgPSBNeUJ1dHRvblNoYWRlZC5zcmM7d2luZ G93LnN0YXR1cz0nT2ggWWVzISBDbGljayBoZXJlISc7Hgpvbm1vdXNlb3V 0BSl0aGlzLnNyYyA9IE15QnV0dG9uLnNyYzt3aW5kb3cuc3RhdHVzPScnO 2QYAQUeX19Db250cm9sc1JlcXVpcmVQb3N0QmFja0tleV9fFgEFDEltYWd lQnV0dG9uMXDJ4zl4FNylcdE+kep0e5wzi14T" /> </div> <script type="text/javascript"> <!-- if (document.images) {MyButton = new Image;MyButtonShaded = new Image; MyButton.src = 'button1.gif';MyButtonShaded.src = 'button2.gif';} else {MyButton= '';MyButtonShaded = '';}// --> </script> <div> <p> <input type="image" name="ImageButton1" id="ImageButton1" onmouseover="this.src = MyButtonShaded.src;window.status= '是的!请单击此处!';" onmouseout="this.src = MyButton.src;window.status='';" src="button1.gif" style="border-0px;" /> </p> <p> <span id="Label1"></span> </p> </div> <div> <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWAgLhoLy4DwLSwpnTCEKaKJJN3KmLU7TP4vwT5VSKMT+M" /> </div></form> </body> </html>
对于该输出,请注意:通过使用 RegisterClientScriptBlock,JavaScript 函数紧跟在 HTML 代码中开启元素 <form> 的后面。除了使用 RegisterClientScriptBlock 方法添加了 JavaScript 函数外,我们还添加了一些额外的 JavaScript(只是为了增添点乐趣),以便在终端用户将鼠标置于按钮上时文本会显示在浏览器的状态栏中。如图 3 所示。
对于所有此类 JavaScript 来说,最值得高兴的就是,对服务器端事件的普通回发将正常工作。在本例中单击 ImageButton 将产生一个回发,其中更改了标签服务器控件的 text 属性。
Page.ClientScript.RegisterStartupScript 与 Page.ClientScript.RegisterClientScriptBlock 之间的区别
我们已为您介绍了两种不同的可用来将 JavaScript 函数嵌入 ASP.NET 页面的方法,那么,二者之间有何不同呢?主要区别在于,RegisterStartupScript 方法是将 JavaScript 嵌入到 ASP.NET 页面的底部,恰好位于关闭元素 </form> 的前面。RegisterClientScriptBlock 方法是将 JavaScript 嵌入到页面中开启元素 <form> 的紧后面。那么,这有何不同呢?正如我们将要看到的,这有很大的不同。
就此列举一例,以下是在页面加载到浏览器时,将焦点置于该页面上的一个文本框中的方法 - 使用利用了 RegisterStartupScript 方法的 Visual Basic:
Page.ClientScript.RegisterStartupScript(Me.GetType(), "Testing", _ "document.forms[0]['TextBox1'].focus();", True)
由于在浏览器运行到页面底部并执行此小段 JavaScript 时,就已生成了页面上的文本框,并已将其放到了页面中,因此,此方法运行正常。但是,如果不按照上述方法,而编写如下代码(使用 RegisterClientScriptBlock 方法):
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "Testing", _ "document.forms[0]['TextBox1'].focus();", True)
文本框控件将不会获得焦点,且会在页面上生成一个 JavaScript 错误(如图 4 所示)。
出错的原因在于,浏览器将先遇到 JavaScript,而后文本框才会出现在页面中。因此,JavaScript 将无法找到 TextBox1。
将 JavaScript 放到单独的文件 (.js) 中
强烈建议将 JavaScript 函数放到单独的文件中(.js 文件)。一旦它们位于单独的文件中,并且是某个项目的一部分,即可使用某些曾经介绍过的方法将该文件导入到页面中。
例如,可通过以下代码将 .js 文件包括到 ASP.NET 页面中:
Visual Basic
Page.ClientScript.RegisterClientScriptBlock(Me.GetType(), "MyScript", _ "MyJavaScriptFile.js")
C#
Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "MyScript", "MyJavaScriptFile.js");
一旦将 .js 文件导入到了 ASP.NET 页面中,即可像以前一样调用任何 JavaScript 函数。如果要管理 JavaScript 函数,并将它们与其他 ASP.NET 页面的逻辑分离,这是个不错的方法。也可使用该方法很容易地在多个 ASP.NET 页面中使用相同的 JavaScript 函数。
结论
本文简要介绍了在 ASP.NET 页面中使用 JavaScript 的一些常见方法以及对 JavaScript 的一些较为常见的使用方法。需要注意的一些较为重要的提示是,要将 JavaScript 放到单独的 .js 文件中,并使用 RegisterStartupScript 和 RegisterClientScriptBlock 方法将 JavaScript 嵌入到页面中。使用 HtmlGenericControl 的功能将控件特定的 JavaScript 部署到 ASP.NET 页面中也是相当容易的。
关于作者
Bill Evjen 是 .NET 技术的积极拥护者,也是针对 .NET 的基于社团的学习创始人。自从 .NET 于 2000 年发布以来,他一直积极地致力于 .NET 方面的工作。同一年,Bill 创建了“圣路易斯 .NET 用户组”(http://www.stlnet.org) - 世界上最先创建的 .NET 用户组之一。Bill 也是“国际 .NET 联盟”(http://www.ineta.org) 的创始人,该联盟在全球拥有 400,000 多名成员。
以美国密苏里州圣路易斯为基地,Bill 是大家拥戴的 ASP.NET 和 XML Web 服务方面的作者和代言人。他所编写或参与合著的书籍达 10 余种,包括《Professional ASP.NET 2.0》、《Professional C# 2005》、《Professional VB 2005》、《XML Web Services for ASP.NET》以及《Web Services Enhancements: Understanding the WSE for Enterprise Applications, Visual Basic .NET Bible, and ASP.NET Professional Secrets》(均由 Wiley 出版发行)。除了书籍编写之外,Bill 还参与了很多会议的演讲,包括 DevConnections、VSLive 和 TechEd。
Bill 是 Lipper(一家归 Reuters 所有的公司)的技术架构师。他毕业于位于华盛顿州贝灵汉的西华盛顿大学,具有俄语学位。当不在计算机前忙于工作时,通常会在位于芬兰 Toivakka 的避暑别墅中找到他。您可通过 evjen@yahoo.com 与 Bill 取得联系。目前,其个人网络日志位于 http://www.geekswithblogs.net/evjen。