Teddy's Knowledge Base

Call Back Callback - 整合AjaxHepler到NBear

今天将NBear升级到v1.5.5,主要的升级一是新增了三个类EntitySerializer, OneToManyEntitySerializer, OneToOneEntitySerializer用于简化用户对序列化子件的使用,您不必再对着SerializerHelper提供给您的大堆序列化方法无所适从了。另一个重要的更新是集成了AjaxHelper - Teddy以前的Ajax实现到NBear。AjaxHelper原来的实现基于Prototype1.3.1,从Atlas beta出来起,Teddy已经很久没有更新了,因为我一直在思考AjaxHelper存在的必要性,如果存在,该突出什么。这次不是简单的Copy到NBear的目录,而是完整的集成,Ajax的实现核心也改用ASP.NET2.0内置的Callback代替prototype,主要的使用方式不变,请运行并参见下载后的源码的NBear.WebTest project的TestAjaxHelper.aspx,该页面包含了使用范例和简单说明。因为大致的使用方式没变,关于AjaxHelper的更多以前的AjaxHelper相关文章。

下载

您可以从这里下载最新版本的NBear v1.5.5

示例解析

TestAjaxHelper.aspx.cs

 1using System;
 2using System.Data;
 3using System.Configuration;
 4using System.Collections;
 5using System.Web;
 6using System.Web.Security;
 7using System.Web.UI;
 8using System.Web.UI.WebControls;
 9using System.Web.UI.WebControls.WebParts;
10using System.Web.UI.HtmlControls;
11
12public partial class TestAjaxHelper : NBear.Web.UI.Page
13{
14    protected override bool EnableAjaxCallback
15    {
16        get
17        {
18            return true;
19        }

20    }

21
22    protected void Page_Load(object sender, EventArgs e)
23    {
24    }

25}

注意Line14-20,如果希望当前page的AjaxHelper功能开启,必须像这样继承NBear.Web.UI.Page而不是默认的Page,并且重载EnableAjaxCallback属性,置为true。否则是访问不到AjaxHelper的API的。

TestAjaxHelper.aspx

 1<%@ Page Language="C#" AutoEventWireup="true" CodeFile="TestAjaxHelper.aspx.cs" Inherits="TestAjaxHelper" %>
 2
 3<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 4
 5<html xmlns="http://www.w3.org/1999/xhtml" >
 6<head runat="server">
 7    <title>Untitled Page</title>
 8</head>
 9<body>
10    <form id="form1" runat="server">
11    <div id="output1"></div>
12    <br /> 
13    <div>
14         <script language="javascript" type="text/javascript">
15            function OnComplete(content)
16            {
17                //you can deal with the return content here
18               alert(content); 
19            }

20         
</script>
21        <input type="button" value="Callback & Updater using serverside created script handler" onclick="<%= Ajax.Updater("controls/ctlHelloWorld", "output1", null, "alert")  %>" /><br />
22        <br />
23        <input type="button" value="Callback Only using clientside created script handler" onclick="Ajax.Callback('controls/ctlHelloWorld', 'param1=1&param2=22', OnComplete)" /><br />
24        <br />
25        Both Ajax.Callback & Ajax.Updater have serverside and clientside version and can be writen like these two buttons.<br />
26        <br />
27        The first param of Ajax.Callback and Ajax.Updater must be a UseControl inherits from NBear.Web.UI.AjaxTemplate, and u must override OnAjaxTemplatePreRender() and put init code in it to control what to display in the control.<br />
28        If u put code in Page_Load of this kind of controls, they will never be run.<br />
29        <br />
30        You can deal with the callback return data in custom client script function like the 'OnComplete' function in this page.<br />
31        <br />
32        The second param of Ajax.Callback can be "param1=1&amp;param2=22" like params. Please use escape() to wrap this param before pass to serverside.
33        </div>
34    </form>
35</body>
36</html>

