技术开发 频道

用jQuery、ASP.NET与Ajax实现CRUD网页

  【IT168 技术文档】jQuery是一个轻量级的19KB开源JavaScript库,它简化了客户端的编程,也包括CSS编辑。由于jQuery支持所有主要浏览器,所以它能为客户端执行代码提供强而有效,用途广泛的API。jQuery特别吸引人的一点在于它的研发者非常了解客户端的操作需求,而且想为人们提供一种支持所有这些需求的API。

  在这篇文章中,我们会介绍如何用jQuery以及服务器端代码和ASP.NET创建典型CRUD公司网页。该页面将利用服务器端进程,面向服务架构(SOA),ASP.NET验证器,用于ASP.NET的Ajax和jQuery来创建应用程序。

  当用户请求该页面的时候,首先显示出的是客户列表。当用户选取了一个客户后,页面会使用ScriptManager调用一个Web Service,这个服务会在传送一个Customerld后返回一个Customer对象。使用jQuery的客户端代码随即将对象的数据移送到页面要素。用户完成更改后,jQuery会被用来检索此更改并将更新后的Customer对象返回给Web Service,该服务就会更新数据库。在此期间,ASP.NET 验证器生成的客户端代码将被用来检查这一数据。由始至终,页面都不会回传。

  把这些技术结合起来的好处是多方面的:程序响应更迅速,客户端可执行的进程数增加,服务器进程减少从而减少网络流量。所有应用的运行速度都增快,且占用的资源更少。

  除了创建这个应用,我们还可以看看其他在ASP.NET中使用jQuery的例子。

  首先要下载若干文件为当前Visual Studio添加对jQuery的支持;例如,使用jQuery的时候要使用IntelliSense。

  配置页面

  在网页或ASP.NET项目中使用jQuery,我们要在项目中复制包含了jQuery库及其IntelliSense支持的两个文件。这里我们将JavaScript代码文件保存在js文件夹中,因此在该文件夹中我们可以再创建一个jquery子文件夹,然后将那两个文件放入该子文件夹中。

  对于任何你想使用jQuery的页面,都要从.ASPX源码处链接到jQuery库。如果你在页面大部分地方都将使用jQuery,那么你应该为主页面添加此链接。

  链接添加有两种方法可选。如果所有jQuery代码都在浏览器完成<form>要素的起始标签进程后执行,那么你可以在页面中添加ScriptManager,并为其添加一个对jQuery库文件的附注,如图所示:

  如果是要在<form>标签出现前执行jQuery代码,那应该为<head>要素添加一个<script>标签,就像这样:

<script type="text/javascript"  
src
="js/jquery/jquery-1.3.2.js" />

  生成该标签最简单的方式就是将jQuery文件从Solution Explorer中拖出来,放入<head>要素中。

  完成这一更改后,可以对其进行测试,看是否已经通过为.ASPX文件添加这一“Hello,World”代码成功完成页面设置,并能显示该页面:

<script type="text/javascript">        
        $("aspnetForm").ready(function()          
         {            
            alert("Hello, world");          
         }        
        );
</script>

  如果你已经启用Forms Authentication,且正在用主页面作为登录页面,那么互联网信息服务器和VS开发服务器之间可能出现一些异同。开发服务器使用ASP.NET运行时来处理所有文件请求,包括对于JavaScript文件的请求。由于ASP.NET运行时授予你安全设置,所以,如果你将匿名用户锁在此网页之外,那么登录页面将无法访问你的jQuery文件;IE浏览器会生成一个无效且不可调试的运行时错误信息。虽然互联网信息服务器托管应用的时候,这一现象并不会造成什么问题,但是若要支持开发服务器中的调试,就需要将JavaScript文件夹配置成允许匿名用户访问。

  如果你用ScriptManager为jQuery库添加一个附注,就会丧失VS提供给jQuery的IntelliSense支持。寻回这一支持的唯一办法是,为每个要使用jQuery的页面添加一个引用了jQuery库的脚本标签。不过,你必须添加时注意不要在只有两个脚本标签下载该jQuery库的时候就结束页面。可使用此代码:

<% if False then %>  
  
<script type="text/javascript"    
  src
