ASP.NET MVC之Ajax如影隨行


一、Ajax的前世今生

      我一直覺得google是一家牛逼的公司,為什么這樣說呢?《舌尖上的中國》大家都看了,那些美食估計你是百看不厭,但是里邊我覺得其實也有這樣的一個哲學:關於食材,對於種食材的菜農來講,可能它的價值就是賣到市場上而已;而對於大廚們來講,卻可以像變魔術一樣將不起眼的食材變成美味佳餚。大廚們不擁有食材,但他們卻可以恰到好處的搭配使用它們,這就是他們的精明之處。而google同樣是IT界的大廚:java誕生了這么多年,卻沒有被充分利用,而google卻用它搞出來了震驚世界的Android; HTML、XML、Javascript這些個東東都不是google發明的吧,但卻是google卻用它們發明了Ajax, google earth、google suggest以及gmail等ajax技術的廣泛應用,向這個世界帶來了ajax技術,從此ajax與web再也不能分離。這里也向我們程序猿提了個醒:如果不能把所學的各種技術轉化為money或者生產力,那么一切都是扯淡!

      精確的說,ajax並不能提高從服務器端下載數據的速度,而只是使這個等待不那么令人沮喪,這就是所謂的用戶體驗了,但就這一點就足以產生巨大的影響和震動,因為它已經革了c/s東東的命,它無疑是WEB時代的寵兒~

Ajax的給我們帶來的好處大家基本上都深有體會,略表一二:

1、最大的一點是頁面無刷新,在頁面內與服務器通信,給用戶的體驗非常好。

2、使用異步方式與服務器通信,不需要打斷用戶的操作,具有更加迅速的響應能力。

3、可以把以前一些服務器負擔的工作轉嫁到客戶端,利用客戶端閑置的能力來處理,減輕服務器和帶寬的負擔,節約空間和寬帶租用成本。並且減輕服務器的負擔,ajax的原則是“按需取數據”,可以最大程度的減少冗余請求,和響應對服務器造成的負擔。

4、基於標准化的並被廣泛支持的技術,不需要下載插件或者小程序。

缺點也有,但是瑕不掩瑜,所以還是要用!ASP.NET MVC作為微軟的當家利器自然也要擁抱Ajax了,這里就說說他們之間那些事兒!

二、ASP.NET MVC之Ajax

這里不會用原生的Ajax的,其實我連說都不想說,土的掉渣,更別提那個微軟自己的那個已經玩完的Ajax框架了,所以下面的Ajax都不是原生的。

1、基於AjaxHelper的Ajax

MVC框架本身提供了AjaxHelper類用於Ajax異步請求,所以如果你想省事,就用這種方式吧~

AjaxHelper幫助器方法:

Helper method

Description

Ajax.ActionLink

Creates a hyperlink to a controller action that fires an Ajax request when clicked

Ajax.RouteLink

Similar to Ajax.ActionLink, but generates a link to a particular route instead of a named controller action

Ajax.BeginForm

Creates a form element that submits its data to a particular controller action using Ajax

Ajax.BeginRouteForm  Similar to Ajax.BeginForm, but creates a form that sub- mits its data to a particular route instead of a named control- ler action
 Ajax.GlobalizationScript  Creates an HTML script element that references a script that contains culture information
 Ajax.JavaScriptStringEncode  Encodes a string to make sure that it can safely be used inside JavaScript

上面的方法貌似很多,但是實際開發中用到的就兩個幫助器方法而已:

 Ajax.ActionLink()和Ajax.BeginForm()

這里有個問題:怎樣讓項目知道我們用的是MVC自帶的Ajax呢?

SO EASY:

A、在Web.config里邊配置:

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

B、在頁面中引用下面的js類庫即可:

@section scripts{
    <script type="text/javascript" src=" @Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")"></script>
}

一般更為常見的是在布局頁/Views/Shared/_Layout.cshtml 中引入,例如:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    <script src="~/Scripts/jquery-1.8.2.min.js"></script>
    <script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
</head>
<body>
    @RenderBody()
</body>
</html>

Ajax.ActionLink()

  向客戶端輸出一個鏈接地址,當單擊這個鏈接時可以Ajax調用Controller中的方法,Ajax.ActionLink()方法有許多重載,下面是其重載之一:

  public static string ActionLink(this AjaxHelper ajaxHelper, string linkText, string actionName, object routeValues, AjaxOptions ajaxOptions);

  linkText:是顯示在客戶端的文本

  actionName:是Action的名字,默認情況下我們會使用當前的Controller。

  routeValues:將傳入到Controller中方法的參數

  ajaxOptions:配置Ajax的一些選項

Confirm

獲取或設置提交請求之前,顯示在確認窗口中的消息。

HttpMethod

獲取或設置 HTTP 請求方法(“Get”或“Post”)。

InsertionMode

獲取或設置指定如何將響應插入目標 DOM 元素的模式。
LoadingElementId 

獲取或設置加載 Ajax 函數時要顯示的 HTML 元素的 id 特性。

OnBegin

獲取或設置更新頁面之前,恰好調用的 JavaScript 函數的名稱。

OnComplete

獲取或設置實例化響應數據之后但更新頁面之前,要調用的 JavaScript 函數。

OnFailure

獲取或設置頁面更新失敗時,要調用的 JavaScript 函數。

OnSuccess

獲取或設置成功更新頁面之后,要調用的 JavaScript 函數。

UpdateTargetId

獲取或設置要使用服務器響應來更新的 DOM 元素的 ID。

Url

獲取或設置要向其發送請求的 URL。

 


備注:

  • OnComplete和OnSuccess的區別:OnComplete是獲取了Http請求時引發的,此時頁面還沒有進行更新,OnSuccess是在頁面已經更新后引發的。
  • 當加載數據須要花較長時候,為了避免假死狀況,該當給用戶一個反饋信息,如“正在加載...”字樣。在 MVC 的 Unobtrusive Ajax 中經用AjaxOptions選項的 LoadingElementId 和 LoadingElementDuration 兩個屬性可輕松做到這一點,例如下面的設置:
AjaxOptions ajaxOpts = new AjaxOptions {
        UpdateTargetId = "tableBody",
        Url = Url.Action("GetPeopleData"),
        LoadingElementId = "loading",
        LoadingElementDuration = 1000,
    };
  • 對於URL,如果我們設置如下:
AjaxOptions ajaxOpts = new AjaxOptions {
        UpdateTargetId = "tableBody",
        Url = Url.Action("GetPeopleData")
    };

然后查看它生成的 form 屬性:

<form id="form0" action="/People/GetPeople" method="post" data-ajax-url="/People/GetPeopleData" data-ajax-="#tableBody" 
data-ajax-mode="replace" data-ajax="true">

它生成了兩個 Url,分別為 action 屬性 和 data-ajax-url 屬性的值,前者是 Ajax.BeginForm() 辦法按照當前 controller 和 action 名稱生成的,后者是 AjaxOptions 的 Url 屬性生成的。當瀏覽器沒有禁用 JavaScript 時,Unobtrusive Ajax JS庫會獲取 data-ajax-url 屬性的值作為 Url 產生 ajax 懇求。當瀏覽器禁用了 JavaScript 時,天然 action 屬性的值決定了默示提交的 Url,自然訪問該頁面。固然局部未能刷新,但不會讓用戶體驗很差。


 使用Html.ActionLink方法的一個栗子:

@Ajax.ActionLink("點擊我", "getEntry", new { id = item.Id }, new AjaxOptions 
{ HttpMethod = "Post", UpdateTargetId = "detailsID", InsertionMode = InsertionMode.Replace })

說明:“點擊我”是生產的超鏈接文字;“getEntry”是當前控制器的Action方法;id = item.Id是向Action方法傳遞的參數;HttpMethod = "Post", 說明Ajax請求是post方式的;UpdateTargetId = "detailsID"說明了要更新的html塊的Id標記元素;InsertionMode = InsertionMode.Replace說明是替換ID為detailsID的元素里邊的內容。

實際應用:

 (1)使用Ajax.ActionLink請求返回值為 Json格式的Controller方法

 在Index.cshtml中使用ActionLink,如下:

@Ajax.ActionLink("點擊我", "JsonDetails", new { id = item.Id }, 
new AjaxOptions { HttpMethod = "Post", InsertionMode = InsertionMode.Replace, OnSuccess = "Show" })

相應的Controller:

public ActionResult JsonDetails(int id = 0)
        {
            GuestbookEntry entry = _db.Entries.First(c => c.Id == id);
            return Json(entry, JsonRequestBehavior.AllowGet);
        }

同時需要在Index.cshtml中添加請求成功的相應js函數Show,以便更新ID屬性為detailsID的DIV內容:

<script type="text/javascript">
function Show(data) {
$("#detailsID").html("姓名:" + data.Name + " 消息:" + data.Message);
}
</script>

(2)使用Ajax.ActionLink 請求返回值為PartialView格式的Controller方法

 在Index.cshtml中

@Ajax.ActionLink("AjaxPartialView", "Details", new { id = item.Id }, 
new AjaxOptions { HttpMethod = "Get", UpdateTargetId = "detailsID" })

相應的Controller:

public ActionResult Details(int id = 0)
        {
            GuestbookEntry entry = _db.Entries.First(c => c.Id == id);
            if (Request.IsAjaxRequest())
           {
                return PartialView(entry);
            }
            return View(entry);
        }

在這里我們使用Request.IsAjaxRequest()來判斷是否為Ajax請求,如果是則返回PartialView,否則返回View。最后,返回的內容會直接更新到ID屬性為detailsID的DIV中。

Ajax.BeginForm

 這個方法用於異步提交表單,比如一個新增信息的頁面Create.cshtml,下面的代碼會使表單以Ajax方式提交

@model MvcApplication5.Models.GuestbookEntry
<script type="text/javascript" src=" @Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")"></script>
<script type="text/javascript">
    function success(data) {
        alert(data);
    }
</script>
@{
    ViewBag.Title = "Create";
}

<h2>Create</h2>

@using (Ajax.BeginForm(new AjaxOptions { 
    HttpMethod="Post",
    OnSuccess = "success"
}))
{
    @Html.ValidationSummary(true)

    <fieldset>
        <legend>GuestbookEntry</legend>
        <div class="editor-label">
            @Html.LabelFor(model => model.Name)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Name)
            @Html.ValidationMessageFor(model => model.Name)
        </div>
        <div class="editor-label">
            @Html.LabelFor(model => model.Message)
        </div>
        <div class="editor-field">
            @Html.EditorFor(model => model.Message)
            @Html.ValidationMessageFor(model => model.Message)
        </div>
        <p>
            <input type="submit" value="Create" />
        </p>
    </fieldset>
}

控制器的代碼如下:

        [HttpPost]
        public ActionResult Create(GuestbookEntry entry)
        {
            if (ModelState.IsValid)
            {
                entry.DateAdded = DateTime.Now;
                _db.Entries.Add(entry);
                _db.SaveChanges();
                return Content("New Entry successfully added.");
            }
            else {
                return View();
            }
        }

注:

貌似上面的Ajax方法很方便,但是它的工作原理可能大家不是很清楚,這里就大概說一下吧~

當調用 Ajax.BeginForm 方法后,經由選項 AjaxOptions 對象設置的屬性將會被轉化成 form 表單的屬性,這些屬性以 data-ajax 開首,如本示例生成的 form 表單:

<form action="/GuestBook/Create" data-ajax="true" data-ajax-mode="replace" data-ajax-="#tableBody" id="form0" method="post">

當 Create.cshtml 視圖加載完成並浮現 Html 頁面時,jquery.unobtrusive-ajax.js 庫會尋找所有 data-ajax == true的元素,然后按照其它以 data-ajax 開頭的屬性值,jQuery 庫中的函數將知道如何去執行 Ajax 請求。

2、基於JQuery的Ajax

(1)使用JQuery的Ajax請求返回值為 Json格式的Controller方法

 原理就是用JQuery的Ajax方法請求Action方法,返回值設為JSON,然后對JSON數據進行處理,例如用js函數進行處理

 舉個栗子: 

<script type="text/javascript" language="javascript">
        $(function(){
                GetRoomInfoList();
}); function GetRoomInfoList() { showDivLoading();
//異步加載數據時的浮層 $.ajax({ type: "Post", url: "@Url.Content("~/Room/GetRoomInfoShipId")",//異步請求的URL,就是Room控制器方法GetRoomInfoShipId(long shipId) dataType: "json",//要求返回數據為JSON格式 data:{shipId:$("#ShipIdForSearch").val()},//異步請求的參數 success: function(data){ $("#RoomInfoListTable").empty(); //清空里面的所有內容 $.each(data, function(i, item){ //用js拼字符串處理數據,這里是顯示所有房型列表信息 var str="<tr>"; str+=" <td>"; str+=" <span style=\" width:150px;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;\">"; str+=item.BaseRoomId; str+=" </span>" str+=" </td>"; str+=" <td>"; str+=" <span style=\" width:150px;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;\">"; str+=item.ShipId; str+=" </span>" str+=" </td>"; str+=" <td>"; str+=" <span style=\" width:150px;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;\">"; str+=item.RoomType; str+=" </span>" str+=" </td>"; str+=" <td>"; str+=" <span style=\" width:150px;display:block;white-space:nowrap; overflow:hidden; text-overflow:ellipsis;\">"; str+=item.RoomName; str+=" </span>" str+=" </td>"; str+="</tr>"; $("#RoomInfoListTable").append(str);
}); } }); }

(2)使用JQuery的Ajax 請求返回值為PartialView格式的Controller方法

 假設有這樣的一個Model:

namespace MvcApplication1.Models
{
  public class Team
    {
        public string Preletter { get; set; }
        public string Name { get; set; }
    }
}

 通過JQuery異步加載分部視圖,Home/Index.cshtml:

@{
    ViewBag.Title = "Index";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Index</h2>
<div>
<a href="#" id="a">通過jQuery異步</a> <br/>
</div>
<div id="result">
</div>
@section scripts
{
   <script type="text/javascript">
     $(function() {
     $('#a').click(function() {
         $.ajax({
         url: '@Url.Action("Index","Home")',
         data: { pre: 'B' },
         type: 'POST',
         success: function(data) {


                        $('#result').empty().append(data);


                    }
                });

                return false;
            });
        });
    </script>
}

HomeController控制器中:

using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using MvcApplication1.Models;
namespace MvcApplication1.Controllers
{
    public class HomeController : Controller
       {
        public ActionResult Index()
        {
            return View();
        }
        [HttpPost]
        public ActionResult Index(string pre)
        {
            var result = GetAllTeams().Where(t => t.Preletter == pre).ToList();
            ViewBag.msg = "通過jQuery異步方式到達這里~~";
            return PartialView("TeamY", result);
        }
        private List<Team> GetAllTeams()
        {
            return new List<Team>()
            {
                new Team(){Name = "巴西隊", Preletter = "B"},
                new Team(){Name = "克羅地亞隊", Preletter = "K"},
                new Team(){Name = "巴拉圭", Preletter = "B"},
                new Team(){Name = "韓國", Preletter = "K"}
            };
        }
    }
}

分部視圖TeamY.cshtml:

@model IEnumerable<MvcApplication1.Models.Team> 
@{
    var result = string.Empty;
    foreach (var item in Model)
    {
        result += item.Name + ",";
    }
}
@ViewBag.msg.ToString()
<br/>
@result.Substring(0,result.Length - 1)

3、基於JQuery的表單異步提交

 舉個栗子吧:

<script type="text/javascript">
    $(document).ready(function () {
        $("#form1").submit(function (event) {
            event.preventDefault();//阻止默認提交事件,改用JS處理提交事件
$.ajax({
type:"Post//表單提交類型 
url: "@Url.Content("~/User/Create")",//表單提交的Action方法
data:$("#form1").serialize(), //序列化表單的值為字符串,前提是表單里邊的輸入標簽都要有name屬性才可以,序列化后的形式大概是這樣的:a=1&b=2&c=3&d=4&e=5
success:function(msg){
$("#result").html(msg);    
}
});
           
return false;
});   
});
</script>

但是我覺得如果表單提交的數據少的話,可以用這種,如果多的話,就沒有必要了,用MVC自帶的更好

三、如何提高Ajax性能

1、適當使用緩存機制

2、使用CDN內容分發來訪問Jquery腳本:

     (1)自己公司架設CDN服務器

     (2)使用第三方公司的,比如微軟,谷歌等公司的CDN,但有時候不太靠譜

3、JS/CSS文件的打包合並(Bundling)及壓縮(Minification)

將多個JS或CSS文件打包合並成一個文件,並在網站發布之后進行壓縮,從而減少HTTP請求次數,提高網絡加載速度和頁面解析速度。壓縮功能實現了對javascript腳本和CSS進行壓縮的功能,它能夠去除腳本或樣式中不必要的空白和注釋,同時能夠優化腳本變量名的長度

例如在BundleConfig.cs里面配置捆綁js和css文件:

using System.Web;
using System.Web.Optimization;

namespace MvcExample
{
    public class BundleConfig
    {
        // For more information on Bundling, visit http://go.microsoft.com/fwlink/?LinkId=254725
        public static void RegisterBundles(BundleCollection bundles)
        {
            bundles.Add(new ScriptBundle("~/bundles/jquery").Include(
                        "~/Scripts/jquery-{version}.js"));

            bundles.Add(new StyleBundle("~/Content/css").Include("~/Content/site.css"));
        }
    }
}

 記得在Global.asax中注冊一下:

BundleConfig.RegisterBundles(BundleTable.Bundles);

頁面引用時可以這樣引用:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
    @Styles.Render("~/Content/css")
    @Scripts.Render("~/bundles/jquery")
    @RenderSection("scripts", required: false)
</head>
<body>
    @RenderBody()
</body>
</html>

啟用JS/CSS文件壓縮合並:

  • Web.config中配置
<compilation debug="false" targetFramework="4.0" />
  • 在BundleConfig.cs或Global.asax中添加以下代碼即可:
BundleTable.EnableOptimizations = true;

4、最好將js腳本文件放在view頁面下面一點

關於ASP.NET MVC和Ajax的故事,暫且講到這里吧!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM