zoukankan      html  css  js  c++  java
  • 深入理解jQuery AJAX调用页面内Web服务

    这篇文章的灵感是来自XuebinDing的这篇jQuery AJAX实现调用页面后台方法和web服务定义的方法,原文讲到了这种直接调用aspx页面内的Web服务方法,非常的轻巧,但作者只给出了代码,里面一些的详细并没有给出说明,这里我会花上一些时间来去深入解析一下这其中的原理。

    先来看代码,注意此方法是位于aspx代码文件中:

    using System.Web.Services;
    /// <summary>
    /// 无参数的Ajax调用
    /// </summary>
    /// <returns></returns>
    [WebMethod]
    public static string SayHello() {
    return "Hello Ajax";
    }

    jQuery来使用json方式调用此方法:

    $.ajax({
    type: 'post',
    url: 'TextAjax.aspx/SayHello,
    data: data,
    contentType: "application/json; charset=utf-8",
    dataType: 'json',
    success: function(data) {
    alert(data.d);
    }
    });

    效果如下:

    这里需要注意以下问题:

    1、WebMethod方法必须为static方法;

    2、Ajax请求不能使用get方式。

    3、如果使用的是VS2005,则需要在web.config中system.web段增加对System.Web.Extensions(可能需要System.Web.Extensions.dll)的引用:

    <httpModules>
    <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
    </httpModules>

    1、为何aspx能实现Web服务?

    在我们的印象里貌似 asp.net的Web服务是以.asmx来结尾的,而我们现在的asp.net也能实现Web服务,这是因为默认Web.config中已经添加了System.Web.Handlers.ScriptModule,它是用于管理asp.net中ajax功能的HTTP模块,这样不管用户是请求.asmx文件还是.aspx文件,都会通过此处理程序来处理请求。

    在Web.Config中可以看到对.asmx的处理程序:

    <add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>

    而在vs2005(ASP.NET2.)中默认对.asmx处理的配置是这样的:

    <add path="*.asmx" verb="*" type="System.Web.Services.Protocols.WebServiceHandlerFactory, System.Web.Services, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" validate="False"/> 

    可见对.asmx的处理程序由System.Web.Services.Protocols.WebServiceHandlerFactory变成了System.Web.Script.Services.ScriptHandlerFactory,查看System.Web.Extensions.dll的ScriptHandlerFactory方法:

    View Code
    public virtual IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
    {
    IHttpHandlerFactory factory;
    if (RestHandlerFactory.IsRestRequest(context))
    {
    factory = this._restHandlerFactory;
    }
    else
    {
    factory = this._webServiceHandlerFactory;
    }
    IHttpHandler originalHandler = factory.GetHandler(context, requestType, url, pathTranslated);
    bool flag = originalHandler is IRequiresSessionState;
    if (originalHandler is IHttpAsyncHandler)
    {
    if (flag)
    {
    return new AsyncHandlerWrapperWithSession(originalHandler, factory);
    }
    return new AsyncHandlerWrapper(originalHandler, factory);
    }
    if (flag)
    {
    return new HandlerWrapperWithSession(originalHandler, factory);
    }
    return new HandlerWrapper(originalHandler, factory);
    }

    ScriptHandlerFactory在兼容WebServiceHandlerFactory的基础上同时增加了RestHandlerFactory的处理。

    2、为何是data.d?

    在js代码里你可以看到对返回对象的访问是data.d,从控制台也可以看到返回的数据是这样的:

    {"d":"Hello Ajax"}

    这个.d是怎么回事呢?其实它是为了避免各种XSS跨站攻击,不允许使用GET方式也是出于这个需求。详细分析可以参见这位asp.net官方人员的回复http://encosia.com/a-breaking-change-between-versions-of-aspnet-ajax/#comment-34045

    扩展

    这种调用本页面的方式还是有很多可取之后,尤其是逻辑比较简单,不需要封装公共方法、只在当前页面内调用的方法来尤其合适。这里我封装了客户端调用的代码:

    /*
    * Ajax请求处理基础类
    */
    function AjaxRequestBuiler(url, data, callback) {
    var async = !(callback == undefined);
    var response = $.ajax({
    type: 'post',
    url: url,
    data: data,
    contentType: "application/json; charset=utf-8",
    dataType: 'json',
    async: async,
    success: function(data) {
    if (!!callback) {
    complete(data);
    }
    }
    });
    if (!async) {
    try {
    return eval('(' + response.responseText + ')').d;
    } catch (Error) {

    }
    }
    function complete(obj) {
    callback(obj);
    }
    }

    包含了同步调用和异步回调的方式,使用如下:

    function RequestAjax() {
    var d = AjaxRequestBuiler('TestAjax.aspx/SayHello');
    alert('无回调同步加载:' + d);
    AjaxRequestBuiler('TestAjax.aspx/SayHello', null, function(data) {
    alert('回调异步加载:' + data.d);
    alert('回调成功');
    });
    }

    代码下载地址

  • 相关阅读:
    Django跨域问题
    DOM,jquery,vue
    from和modelform的用法和介绍
    元类的__call__和__new__方法的作用
    Django学习之路由分发和反向解析
    Django 自定义auth_user
    Django创建对象的create和save方法
    Flask--(登录注册)抽取视图函数
    Flask--(项目准备)--添加日志
    Flask--(项目准备)--框架搭建,配置文件抽取,业务逻辑抽取
  • 原文地址:https://www.cnblogs.com/walkingp/p/2379337.html
Copyright © 2011-2022 走看看