注意这里两个Button不同的onclick设置方式,两种方式等价可选的,也就是说客户端和服务段都有Ajax.Callback和Ajax.Updater函数,该页面的说明文字作了进一步解释。点击这个页面中的按钮时,callback将被触发,调用并显示controls/ctlHelloWorld.ascx中的内容。

ctlHelloWorld.ascx

1<%@ Control Language="C#" AutoEventWireup="true" CodeFile="ctlHelloWorld.ascx.cs" Inherits="controls_ctlHelloWorld" %>
2<%# text %><br />
3<br />
4<asp:GridView ID="GridView1" runat="server">
5</asp:GridView>

注意,这里演示一个很简单的数据绑定,复杂绑定也是一样的。

ctlHelloWorld.ascx.cs

 1using System;
 2using System.Data;
 3using System.Configuration;
 4using System.Collections;
 5using System.Web;
 6using System.Web.Security;
 7using System.Web.UI;
 8using System.Web.UI.WebControls;
 9using System.Web.UI.WebControls.WebParts;
10using System.Web.UI.HtmlControls;
11
12public partial class controls_ctlHelloWorld : NBear.Web.UI.AjaxTemplate
13{
14    protected string text = "Hello World";
15
16    public override void OnAjaxTemplatePreRender()
17    {
18        TestEntity obj = new TestEntity();
19        obj.ID = 1;
20        obj.Name = "test";
21
22        GridView1.DataSource = new TestEntity[] { obj, obj, obj };
23
24        DataBind();
25    }

26
27    public class TestEntity
28    {
29        private int _ID;
30        private string _Name;
31
32        public int ID
33        {
34            get
35            {
36                return _ID;
37            }

38            set
39            {
40                _ID = value;
41            }

42        }

43
44        public string Name
45        {
46            get
47            {
48                return _Name;
49            }

50            set
51            {
52                _Name = value;
53            }

54        }

55    }

56}

这里非常关键的是Line12和Line16-24,作为AjaxTemplate的usercontrol必须从NBear.Web.UI.AjaxTemplate继承,如果需要进行试数据初始化或者数据绑定,必须重载基类AjaxTemplate的OnAjaxTemplatePreRender()函数,注意,这里不要将代码写在usercontrol的Page_Load里,否则当作为AjaxTemplate时不会被执行。

ok,示例介绍到这里,下面还是再说说AjaxHelper区别于一般的Ajax实现的设计思想!

AjaxHelper的特点

从AjaxHelper第一版开始,AjaxHelper就是以一种不太一样的形式出现的。尤其是在ASP.NET下,它使用ASP.NET的UserControl作为模版引擎,使得用户想通过ajax回调显示的内容可以直接借用usercontrol所具有的所有可视化设计、ASP.NET通用组件、尤其是数据绑定的便利,从而能够方便的将数据显示和操作分离,构成一个MVC的结构。AjaxHelper只是帮你传递模版的内容通过无刷新的异步callback获取数据,显示到页面上指定的位置或者交给用户来处理。这样就简化了传统的许多Ajax实现仅仅传递XML格式数据,或者需要在后台手工构造数据这样的非常依赖用户对数据的处理的问题。

配合NBear内置的JSON实现,更能够使得基于现在的NBear的Ajax开发,拥有更强的服务端和客户端交互能力。就像NBear框架的整体形象一样,简单易用。尤其是这次集成后的AjaxHelper,简化了旧有版本的累赘的部分,完全无须例如httpmoudule或者在页面引用某个js文件等这样的配置,用户也可以选择是否enable,更不会无故增加页面的大小和服务器处理的负担。

如果你需要Ajax效果和传统的ASP.NET控件结合使用,或为原有项目增加Ajax效果,而不是将整个项目整体构架思路都基于Atlas这样的构架重写,那么AjaxHelpler同样会是一个不错的选择。

posted on 2006-04-27 22:30 Teddy's Knowledge Base 阅读(3412) 评论(10)  编辑 收藏 网摘 所属分类: AjaxWeb Dev.Tech. ThinkingNBear

评论

#1楼 2006-04-28 08:05 NBear浣跨敤鑰?Url=涓囧垎鎰熻阿[未注册用户]

认真阅读过   回复  引用    

#2楼 2006-04-28 08:06 NBear娴h法鏁ら懓?Url=娑撳洤鍨庨幇鐔婚樋[未注册用户]

认真阅读过。
本人水平有限,努力学习中
感谢Teddy的辛苦工作
  回复  引用    

#3楼 2006-04-28 09:39 蛙蛙池塘      

最近用Ajaxhelper和ajax.net做一个程序,ajaxhelper不错,不过用户控件里的grid控件等不支持分页,也不支持一个页多歌ajaxtemplate和嵌套的ajax模板,实在让人郁闷。是不是我还不会用呀。ajaxhelper能不能想ajax.net那样调用服务端的函数呀,还是只能加载用户控件呀。   回复  引用  查看    

#4楼[楼主] 2006-04-28 09:56 Teddy's Knowledge Base      

@蛙蛙池塘

现在集成到NBear之后,主要的用法和原来一样还是只能调用usercontrol,不过,还是可以使用asp.net内置的callback来调用服务端方法呀。但是你说得自动分页,如果要支持的话只能提供新的grid控件,用内置的grid的话不能再用它的分页功能,只有自己来控制。

我不知道你说的“不支持一个页多歌ajaxtemplate和嵌套的ajax模板”是什么意思,AjaxHelper只是提供一个调用接口返回usercontrol的内容,怎么使用和发挥它的作用还是由用户来控制,在usercontrol中同样可以方便的再调用其它的ajaxtemplate,一个页面上调用不同的多个ajaxtemplate也是一样可以做到的。
  回复  引用  查看    

#5楼 2006-06-01 06:26 学习.NET      

请教一个问题,本来是给您留言的,但留言一直无法提交,所以就写到这里了,如果您觉得不妥,可以立即删掉,谢谢.

1、一个基类。
为了便于说明问题,放到一个具体的应用场景中,这是一个数据访问层对象的基类.用于得到单个实体类或实体类集合,如OrderInfo及List<OrderDetailInfo>
public abstract class DataAccessObjectBase<TDomainObject> where TDomainObject : new()
{
// 此方法可以认为没有
public abstract void LoadDomainObjectInfo(TDomainObject domainObject, System.Data.IDataReader dr);
// 在下面的方法中调用此方法
public virtual void LoadDetailObjectInfo<TDetailObject>(TDetailObject detailObject, System.Data.IDataReader dr)
{
throw new Exception("The method or operation is not implemented.");
}

/// <summary>
/// 返回当前实体类的子对象,如订单类,则返回的是订单的订单明细
/// </summary>
/// <typeparam name="TDetailObject"></typeparam>
/// <param name="id"></param>
/// <returns></returns>
public List<TDetailObject> SelectDetailObject<TDetailObject>(System.Guid id) where TDetailObject : new()
{
Database db = DatabaseFactory.CreateDatabase();
DbCommand cmd = db.GetStoredProcCommand(SelectDetailObjectStoredProcedureName);
// 为代表存储过程命令的参数赋值
DataAccessHelper.PopulateIdParamter(db, cmd, id, ObjectId);

List<TDetailObject> domainObjectList = new List<TDetailObject>();

IDataReader dr = db.ExecuteReader(cmd);
while (dr.Read())
{
TDetailObject detailObject = new TDetailObject();
// 这个方法需要子类实现
LoadDetailObjectInfo<TDetailObject>((TDetailObject)detailObject, dr);

domainObjectList.Add(detailObject);

}

return domainObjectList;
}
}
2、一个具体的数据访问对象
public class OrderDao : DataAccessObjectBase<OrderInfo>
{
public override void LoadDetailObjectInfo<TDetailObject>(TDetailObject detailObject, IDataReader dr)
{
// 我想在这里直接操作一个具体的实体类,如OrderInfo,而不是一个类型参数TDetailObject,应该如何写?
// 我感觉从语法上来说不行,不知有没有迂回的办法。
LoadAdminObjectInfo.LoadOrderItemInfo(detailObject, dr);
}
}
3、一个辅助对象,用于具体的数据访问对象。
public class LoadAdminObjectInfo
{
public static void LoadOrderItemInfo(OrderItemInfo orderItem, System.Data.IDataReader dr)
{
orderItem.OrderItemId = (System.Guid)dr["OrderItemId"];
orderItem.OrderId = (System.Guid)dr["OrderId"];
orderItem.LocalId = (System.String)dr["LocalId"];
}
}