="js/jquery/jquery-1.3.2.js" />
<% End if %>

  或者,你可以为每个页面添加一个链接到jQuery库的脚本标签。

  服务器部分

  用于此部分示例的页面非常简单:在Northwind数据库中一个显示所有客户的列表框,一个显示所有选定客户的标签,一个显示且让用户更新ContactName的文本框,以及一个触发更新的HTML按钮。现实中的页面肯定更复杂一些,但是此示例足以阐述利用这三项技术的架构了。

  由于用户必须从服务器对页面发出请求,所以你应该使用标准服务器端ASP.NET进程,在发送给用户前尽可能多的在页面中放入数据。虽然jQuery对此不做要求,但是笔者曾使用过Entity Framework和Entity控件来填充列表框。对于这个页面,无需进行额外添加。

  但是笔者需要创建两个Web服务:一个是GetCustomer,它在传递了客户ID后,返回一个Customer对象;另一个是UpdateCustomer,在传递Customer对象后,依据控件的属性值更新数据库。可以用.ASMX文件或WCF类创建这些服务。使用.ASMX文件比使用WCF所需的配置更改要少,因此我们使用一个名为NorthwindCustomer.asmx的.ASMX文件在此作示例。

  为了将.ASMX服务配置成可从客户端调用的服务,你只需取消包含在类中ScriptService的默认属性。如果你要创建的是一个网页,而非ASP.NET项目,那么你还要确保是否在Namespace中包含了.ASMX代码文件中的代码。此外,还需以.ASMX文件的沿用属性指定Namespace。

  无论是使用.ASMX文件还是WCF类,都需要指定ScriptManager Services集合中的.ASMX或.SVC文件。完成这些后,就可以转向客户端代码了。

  检索ASP.NET控件

  当用户在列表框中选定一个客户,列表框点击事件中的代码必须调用Web Service上的GetCustomer方法。没有jQuery的话,添加事件处理程序意味着追查那些用于列表框的HTML要素以及添加一个新的Onclick属性。在其他情况中,这样就无法将进程代码从用户界面里分离。

  而使用jQuery的话,该进程就不需要向HTML要素中添加任何事物。相反,你的代码会对该要素进行检索,并将其函数绑定到控件上。要检索要素的附注,可使用圆括号中的jQuery选择器。此选择器是CSS选择器和XPath位置路径的结合体。该选择器通过设置为ListBox1的ID属性寻找所有要素:

  $("#ListBox1")

  一旦检索完要素的引文,就可以调用检索要素上执行操作的jQuery函数。举例,事件名称被传递后,bind函数会将事件处理程序附加到一个控件上,而事件被触发后,函数就会被运行。此示例绑定的就是用户点击列表框后,会显示"Hello,World"的函数:

  $("#ListBox").bind("click", function(e) {

  alert(
"Hello, World");

  });

  使用bind方法的好处之一是,将一个事件附加给一个控件的操作可完全从用户界面的代码中分离。所以我们可以将此代码放入单独的JavaScript文件中,而不是页面中。

  要想融合ASP.NET技术,还需要解决ASP.NET从控件ID属性生成要素ID属性的方式。虽然有多种方式可以解决这个问题,不过其中却有两种方法可减少工作量。

  第一种方法是使用.ASPX文件中嵌入的服务器端代码来返回数值,控件创建的要素ID属性会使用该数值。此数值可在控件的Clientld属性中找到。下面的代码展示了这一技巧:

  $("#").bind(...

  另一种替代方法是使用不同的选择器,该选择器可以让你通过指定属性和属性值的方法找到控件。使用此技巧的话,仍然可以根据要素ID属性进行明确搜索。不过,你可以使用以jQuery结尾的运算符检查ID属性的最终字符,而不是检查整个ID属性。不要考虑ASP.NET对控件ID所做的更改,由此产生标识符通常都以下划线开头,以控件服务器端ID结尾。这一代码同样也能查找可对ID属性为ListBox1的控件作出响应的要素:

  $("element[id$='_ListBox1']").bind(...

  在此文中,我们只使用前一种方法。如果使用Microsoft .NET Framework 4,则还有第三种选择:Clientld属性可写,因此用户可以控制控件属性。

  检索数据

  ListBox的点击事件调用的函数必须调用GetCustomer Web Service。因为我们在ScriptManager中指定了服务,所以可通过名称调用GetCustomer服务,为ListBox发送当前值。调用该服务的时候,还要发送两个函数的名称,一个是Web Service返回时被调用的函数——CustomerRetrieved,另一个是Web Service返回错误值时被调用的函数——GenericFailure。在绑定到要素点击事件中的函数中,变量指向该ListBox。绑定ListBox点击事件以及调用Web Service的代码应该是这样:

  $("#").bind("click", function(e) { NorthwindCRM.NorthwindCustomers.GetCustomer(this.value, CustomerRetrieved, GenericFailure);});

  我们不需要使用ScriptManager的函数调用Web Service;jQuery包含可调用Web Service的Post函数。它相当于对GetCustomer方法的调用,可以处理可能被返回的XML文档,其代码如下:

  $.post("NorthwindCustomers.asmx/GetCustomer", false, function(xml) { CustomerRetrieved(xml); }, "string");

  就个人而言,笔者觉得 ScriptManager功能更易于使用。不过,如果你使用的是ScriptManager和jQuery,就意味着要将这两种代码结合起来应用于页面,其代码量肯定多一些。如果不使用ScriptManager来支持其他Ajax功能,而且又没有将ScriptManager放置到主页面,那么它就会出现在每个页面中,因此有必要放弃ScriptManager,转而使用jQuery的Post函数

  更新页面

  在CustomerRetrieved函数中,笔者想对显示数据的页面要素进行检索,然后用Customer对象上的属性值对其进行更新。这样就引出jQuery的另一个性能:寻找所有匹配要素的选择器。jQuery函数旨在处理所有被选择器检索过的控件。以此前例子为例,用自己提供的ID属性绑定所有要素的点击事件。

  要想为选择器检索的所有要素设置值属性,可以把数据发送到jQuery的val函数。在这个例子中,就查找了CustomerTextBox,并将其值属性设置为Customer对象的ContactName属性:

function CustomerRetrieved(cust)    
{          
   $(
'#<%=Me.CustomerNameTextBox.ClientId%>').val(cust.ContactName);    
}

  不过,并非所有控件都生成一个带有值属性的要素。例如,Label控件生成的Span要素就是在标签内带有Label文本:

<span id="ctl00_MainPlaceHolder_CompanyIdLabel">
ALFKI
</span>

  在有Span要素的情况下,笔者不想更新值属性,而想更新其文本属性,它的文本属性相当于DOM的innerText属性。况且,jQuery具备一个Text函数,该函数可以设置所有被检索要素的内部文档。此示例查找的是CompanyLabel控件,并将其内部文档设置成客户对象的CompanyName属性:

$('#<%=Me.CompanyIdLabel.ClientId%>').text( cust.CompanyName );

  更新服务器端数据

  页面上的HTML按钮可以用来调用DoUpdate函数,该函数会把数据发回给UpdateCustomer Web Service。虽然我们可以使用jQuery的bind函数将事件处理器附加到按钮的点击事件中,但是我们只会设置按钮的单击属性,和标准JavaScript客户端代码一样,用来调用DoUpdate函数:

<input id="UpdateButton" type="button" value="Update"         onclick="return DoUpdate()" />

  在DoUpdate函数中,代码生成了NorthwindCustomer对象的实例,并从页面要素对其属性进行设置。该函数的开始部分如下:

  function DoUpdate() {

  var cust
= new NorthwindCustomer();

  cust.CompanyName
= $('#').text();

  cust.ContactName
= $('#').val();

  为了再次调用UpdateCustomer Web Service方法,笔者使用ScriptManager函数——并发送该方法所需的Customer对象。和之前一样,如果方法运行完整,就发送函数名称来调用;如果出错就发送方法调用。其代码如下:

  NorthwindCRM.NorthwindCustomers.UpdateCustomer( cust, CustomerUpdated, GenericFailure);

  为了扩展该页面,使其支持插入和删除操作。可以要求其他按钮,客户端代码和Web Services。

  验证数据

  ASP.NET验证控件可自动生成客户端代码,而且客户端代码可以选择性地添加到CustomerValidator。最有效的方法是从DoUpdate事件处调用该代码,如果其中一个验证器失效,就跳过更新。好在ASP.NET页面为该页面添加了一个ValidatorValidate的函数,发送客户端验证器的时候,它可以调用控件的客户端代码。如果验证失败,会显示控件的ErrorMessage,且验证器的isvalid属性会被设置为False。

  使用客户端验证代码的第一步是找到页面的验证控件。必须将每个验证器发送到ValidateValidator函数,然后检查器isvalid属性。如果有任何验证器失效,该函数必须进行标注以防止进程继续。

  虽然jQuery拥有大量函数,以及大量插件,但笔者不清楚具体哪个函数可以做什么。幸好,如果jQuery具备一个你需要的函数,你就可以使用它的每个函数。每个函数都以你自己函数执行一次。在这些函数中,关键词将指示当前要素。

  在客户端,Validator控件和Span要素一样呈现出来。下列代码中的选择器被放置在DoUpdate函数中,它首先用Validator结尾的ID属性找出所有Span要素。然后,该代码调用了ValidatorValidate方法用于每个验证器,并检查了isvalid属性,还设置了一个isValid标记。最后,如果验证器失效,代码会跳过更新:

  var isValid = true;

  $(
"span[id$='Validator']").each(function() {

  ValidatorValidate(
this);

  
if (!this.isvalid) { isValid = false }; });

  
if (isValid) {

  ..update code..

  管理页面外观

  虽然本文的重心放在典型的CRUD操作上,但是研发jQuery的目的主要是支持CSS控制。

  在DoUpdate函数中,如果操作成功,UpdateCustomer Web Service会返回字符串"OK",反之则返回出错信息。当Web Service方法将信息发送到页面标签的时候,CustomerUpdated函数会被调用:

  function CustomerUpdated(msg) {

  
if (msg == "OK") {

  $(
'#').text("Update successful");

  }

  
else {

  $(
'#').text(msg); }

  }

  不过,错误信息应该是被高亮度显示出来。该代码将CSS类属性设置为高亮度显示:

  else {

  $(
'#').text(msg);

  $(
'#').addClass("ErrorStyle");

  }

  本文结合了Ajax,Web Service,服务器端编程以及jQuery多种技术。目的是创建响应更快,运行更快速的商业应用,从而减少服务器的负荷,减少网络流量。

  (凡署名“IT168”的稿件均为本站原创,请在转载时注明出处及作者。非上述媒体稿件均系转载,转载目的在于传递更多信息,并不代表本网赞同其观点和对其真实性负责。转载者自负版权等法律责任。)

0
相关文章