Although ajaxpro is an older component, the implementation ideas and source code are still of great reference value. Next, through this article, I will introduce to you how to write lightweight ajax components 02--a brief analysis of AjaxPro. Interested friends can refer to the following
Preface
The previous article introduced the implementation on the webform platform Some ways of ajax and implement a base class. In this article we look at an open source component: ajaxpro. Although this is an older component, the implementation ideas and source code are still worth learning. Through the introduction in the previous article, we know that calling the page object method is achieved by reflection. The key is the entire processing process, including reflection calling method, parameter mapping, etc. Ajaxpro not only helps us implement this process in the background, but also encapsulates the request calling methods in the foreground, such as ajax-related methods. You can use ajaxpro methods to send asynchronous requests without the need to encapsulate js yourself or use a js library. Next, we will briefly analyze this component.
1. How to use ajaxpro
Let’s first look at how to use this component.
1. Register AjaxHandlerFactory
Make the following configuration in web.config:
1 2 3 |
|
Simply put, the requested url complies with ajaxpro/*. ashx format will be processed by AjaxHandlerFactory, which is a factory class that implements the IHandlerFactory interface and is used to obtain the IHandler handler. The format of type is: "Name control. Class name, assembly name".
2. Register in the page class Page_Load event
1 2 3 4 |
|
We pass the Type of this page object to the ResisterTypoForAjax method. This method is used to register the script in the foreground. Specifically The RegisterClientScriptBlock of the current Page object will be called to register, so there must be a
in the .aspx file, otherwise the script will not be registered. (Type is passed here, but it can actually be done without passing it. This type can also be obtained internally through HttpContext.Current.Handler.GetType().BaseType)3. Mark the method with AjaxMethod
1 2 3 4 5 |
|
AjaxMethod is a tag attribute, indicating that this method is used to process ajax requests, and it is ultimately executed through reflection; it has several constructor pairs, and for some data that needs to be cached, the cache time can be set; If our request does not need to use Session, we can set HttpSessionStateRequirement; if the request needs to be asynchronous, such as requesting a time-consuming web service, we can also set the handler to asynchronous state.
The return value of a method can be a simple type or a complex type; for example, the collection type obtained in the foreground is an array.
4. Front-end call
The configuration and use of the back-end are very simple. Next, let’s see how the front-end initiates a request.
1 2 3 4 5 6 7 |
|
Here AjaxProNamespace is the namespace where the page class is located, AjaxProPage is the name of the page class, and GetList is the marked method. Why can it be written like this? As mentioned earlier, ajaxpro will register the script in the foreground, and it will generate the following script based on the relevant information of our page object, so we can call it like this without having to write js ourselves or use the jquery library method.
1 2 3 4 5 6 7 8 9 10 |
|
The parameters of GetList correspond to the parameters of the background method. The type must be convertible, otherwise the call will fail. The last parameter is the callback function. The parameter of the callback function is an object that encapsulates the return result. Its value attribute is the value returned after successful execution. For example, the above returned object is an array object. Its error includes failure information.
Note that the commented out part above is the method of synchronous request, which is often not what we want. I have seen someone use it incorrectly.
2. Principle of ajaxpro processing requests
The main focus here is on the process of components processing ajax requests, and other auxiliary functions will not be introduced.
1. Generate auxiliary scripts
In the Page_Load event we called AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxProPage)); to register the required scripts. We noticed that the following script was introduced on the front page:
That is, each page will initiate these requests. These are all files ending in .ashx, but they are actually all js code; some of these js are nested inside dll as resources, and some are automatically generated. They mainly encapsulate ajax request-related methods and allow us to use: Namespace. Page class name. Tag method name is used to call the method. Why use .ashx instead of .js? Because as a resource file inside the component, the .js file cannot be requested directly from the outside, but the .ashx can be intercepted, and then the content is output using Response.Write.
如果每次都生成和发送这些脚本的效率是很低的,ajaxpro内部的处理是判断请求头的If-None-Math和If-Modified-Since,如果两个都和缓存的一样,就返回一个304状态码。所以,客户端只有首次请求服务端会返回文件的内容,后续的都只返回304表示使用本地缓存。我们刷新页面可以验证这个过程:
2. 拦截请求
HttpHandler(IHttpHandler) 和 HttpModule(IHttpModule) 是asp.net 两个重要的组件,让我们可以在asp.net的基础上很方便的进行扩展。HttpHandler对应某种具体的请求,例如.ashx,.aspx等;HttpModule是一个拦截器,可以在管道的某个事件对所有请求进行拦截。简单的说,在管道中,HttpApplication会触发一系列事件,我们在通过HttpModule对某个事件进行注册,例如我们可以在处理程序对象生成前拦截请求,然后映射到自己的处理程序;而实际处理请求返回结果的是HttpHandler,例如Page用来生成html。
以asp.net mvc框架为例,它是建立在asp.net 路由机制的基础上的,asp.net 路由系统通过一个UrlRoutingModule对请求进行拦截,具体是在PostResolveRequestCache事件进行拦截,对url进行解析,封装相应的路由数据后,最终将请求交给一个MvcHandler进行处理,MvcHandler实现了IHttpHandler接口。
前面我们进行了如下配置:
IHttpHandler的ProcessRequest(异步就是BeginProcessRequest)就用来执行请求返回输出结果的。如果只需要一种处理程序我们也可以实现IHttpHandler。IHandlerFactory的定义如下:
1 2 3 4 5 |
|
所以,ajaxpro的所有请求都会符合ajaxpro/*.ashx格式,然后在GetHandler方法,就可以进行具体的处理,返回结果是IHttpHandler;以非异步状态为例,如果我们配置了需要Session,就会生成一个实现IHttpHandler和IRequiresSessionState的Handler,如果需要只读的Session,就会生成一个实现IHttpHandler和IReadOnlySessionState的Handler;这些信息可以通过反射从AjaxMethod标记属性获得。AjaxHandlerFactory的主要代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
|
3. 反射执行方法
当获得一个处理本次请求的Handler后,就可以在其ProcessRequest(异步为BeginProcessRequest)执行指定的方法。要执行一个页面对象的方法,我们必须知道指定页面所在的程序集,名称空间,页面类的名称以及方法的名称。这似乎符合我们前面:名称空间.类名称.方法名称的调用方式。为了与一般请求区分开,让组件具有足够的独立性,ajaxpro只拦截符合"ajaxpro/*.ashx格式的请求,这说明我们的ajax请求也要符合这个格式。如:http://localhost:50712/ajaxpro/AjaxProNamespace.AjaxProPage,TestAjaxProSourceCode.ashx,这个格式由前台脚本自动生成,并不需要我们去构造。仔细观察,会发现AjaxProNamespace.AjaxProPage,TestAjaxProSourceCode 就是页面类的完全限定名:名称空间.类名称,程序集名称,通过这个我们就可以生成具体的Type,然后进行反射获取信息。那么方法的名称呢?ajaxpro将其放在http header 中,名称为:X-AjaxPro-Method。有了这些信息,就可以反射执行方法了。这里核心代码为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
|
三、总结
我们总结一下ajaxpro的核心处理流程,它通过一个IHttpHandlerFactory拦截指定格式的url,然后从中获取类型的完全限定名生成类型对象,接着通过反射获取标记方法的特性,生成一个自定义的实现IHttpHandler接口的对象;在其ProcessRequest方法中,从http headers获取方法名称,通过反射进行参数映射并执行函数。
ajaxpro has the following advantages:
1. Simple configuration.
2. Can be used in conjunction with other components.
3. Encapsulate the front-end script. We don’t need to encapsulate it ourselves or use other script libraries.
4. For return value processing, we can return simple types or complex types, which will be automatically serialized.
The disadvantages are:
1. The page will have 4 more requests. Although 304 caching will be utilized, a request still needs to be sent to the server.
2. Ajax cannot use Get request. Since the URL format is customized, Get requests cannot be used using this format. We know that Get requests can be cached by browsers. One of Yahoo's front-end optimization suggestions is to use more get requests. In fact, we should put the namespace, class name, and assembly in the http header, and then provide a type parameter for us to choose freely.
3. Bind with