Asp.Net服务器控件编程学习记录:第一个Callback控件

实现一个完整的Ajax功能,在代码方面,需要做如下四个方面的工作:

  1. 用于实现该功能的DOM“骨架”;
  2. 页面上发送Ajax请求的javascript代码;
  3. 服务器端处理该请求并返回处理结果的代码(可能为C#或VB书写);
  4. 页面上接收服务器处理结果并作出相应反应的javascript代码。

下面从这四个方面来看第一个使用Callback实现Ajax功能的服务器控件,其功能很简单,就是实现无刷新验证输入内容是否为电子邮件格式。

首先新建一个名为“mySolution”的解决方案,包含两个Project,类型分别为Web Site和ASP.NET Server Control,命名分别为"Web"和"DDRII"。其中Web引用DDRII,新建一页面名为AjaxTest.aspx;DDRII中新建一 ASP.NET Server Control类型的Item,命名为MyCallbackControl,继承WebControl和ICallbackEventHandler,主 要的代码编写工作都在这里面。

接下来逐一实现上述4个工作。

一、生成DOM骨架,代码如下

代码
     
       
1 protected override void RenderContents(HtmlTextWriter output)
2 {
3 output.AddAttribute(HtmlTextWriterAttribute.Id, " txtInput " );
4 output.AddAttribute(HtmlTextWriterAttribute.Type, " text " );
5 output.AddAttribute( " onblur " , " ExecuteCallback(this.value,null); " );
6 output.RenderBeginTag(HtmlTextWriterTag.Input);
7 }

所做的工作就是在控件呈现内容时画了一个输入框,令其id为"txtInput",失去焦点时执行ExecuteCallback方法。

二、生成发送请求的javascript代码并放到页面上

首先拼装js代码:

代码
    
      
1 StringBuilder strCallbackScript = new StringBuilder();
2 strCallbackScript.Append( " function ExecuteCallback(argument,context) { " );
3 strCallbackScript.Append(Page.ClientScript.GetCallbackEventReference( this ,
4 " argument " , this .ClientCallbackFunction, " context " ));
5 strCallbackScript.Append( " ;} " );

发送Ajax请求的javascript主要是Page.ClientScript.GetCallbackEventReference方法生成 的,其第一个参数为相关的控件,第二个参数为向服务器传递的参数,第三个参数为客户端的回调方法名称,第四个参数为上下文。在外面包上一层作为新的方法 ExecuteCallback,减少需要理会的参数。

ClientCallbackFunction为该控件的公共属性,使用者可在属性栏看到和设置它的内容:

代码
    
      
1 [Category( " Appearance " )]
2   public string ClientCallbackFunction
3 {
4 get
5 {
6 String s = (String)ViewState[ " ClientCallbackFunction " ];
7 return ((s == null ) ? String.Empty : s);
8 }
9 set
10 {
11 ViewState[ " ClientCallbackFunction " ] = value;
12 }
13 }

发送请求的代码被拼装好后,由Page.ClientScript.RegisterClientScriptBlock方法放到了页面上。在此之前进行了检验,确认是否此代码块已经被注册过了:

   
     
1 if ( ! Page.ClientScript.IsClientScriptBlockRegistered( " call " ))
2 {
3 Page.ClientScript.RegisterClientScriptBlock( this .GetType(),
4 " call " , strCallbackScript.ToString(), true );
5 }

以上代码均在控件的OnPreRender方法内,也就是要在呈现之前执行。

三、服务器端的请求处理和结果返回

控件只要继承并实现了ICallbackEventHandler接口,就具备了处理Callback方式请求的能力。

代码
    
      
1 #region ICallbackEventHandler Members
2   public string GetCallbackResult()
3 {
4 return this .Result;
5 }
6   public void RaiseCallbackEvent( string eventArgument)
7 {
8 if (StringValidate.IsEmail(eventArgument.ToString()))
9 {
10 this .Result = " true " ;
11 }
12 else
13 {
14 this .Result = " false " ;
15 }
16 }
17   #endregion

RaiseCallbackEvent方法根据客户端传递的参数进行业务逻辑的处理,GetCallbackResult则将结果返回给客户端。

四、页面上的内容

页面上首先拖一个写的控件到上面:

代码
    
      
1 < body >
2 < form id ="formMain" runat ="server" >
3 < div >
4 < DDRII:MyCallbackControl ID ="littleCallback" runat ="server" ClientCallbackFunction ="clientCallback" />
5 </ div >
6 </ form >
7   </ body >

ClientCallbackFunction属性是可以在属性栏里设置的,这就是页面上的回调函数的名称。

   
     
< script type = " text/javascript " >
function clientCallback(text) {
alert(text);
}
< / script>

在上述四个方面完成后,这就是一个完整可以运行的使用Callback方式实现Ajax功能的服务器控件了,当然,在此之前验证用的类是必须写好了的。

代码
    
      
1 using System.Text.RegularExpressions;
2 namespace DDRII
3 {
4 class StringValidate
5 {
6 const string EmailValStr = @" \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* " ;
7
8 public static bool IsEmail( string srcStr)
9 {
10 return IsValidate(EmailValStr, srcStr);
11 }
12
13 private static bool IsValidate( string rule, string input)
14 {
15 Regex regex = new Regex(rule);
16 return regex.IsMatch(input);
17 }
18 }
19 }


用html标签加jQuery实现同样功能的代码

代码
     
       
1 < head runat ="server" >
2 < title ></ title >
3 < script src ="Scripts/jquery-1.4.2.min.js" type ="text/javascript" ></ script >
4 < script type ="text/javascript" >
5 function s(txt) {
6 alert(txt);
7 }
8 function e() {
9 alert( " Some Error occured! " );
10 }
11 $( function () {
12 $( " #txtInput " ).blur( function () {
13 $.ajax({
14 url: " Sample.ashx " ,
15 data: " content= " + escape($( " #txtInput " ).val()),
16 success: s,
17 error: e
18 });
19 });
20
21 });
22 </ script >
23 </ head >
24 < body >
25 < form id ="formMain" runat ="server" >
26 < div >
27 < input id ="txtInput" type ="text" />
28 </ div >
29 </ form >
30 </ body >
31
处理使用了Generic handler,也就是放在后缀名ashx的文件中的Sample类

代码
    
      
1 public class Sample : IHttpHandler
2 {
3 public void ProcessRequest(HttpContext context)
4 {
5 context.Response.ContentType = " text/plain " ;
6 string content = context.Request.QueryString[ " content " ];
7 if ( ! StringValidate.IsEmail(content))
8 {
9 context.Response.Write( " false " );
10 context.Response.End();
11 }
12 context.Response.Write( " true " );
13 }
14
15 public bool IsReusable
16 {
17 get
18 {
19 return false ;
20 }
21 }
22 }
可以使用自己定义的后缀名,比如“.ajax”,然后写个专门处理该后缀名的handler;接下来的事情在IIS7中很好办,在web.config中 注册一下就OK,但是IIS6比较恶心,不但要在web.config中写明是哪个handler处理这个后缀名的请求,还得在IIS6中配置,告诉 IIS6遇到后缀名“.ajax”的请求,就交给aspnet_isapi.dll去处理。

客户端得到的html两相对比,服务器控件方式实现该功能增加了许多“额外”内容,再加上服务器控件有其自身的生命周期(Callback方式只运 行该周期中一部分)。这似乎就是很多人认为在大型Asp.NET网站上使用服务器控件会影响性能的地方,不过如果完全不使用服务器控件(包括自己写的和 VS的标准控件)的话,为什么不干脆用J2EE呢?我将继续学习服务器控件编程的内容,希望能在深入学习之后对这个问题能得出一个自己的观点。

你可能感兴趣的:(callback)