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呢?我将继续学习服务器控件编程的内容,希望能在深入学习之后对这个问题能得出一个自己的观点。

原文地址:https://www.cnblogs.com/luoyaoquan/p/2030439.html