zoukankan      html  css  js  c++  java
  • [转]深入ASP.NET MVC之九:Ajax支持

    本文转自:http://www.cnblogs.com/yinzixin/archive/2012/12/22/2824384.html

    目前前端页面和服务端进行Ajax交互大多采用的都是jQuery, ASP.NET MVC提供了一些方法使得这个过程变得更加容易。常见的Ajax应用场景有两种,一个是点击一个链接,然后局部加载一些内容,可以是html片段,也可能是json数据,然后通过前端js处理之后显示;另一个是异步提交表单。这些帮助方法都是位于AjaxExtensions种的扩展方法。先看第一类场景,这是通过ActionLink来生成一个点击之后可以异步加载数据的链接。

     

    1. Ajax Action Link

    先看下如何使用这些方法,首先保证页面加载了依赖的js库:

    <script src="@Url.Content("~/Scripts/jquery-1.6.2.min.js")" type="text/javascript"></script>
        <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")"></script>

    假如有如下的Controller:

    public class AjaxController : Controller
        {
            public ActionResult Index()
            {
                return View();
            }
    
            public string Result(string name)
            {
                System.Threading.Thread.Sleep(2000);
                return "This is " + name;
            }
        }

    View文件如下:

    @{
        ViewBag.Title = "Index";
        string[] data = new string[] { "Jack", "Tom", "Kathy" };
    }
    <style type="text/css">
        a {
            margin:10px;
        }
        #loading {
            display:none;
            color:red;
        }
    </style>
    <div>
        @foreach (var n in data)
        {
            @Ajax.ActionLink(n, "Result", new { name = n }, new AjaxOptions{
                 UpdateTargetId = "tabledata",
                 LoadingElementId = "loading"
            });
        }
    </div>
    <div id="loading">
        Loading Data...
    </div>
    <div id="tabledata">
    
    </div>
    

    这样的效果便是点击超链接,从Result这个action方法就会被插入到id为tabledata的div中,在加载的过程中,id为loading的div会显示。应该说,这是一种非常常见的操作场景。在asp.net mvc的帮助下,我们不需要多写任何js代码就可以实现这一效果。下面来看下这是如何实现的。先看ActionLink生成了什么html代码:

    <a data-ajax="true" data-ajax-loading="#loading" data-ajax-mode="replace" data-ajax-update="#tabledata" href="/Ajax/Result?name=Jack">Jack</a>

    ActionLink的源代码没有太多复杂的地方,只是按规则生成这个标签而已,唯一复杂的地方是href的生成,但这个不是本文讨论的重点,这和routing模块关系更加紧密一些,有机会另文分析。真正实现功能的地方都是在jquery.unobtrusive-ajax.js这个文件中,这是一个jquery的插件,首先在插件被加载的时候,执行了如下代码:

        $("a[data-ajax=true]").live("click", function (evt) {
            evt.preventDefault();
            asyncRequest(this, {
                url: this.href,
                type: "GET",
                data: []
            });
        });

    利用jQuery的live方法设置了click事件设置为asyncRequest方法:

    function asyncRequest(element, options) {
            var confirm, loading, method, duration;
    
            confirm = element.getAttribute("data-ajax-confirm");
            if (confirm && !window.confirm(confirm)) {
                return;
            }
    
            loading = $(element.getAttribute("data-ajax-loading"));
            duration = element.getAttribute("data-ajax-loading-duration") || 0;
    
            $.extend(options, {
                type: element.getAttribute("data-ajax-method") || undefined,
                url: element.getAttribute("data-ajax-url") || undefined,
                beforeSend: function (xhr) {
                    var result;
                    asyncOnBeforeSend(xhr, method);
                    result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(this, arguments);
                    if (result !== false) {
                        loading.show(duration);
                    }
                    return result;
                },
                complete: function () {
                    loading.hide(duration);
                    getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(this, arguments);
                },
                success: function (data, status, xhr) {
                    asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
                    getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(this, arguments);
                },
                error: getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"])
            });
    
            options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });
    
            method = options.type.toUpperCase();
            if (!isMethodProxySafe(method)) {
                options.type = "POST";
                options.data.push({ name: "X-HTTP-Method-Override", value: method });
            }
    
            $.ajax(options);
        }

    这个方法还是比较清晰的。首先根据options确定是否弹出一个确认框,然后是设置加载等待的元素和显示时间。接下来就是给options添加几个回调函数,这个options其实最终就是给jquery的ajax方法的参数。下面简单看下在设置回调函数的时候主要调用的getFunction方法:

    function getFunction(code, argNames) {
            var fn = window, parts = (code || "").split(".");
            while (fn && parts.length) {
                fn = fn[parts.shift()];
            }
            if (typeof (fn) === "function") {
                return fn;
            }
            argNames.push(code);
            return Function.constructor.apply(null, argNames);
        }

    这个方法接受两个参数,第一个code,就是在AjaxOptions中OnXXX属性上设置的值,第二个是argNames,表示的是这个回调函数的参数名字。首先它是从window对象开始查找是否有名字为code的函数,如果有,就直接返回那个函数;否则,code就是代码而不是函数名称,利用Function的构造函数创建一个新的函数。因此,OnBegin的值用如下的两种形式都是可以的:

    @Ajax.ActionLink(n, "Result", new { name = n }, new AjaxOptions{
                 UpdateTargetId = "tabledata",
                 LoadingElementId = "loading",OnBegin="  alert("on begin");return false;"
            });

    或者

    <script type="text/javascript">
                function Begin() {
                    alert("on begin");
                }
            </script>
            @Ajax.ActionLink(n, "Result", new { name = n }, new AjaxOptions
       {
           UpdateTargetId = "tabledata",
           LoadingElementId = "loading",
           OnBegin = " Begin"
       });

    用第一种方式仍然可以使用参数。参数的名字见源代码。这里的JavaScript技巧值得学习下。ActionLink的原理就是这样,把原来使用jquery要做的一些准备工作包装的更加简单。

    等到调用结束之后,在OnSuccess的时候,会默认执行如下方法:

    function asyncOnSuccess(element, data, contentType) {
            var mode;
    
            if (contentType.indexOf("application/x-javascript") !== -1) {  // jQuery already executes JavaScript for us
                return;
            }
    
            mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
            $(element.getAttribute("data-ajax-update")).each(function (i, update) {
                var top;
                switch (mode) {
                case "BEFORE":
                    top = update.firstChild;
                    $("<div />").html(data).contents().each(function () {
                        update.insertBefore(this, top);
                    });
                    break;
                case "AFTER":
                    $("<div />").html(data).contents().each(function () {
                        update.appendChild(this);
                    });
                    break;
                default:
                    $(update).html(data);
                    break;
                }
            });
        }

    注意这里,UpdateTargetId如果不填或者没有找到元素,那么就不会发生任何事。这种情况适合服务器端返回的是json,xml等类型的数据而不是html,当我们拿到数据之后,需要通过JavaScript来生成要显示的html。

    2. Ajax Form

    Ajax Form的原理和ActionLink很像,唯一不同的是提交表单到一个地址,然后得到获得的数据:

    @using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId = "result" , Url=Url.Action("Result")}))
    { 
        @Html.EditorFor(m => m)    
        <input type="submit" value="submit" />   
    
    }
    <div id="result">
    </div>
    

    Action代码如下:

    public string Result(Course course)
            {
                System.Web.Script.Serialization.JavaScriptSerializer s = new System.Web.Script.Serialization.JavaScriptSerializer();
                return s.Serialize(course);
            }

    image

  • 相关阅读:
    android代码控制seekbar的样式
    在Android中显示GIF动画
    一个带动画效果的颜色选择对话框控件AnimatedColorPickerDialog
    史上最强Android 开启照相或者是从本地相册选中一张图片以后先裁剪在保存并显示的讲解附源码
    Linux System Programming note 8 ——File and Directory Management
    Spring它不支持依赖注入static静态变量
    举例说,在命令模式(Command Pattern)
    log4j 日志大小限制 分成30一个 不按日期分日志 按大小分成 按生产日期
    JavaScript获取路径
    awk与sed:关于多行的样本
  • 原文地址:https://www.cnblogs.com/freeliver54/p/3895124.html
Copyright © 2011-2022 走看看