Home Web Front-end JS Tutorial Writing lightweight ajax components 02--A brief analysis of AjaxPro

Writing lightweight ajax components 02--A brief analysis of AjaxPro

May 24, 2018 pm 03:01 PM
ajax Lightweight

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:

<httpHandlers>
 <add verb="POST,GET" path="ajaxpro/*.ashx" type="AjaxPro.AjaxHandlerFactory, AjaxPro"/>
</httpHandlers>
Copy after login

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

protected void Page_Load(object sender, EventArgs e)
{
 AjaxPro.Utility.RegisterTypeForAjax(typeof(AjaxProPage));
}
Copy after login

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 

[AjaxMethod]
public List<string> GetList(string input1,string input2)
{
 return new List<string> { input1, input2 };
}
Copy after login

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.

function GetList() {
 //var result = AjaxProNamespace.AjaxProPage.GetList("a", "b").value;
 //console.log(result);
 AjaxProNamespace.AjaxProPage.GetList("a", "b", function (result) {
  console.log(result);
 });  
}
Copy after login

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.

if(typeof AjaxProNamespace == "undefined") AjaxProNamespace={};
if(typeof AjaxProNamespace.AjaxProPage_class == "undefined") AjaxProNamespace.AjaxProPage_class={};
AjaxProNamespace.AjaxProPage_class = function() {};
Object.extend(AjaxProNamespace.AjaxProPage_class.prototype, Object.extend(new AjaxPro.AjaxClass(), {
 GetList: function(input1, input2) {
  return this.invoke("GetList", {"input1":input1, "input2":input2}, this.GetList.getArguments().slice(2));
 },
 url: &#39;/ajaxpro/AjaxProNamespace.AjaxProPage,TestAjaxProSourceCode.ashx&#39;
}));
AjaxProNamespace.AjaxProPage = new AjaxProNamespace.AjaxProPage_class();
Copy after login

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接口。

  前面我们进行了如下配置: 这表明了任何的以 ajaxpro/任意名称.ashx结尾的 Post/Get 请求,都交给AjaxPro.AjaxHandlerFactory进行处理,它是一个实现了IHandlerFactory的处理程序工厂,用来生成具体的IHttpHandler。组件内部定义了多个实现IHttpHandler的类,有的是为了生成js脚本的,对于处理ajax请求,主要分为两类:异步(IHttpAsyncHandler)和非异步(IHttpHandler);在这两类的基础上,对于Session的状态的支持又分为三种:支持读写(实现IRequiresSessionState标记接口)的Handler、只读(实现IReadOnlySessionState标记接口)的Handler和不支持Session的Handler。具体生成什么样的Handler是通过AjaxMethod进行判断的。

  IHttpHandler的ProcessRequest(异步就是BeginProcessRequest)就用来执行请求返回输出结果的。如果只需要一种处理程序我们也可以实现IHttpHandler。IHandlerFactory的定义如下:

public interface IHttpHandlerFactory
{
 IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated);
 void ReleaseHandler(IHttpHandler handler);
} 
Copy after login

  所以,ajaxpro的所有请求都会符合ajaxpro/*.ashx格式,然后在GetHandler方法,就可以进行具体的处理,返回结果是IHttpHandler;以非异步状态为例,如果我们配置了需要Session,就会生成一个实现IHttpHandler和IRequiresSessionState的Handler,如果需要只读的Session,就会生成一个实现IHttpHandler和IReadOnlySessionState的Handler;这些信息可以通过反射从AjaxMethod标记属性获得。AjaxHandlerFactory的主要代码如下:

public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
{
 string filename = Path.GetFileNameWithoutExtension(context.Request.Path);
 Type t = null;
 Exception typeException = null;
 bool isInTypesList = false;
 switch (requestType)
 {
  //Get请求,获取前面的那4个脚本
  case "GET": 
   switch (filename.ToLower())
   {
    case "prototype":
     return new EmbeddedJavaScriptHandler("prototype");
    case "core":
     return new EmbeddedJavaScriptHandler("core");
    case "ms":
     return new EmbeddedJavaScriptHandler("ms");
    case "prototype-core":
    case "core-prototype":
     return new EmbeddedJavaScriptHandler("prototype,core");
    case "converter":
     return new ConverterJavaScriptHandler();
    default:
     return new TypeJavaScriptHandler(t);
   }
  case "POST":
   IAjaxProcessor[] p = new IAjaxProcessor[2];
   p[0] = new XmlHttpRequestProcessor(context, t);
   p[1] = new IFrameProcessor(context, t);
   for (int i = 0; i < p.Length; i++)
   {
    if (p[i].CanHandleRequest)
    {
     //获取标记方法的AjaxMethod属性
     AjaxMethodAttribute[] ma = (AjaxMethodAttribute[])p[i].AjaxMethod.GetCustomAttributes(typeof(AjaxMethodAttribute), true);
     bool useAsync = false;
     HttpSessionStateRequirement sessionReq = HttpSessionStateRequirement.ReadWrite;
     if (ma.Length > 0)
     {
      useAsync = ma[0].UseAsyncProcessing;
      if (ma[0].RequireSessionState != HttpSessionStateRequirement.UseDefault)
       sessionReq = ma[0].RequireSessionState;
     }
     //6种Handler,根据是否异步,session状态返回指定的Handler
     switch (sessionReq)
     {
      case HttpSessionStateRequirement.Read:
       if (!useAsync)
        return new AjaxSyncHttpHandlerSessionReadOnly(p[i]);
       else
        return new AjaxAsyncHttpHandlerSessionReadOnly(p[i]);
      case HttpSessionStateRequirement.ReadWrite:
       if (!useAsync)
        return new AjaxSyncHttpHandlerSession(p[i]);
       else
        return new AjaxAsyncHttpHandlerSession(p[i]);
      case HttpSessionStateRequirement.None:
       if (!useAsync)
        return new AjaxSyncHttpHandler(p[i]);
       else
        return new AjaxAsyncHttpHandler(p[i]);
      default:
       if (!useAsync)
        return new AjaxSyncHttpHandlerSession(p[i]);
       else
        return new AjaxAsyncHttpHandlerSession(p[i]);
     }
    }
   }
   break;
 }
 return null;
}
Copy after login

  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。有了这些信息,就可以反射执行方法了。这里核心代码为:

internal void Run()
{
 try
 {
  //设置输出结果不缓存(这不一定是我们想要的)
  p.Context.Response.Expires = 0;
  p.Context.Response.Cache.SetCacheability(System.Web.HttpCacheability.NoCache);
  p.Context.Response.ContentType = p.ContentType;
  p.Context.Response.ContentEncoding = System.Text.Encoding.UTF8;
  //验证ajax请求
  if (!p.IsValidAjaxToken())
  {
   p.SerializeObject(new System.Security.SecurityException("The AjaxPro-Token is not valid."));
   return;
  }
  //方法参数对象数组
  object[] po = null;
  //请求处理结果
  object res = null;
  try
  {
   //获取参数
   po = p.RetreiveParameters();
  }
  catch (Exception ex){}
  //获取缓存的Key
  string cacheKey = p.Type.FullName + "|" + p.GetType().Name + "|" + p.AjaxMethod.Name + "|" + p.GetHashCode();
  if (p.Context.Cache[cacheKey] != null)
  {
   //如果缓存存在,则直接使用缓存
   p.Context.Response.AddHeader("X-" + Constant.AjaxID + "-Cache", "server");
   p.Context.Response.Write(p.Context.Cache[cacheKey]);
   return;
  }
  try
  {
   if (p.AjaxMethod.IsStatic)
   {
    //使用反射调用静态方法
    try
    {
     res = p.Type.InvokeMember(
      p.AjaxMethod.Name,
      System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod,
      null, null, po);
    }
    catch (Exception ex){}
   }
   else
   {
    try
    {
     //创建实例对象,反射调用实例方法
     object c = (object)Activator.CreateInstance(p.Type, new object[] { });
     if (c != null)
     {
      res = p.AjaxMethod.Invoke(c, po);
     }
    }
    catch (Exception ex){}
   }
  }
  catch (Exception ex){}
  try
  {
   //判断结果是不是xml,如是设置ContentType
   if (res != null && res.GetType() == typeof(System.Xml.XmlDocument))
   {
    p.Context.Response.ContentType = "text/xml";
    p.Context.Response.ContentEncoding = System.Text.Encoding.UTF8;
    ((System.Xml.XmlDocument)res).Save(p.Context.Response.OutputStream);
    return;
   }
   string result = null; ;
   System.Text.StringBuilder sb = new System.Text.StringBuilder();
   try
   {
    result = p.SerializeObject(res);
   }
   catch (Exception ex){}
   //如果需要缓存,则将结果写入缓存
   if (p.ServerCacheAttributes.Length > 0)
   {
    if (p.ServerCacheAttributes[0].IsCacheEnabled)
    {
     p.Context.Cache.Add(cacheKey, result, null, DateTime.Now.Add(p.ServerCacheAttributes[0].CacheDuration), System.Web.Caching.Cache.NoSlidingExpiration, System.Web.Caching.CacheItemPriority.Normal, null);
    }
   }
  }
  catch (Exception ex){}
 }
 catch (Exception ex){}
}
Copy after login

三、总结

  我们总结一下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

. The purpose is to generate the front-end script for us, but if we want to use the .html file .aspx.cs method, it cannot be used (some pages in the blog park use this method); even our interface may need to be provided to the mobile terminal With use, this convenience becomes a limitation.

 4. Reflection. This is relatively inefficient, and it does not even cache MethodInfo like our previous page class.

It can be seen that this component is still worth using if you don’t care about efficiency. Here is just a core introduction, there are many other functions in it. This is the source code of the ajaxpro component. Interested friends can study it.

The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.

Related articles:

A brief analysis of the difference between json and jsonp and the format conversion after obtaining json data through ajax

Django framework uses ajax Implementing the function of batch importing data

Detailed explanation of AJAX XMLHttpRequest object

The above is the detailed content of Writing lightweight ajax components 02--A brief analysis of AjaxPro. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to solve the 403 error encountered by jQuery AJAX request How to solve the 403 error encountered by jQuery AJAX request Feb 20, 2024 am 10:07 AM

Title: Methods and code examples to resolve 403 errors in jQuery AJAX requests. The 403 error refers to a request that the server prohibits access to a resource. This error usually occurs because the request lacks permissions or is rejected by the server. When making jQueryAJAX requests, you sometimes encounter this situation. This article will introduce how to solve this problem and provide code examples. Solution: Check permissions: First ensure that the requested URL address is correct and verify that you have sufficient permissions to access the resource.

How to solve jQuery AJAX request 403 error How to solve jQuery AJAX request 403 error Feb 19, 2024 pm 05:55 PM

jQuery is a popular JavaScript library used to simplify client-side development. AJAX is a technology that sends asynchronous requests and interacts with the server without reloading the entire web page. However, when using jQuery to make AJAX requests, you sometimes encounter 403 errors. 403 errors are usually server-denied access errors, possibly due to security policy or permission issues. In this article, we will discuss how to resolve jQueryAJAX request encountering 403 error

PHP and Ajax: Building an autocomplete suggestion engine PHP and Ajax: Building an autocomplete suggestion engine Jun 02, 2024 pm 08:39 PM

Build an autocomplete suggestion engine using PHP and Ajax: Server-side script: handles Ajax requests and returns suggestions (autocomplete.php). Client script: Send Ajax request and display suggestions (autocomplete.js). Practical case: Include script in HTML page and specify search-input element identifier.

How to solve the problem of jQuery AJAX error 403? How to solve the problem of jQuery AJAX error 403? Feb 23, 2024 pm 04:27 PM

How to solve the problem of jQueryAJAX error 403? When developing web applications, jQuery is often used to send asynchronous requests. However, sometimes you may encounter error code 403 when using jQueryAJAX, indicating that access is forbidden by the server. This is usually caused by server-side security settings, but there are ways to work around it. This article will introduce how to solve the problem of jQueryAJAX error 403 and provide specific code examples. 1. to make

How to get variables from PHP method using Ajax? How to get variables from PHP method using Ajax? Mar 09, 2024 pm 05:36 PM

Using Ajax to obtain variables from PHP methods is a common scenario in web development. Through Ajax, the page can be dynamically obtained without refreshing the data. In this article, we will introduce how to use Ajax to get variables from PHP methods, and provide specific code examples. First, we need to write a PHP file to handle the Ajax request and return the required variables. Here is sample code for a simple PHP file getData.php:

PHP vs. Ajax: Solutions for creating dynamically loaded content PHP vs. Ajax: Solutions for creating dynamically loaded content Jun 06, 2024 pm 01:12 PM

Ajax (Asynchronous JavaScript and XML) allows adding dynamic content without reloading the page. Using PHP and Ajax, you can dynamically load a product list: HTML creates a page with a container element, and the Ajax request adds the data to that element after loading it. JavaScript uses Ajax to send a request to the server through XMLHttpRequest to obtain product data in JSON format from the server. PHP uses MySQL to query product data from the database and encode it into JSON format. JavaScript parses the JSON data and displays it in the page container. Clicking the button triggers an Ajax request to load the product list.

PHP and Ajax: Ways to Improve Ajax Security PHP and Ajax: Ways to Improve Ajax Security Jun 01, 2024 am 09:34 AM

In order to improve Ajax security, there are several methods: CSRF protection: generate a token and send it to the client, add it to the server side in the request for verification. XSS protection: Use htmlspecialchars() to filter input to prevent malicious script injection. Content-Security-Policy header: Restrict the loading of malicious resources and specify the sources from which scripts and style sheets are allowed to be loaded. Validate server-side input: Validate input received from Ajax requests to prevent attackers from exploiting input vulnerabilities. Use secure Ajax libraries: Take advantage of automatic CSRF protection modules provided by libraries such as jQuery.

What are the ajax versions? What are the ajax versions? Nov 22, 2023 pm 02:00 PM

Ajax is not a specific version, but a technology that uses a collection of technologies to asynchronously load and update web page content. Ajax does not have a specific version number, but there are some variations or extensions of ajax: 1. jQuery AJAX; 2. Axios; 3. Fetch API; 4. JSONP; 5. XMLHttpRequest Level 2; 6. WebSockets; 7. Server-Sent Events; 8, GraphQL, etc.

See all articles