问题:
具体的数据访问对象中的这个方法:
public override void LoadDetailObjectInfo<TDetailObject>(TDetailObject detailObject, IDataReader dr)
{}
我应该如何实现才能直接操作一个 具体的数据访问对象, 而不是一个类型参数TDetailObject?


  回复  引用  查看    

#6楼[楼主] 2006-06-01 06:58 Teddy's Knowledge Base      

@学习.NET
你的留言放在这个帖子确实不合适,和你问的问题完全不相干!

对于于你的问题:
如果希望一个method可以执行,只需要他的参数符合它允许的参数类型,如你这里的public static void LoadOrderItemInfo(OrderItemInfo orderItem, System.Data.IDataReader dr),第一个参数你传入的值必须为OerderItemInfo才能被接受,那么,你如果传入一个TDetailObject detailedObject类型,则要保证detailedObject可以被转换到OrderItemInfo类型。

可选的办法有:

1、调用LoadOrderItemInfo(OrderItemInfo orderItem, System.Data.IDataReader dr)时,将TDetailObject detailedObject显式转换为OrderItemInfo类型;

2、将LoadOrderItemInfo(OrderItemInfo orderItem, System.Data.IDataReader dr)的第一个参数类型改为object,内部再转换为OrderItemInfo;
  回复  引用  查看    

#7楼 2006-10-24 12:32 ssss[未注册用户]

@Teddy's Knowledge Base
ssss
  回复  引用    

#8楼 2006-11-07 01:00 MK2      

@Teddy's Knowledge Base
呵呵,原来你使用UserControl来返回HTML实现Ajax比ScottGu的“Cool UI Templating Technique to use with ASP.NET AJAX for non-UpdatePanel scenarios " 这篇文章还要早呢,呵呵,强悍`````不知道你以后会怎样对待Asp.net Ajax和NBear上的AjaxHelper呢?继续强化它?还是建议我们使用Asp.net Ajax?

还有,这篇文章标题中的AjaxHelper单词写错啦```嘿嘿,我都是忘记了Help怎样写,然后看照抄你的标题,才发现的,呵呵。。。。。继续关注NBear````
  回复  引用  查看    

#9楼[楼主] 2006-11-07 07:00 Teddy's Knowledge Base      

@MK2
谢谢支持~~我在asp.net1.1的早期就提出了这个思路,当时就提供了独立的asp.net1.1版本和通用的asp/php等都可以用的版本。

这种形式实现Ajax效果的好处有不少:
1、对页面增加的开销小(atlas会使页面变大好几十K)
2、学习曲线低,无需特别学习,看两分钟就会了
3、可以使用asp.net标准控件来承载和绑定数据

当然,缺点是没有atlas这样的框架那样灵活,和有丰富的控件支持。

大家可以根据需要选择用哪个,甚至,也可以同时使用。
  回复  引用  查看    

#10楼 2008-09-22 17:39 fansunny[未注册用户]

我想请教一下,我想把实体数组转成Json数据怎么处理,我没看到这三个类EntitySerializer, OneToManyEntitySerializer, OneToOneEntitySerializer   回复  引用    




发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 386985




相关文章:

相关链接: