zoukankan      html  css  js  c++  java
  • Unobtrusive Ajax in Asp.net MVC

         讲述怎么使用Unobtrusive Ajax之前,先看在Asp.net MVC传统情况下怎么来实现一个下拉框联动效果:

         1. 简单的定义一个model:

        public class Appointment
        {
            public string ClientName { getset; }
            [DataType(DataType.Date)]
            public DateTime Date { getset; }
            public bool TermsAccepted { getset; }
        }

         2. controller和action的实现:

         index.cshtml: 

    @model string
    @{
        ViewBag.Title = "Index";
    }
    <h4>Appointment List</h4>
    @using (Html.BeginForm())
    {
        <table>
            <thead>
                <th>
                    Client Name
                </th>
                <th>
                    Appointment Date
                </th>
            </thead>
            <tbody id="tabledata">
                @Html.Action("AppointmentData"new { id = Model })
            </tbody>
        </table>
        <p>
            @Html.DropDownList("id"new SelectList(new[] { "All""Joe""Jane""Bob" }, (Model ?? "All")))
            <input type="submit" value="Submit" />
        </p>
    }

        AppointmentData.cshtml:

    @using UnobtrusiveAjax.Models
    @model IEnumerable<UnobtrusiveAjax.Models.Appointment>
    @{
        Layout = null;
    }

    @foreach (Appointment appt in Model)
    {
        <tr>
            <td>@Html.DisplayFor(m => appt.ClientName)
            </td>
            <td>@Html.DisplayFor(m => appt.Date)
            </td>
        </tr>
    }

        最终的效果就是:当切换下拉框的选择项时,Appointment list也对应变化,但是页面是通过postback来刷新数据的。现在想实现Ajax切换效果:

        4. 启用Unobtrusive Ajax脚本了。

        web.config中新增:

              <add key="UnobtrusiveJavaScriptEnabled" value="true"/>。

        然后在页面中引入:

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

        5. 页面中更新form为ajax form:

    @model string
    @{
        ViewBag.Title = "Index";
        AjaxOptions ajaxOptions = new AjaxOptions
                                      {
                                          UpdateTargetId = "tabledata"
                                      };
    }
    <h4>Appointment List</h4>

    @using(Ajax.BeginForm("AppointmentData", ajaxOptions))
    {
        <table>
            <thead>
                <th>
                    Client Name
                </th>
                <th>
                    Appointment Date
                </th>
            </thead>
            <tbody id="tabledata">
                @Html.Action("AppointmentData"new { id = Model })
            </tbody>
        </table>
        <p>
            @Html.DropDownList("id"new SelectList(new[] { "All""Joe""Jane""Bob" }, (Model ?? "All")))
            <input type="submit" value="Submit" />
        </p>
    }

    这时候,基本的Ajax效果已经出来了。如果要继续完善美化,可以从AjaxOptions着手。先看AjaxOptions的属性有:Confirm, HttpMethod, InsertionMode, LoadingElementId, LoadingElementDuration, UpdateTargetId, Url,OnBegin, OnComplete, OnFailure, OnSuccess等。详细的可以参考:http://msdn.microsoft.com/en-us/library/system.web.mvc.ajax.ajaxoptions(v=vs.108).aspx。利用这些属性,我们来一个完美的吧:

    @model string
    @{
        ViewBag.Title = "Index";
        AjaxOptions ajaxOptions = new AjaxOptions
                                      {
                                          UpdateTargetId = "tabledata",
                                          Url = Url.Action("AppointmentData"),
                                          LoadingElementId = "loading",
                                          LoadingElementDuration = 2000,
                                          Confirm = "Do you wish to request new data?",
                                          OnBegin = "OnBegin",
                                          
    OnComplete = "OnComplete",
                                          
    OnFailure = "OnFailure",
                                          
    OnSuccess = "OnSuccess"
                                      };
    }
    <h4>Appointment List</h4>
        <script type="text/javascript">
            function OnBegin() {
                alert("This is the OnBegin Callback");
            }
            function OnSuccess(data) {
                alert("This is the OnSuccessCallback: " + data);
            }
            function OnFailure(request, error) {
                alert("This is the OnFailure Callback:" + error);
            }
            function OnComplete(request, status) {
                alert("This is the OnComplete Callback: " + status);
            }
        </script>
    <div id="loading" style="display: none; color: Red; font-weight: bold">
        <p>
            Loading Data...</p>
    </div>
    @using (Ajax.BeginForm(ajaxOptions))
    {
        <table>
            <thead>
                <th>
                    Client Name
                </th>
                <th>
                    Appointment Date
                </th>
            </thead>
            <tbody id="tabledata">
                @Html.Action("AppointmentData"new { id = Model })
            </tbody>
        </table>
        <p>
            @Html.DropDownList("id"new SelectList(new[] { "All""Joe""Jane""Bob" }, (Model ?? "All")))
            <input type="submit" value="Submit" />
        </p>
    }

    其中标黄部分是为了兼容不支持js的浏览器(原有实现在不支持js的浏览器中直接返回没有html的原始数据)。

          6. 增加Ajax Links(支持Ajax的超链接)。在index顶部增加:

    @foreach (string str in new[] { "All""Joe""Jane""Bob" })
    {
        <div style="margin-right: 5px; float: left">
                @Ajax.ActionLink(str, "AppointmentData"new { id = str },
                new AjaxOptions
                {
                    UpdateTargetId = "tabledata",
                    LoadingElementId = "loading",
                })
        </div>
    }

    这时,点击它所生成的链接,和切换下拉框选中内容,效果完全一样。

         7. 为了让上一步中ajax兼容不支持js的浏览器,并将ajax response回来的html数据改为json原始数据,做一些改进。

         controller变为:

        public class AppointmentController : Controller
        {
            public ActionResult Index(string id)
            {
                return View("Index", (object)id);
            }

            public ActionResult AppointmentData(string id)
            {
                IEnumerable<Appointment> data = new[]
                                                    {
                                                        new Appointment
                                                            {ClientName = "Joe", Date = DateTime.Parse("1/1/2012")},
                                                        new Appointment
                                                            {ClientName = "Joe", Date = DateTime.Parse("2/1/2012")},
                                                        new Appointment
                                                            {ClientName = "Joe", Date = DateTime.Parse("3/1/2012")},
                                                        new Appointment
                                                            {ClientName = "Jane", Date = DateTime.Parse("1/20/2012")},
                                                        new Appointment
                                                            {ClientName = "Jane", Date = DateTime.Parse("1/22/2012")},
                                                        new Appointment
                                                            {ClientName = "Bob", Date = DateTime.Parse("2/25/2012")},
                                                        new Appointment
                                                            {ClientName = "Bob", Date = DateTime.Parse("2/25/2013")}
                                                    };
                if (!string.IsNullOrEmpty(id) && id != "All")
                {
                    data = data.Where(e => e.ClientName == id);
                }

                if (Request.IsAjaxRequest())
                {
                    return Json(data.Select(m => new
                                                     {
                                                         ClientName = m.ClientName,
                                                         Date = m.Date.ToShortDateString()
                                                     }),
                                                     JsonRequestBehavior.AllowGet);
                }
                else
                {
                    return View(data);
                }
            }
        }

    标黄部分的变更前者是为了兼容get和post2种请求,后者是为了兼容普通请求和ajax请求并分别生成不同类容。其中,Request.IsAjaxRequest()方法可以判断当前请求是否来自Ajax。

          view变更为:


    @model string
    @{
        ViewBag.Title = "Index";
        AjaxOptions ajaxOptions = new AjaxOptions
                                      {
                                          UpdateTargetId = "tabledata",
                                          //Url = Url.Action("AppointmentData"),
                                          LoadingElementId = "loading",
                                          LoadingElementDuration = 2000,
                                          Confirm = "Do you wish to request new data?",
                                          //OnBegin = "OnBegin",
                                          
    //OnComplete = "OnComplete",
                                          
    //OnFailure = "OnFailure",
                                          
    //OnSuccess = "OnSuccess"
                                      };
    }
    <h4>Appointment List</h4>
    <script type="text/javascript">
        function OnSuccess2(data) {
            var target = $('#tabledata');
            target.empty();
            for (var i = 0; i < data.length; i++) {
                target.append('<tr><td>' + data[i].ClientName + '</td><td>' + data[i].Date + '</td></tr>');
            }
        }
    </script>
    <div id="loading" style="display: none; color: Red; font-weight: bold">
        <p>
            Loading Data...</p>
    </div>
    @using (Ajax.BeginForm(ajaxOptions))
    {
        <table>
            <thead>
                <th>
                    Client Name
                </th>
                <th>
                    Appointment Date
                </th>
            </thead>
            <tbody id="tabledata">
                @Html.Action("AppointmentData"new { id = Model })
            </tbody>
        </table>
        <p>
            @Html.DropDownList("id"new SelectList(new[] { "All""Joe""Jane""Bob" }, (Model ?? "All")))
            <input type="submit" value="Submit" />
        </p>
    }
    @foreach (string str in new[] { "All""Joe""Jane""Bob" })
    {
        <div style="margin-right: 5px; float: left">        
            @Ajax.ActionLink(str, "Index"new { id = str }, new AjaxOptions
            {
                Url = Url.Action("AppointmentData"new { id = str }),
                LoadingElementId = "loading",
                LoadingElementDuration = 2000,
                OnSuccess = "OnSuccess2"
            })
        </div>
    }

         8. 原理:

         Browser端查看html源码发现form部分为:

    <form action="/Appointment" data-ajax="true" data-ajax-confirm="Do you wish to request new data?" data-ajax-loading="#loading" data-ajax-loading-duration="2000" data-ajax-mode="replace" data-ajax-update="#tabledata" id="form0" method="post">    

         ajax links部分为:

    <data-ajax="true" data-ajax-loading="#loading" data-ajax-loading-duration="2000" data-ajax-success="OnSuccess2" data-ajax-url="/Appointment/AppointmentData/Bob" href="/Appointment/Index/Bob">Bob</a>

    所以它实际上和validation部分类似,不过是在html中隐藏了很多自定义属性,然后在unobtrusive ajax 的js中去获取,然后根据这些值来分别处理。

          9. 如果禁用了unobtrusive ajax,则mvc framework会自动启用MicrosoftAjax.js和MicrosoftMVCAjax,但是你需要手动引入它们。它们效果相同,但实现原理不一样。

          源码download 

  • 相关阅读:
    Linux异步IO
    基本数据类型总结--
    总结
    字典魔法二
    字典及其魔法
    元祖的魔法
    列表的特点
    运算符
    while ……else……和while……continue……和 while…………break…………
    作业---写一个程序,用户名 、密码输入错误3次 错误
  • 原文地址:https://www.cnblogs.com/Langzi127/p/2734836.html
Copyright © 2011-2022 走看看