MVC之Ajax如影随行

2014-07-04 10:34 by 书洞里的猫, 15 阅读, 0 评论, 收藏编辑

一、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的故事,暂且讲到这里吧!

MVC之Ajax的更多相关文章

  1. MVC使用ajax异步刷新时怎样输出从后台中传过来的JSON数据

    前言 这几天在学习MVC使用AJAX异步刷,因为是新手.所以在js中传参数到后台以及后台返回数据到前台怎么接受,怎么前台遍历出JSON数据都开始不知道,相信新手在使用时跟我一样会遇到,这里我就和大家分 ...

  2. ASP.NET MVC 实现AJAX跨域请求方法《1》

    ASP.NET MVC 实现AJAX跨域请求的两种方法 通常发送AJAX请求都是在本域内完成的,也就是向本域内的某个URL发送请求,完成部分页面的刷新.但有的时候需要向其它域发送AJAX请求,完成数据 ...

  3. asp.net mvc 使用ajax请求 控制器 (PartialViewResult)分部的action,得到一个分部视图(PartialView)的HTML,进行渲染

    在asp.net mvc 使用ajax请求获取数据的时候,我们一般是返回json或者xml,然后解析这些数据进行渲染,这样会比较麻烦,可以请求一个 分部action,返回一个分部视图 直接可以渲染,不 ...

  4. [转]MVC整合Ajax

    MVC教程第五篇:MVC整合Ajax   2010-02-01 作者:张洋 来源:张洋的BLOG   摘要 本文将从完成“输入数据验证”这个功能出发,逐渐展开ASP.NET MVC与Ajax结合的方法 ...

  5. 在Asp.Net MVC中用Ajax回调后台方法

    在Asp.Net MVC中用Ajax回调后台方法基本格式: var operData = ...; //传递的参数(action中定义的) var type = ...; //传递的参数(action ...

  6. ASP.NET MVC利用ajax把action的JavaScript注册到页面并执行

    相信大家在做Webform时经常会遇到在页面的后台CS文件中根据数据运行结果修改页面显示样式.显示(隐藏).或者弹出框,当时我们会用到ScriptManage或者Page来向页面注册一段js来实现页面 ...

  7. MVC的Ajax的异步请求

    MVC的Ajax的异步请求 在这里小写一下MVC的异步请求的一点小总结. 个人认为是有两种的,一种就是跟webform一样的,依旧是使用jQuery的$.get()方法,只是请求地址不同,webfor ...

  8. (转载)MVC + JQUERY + AJAX的几种方式

    MVC + JQUERY + AJAX的几种方式 // 传过去一个简单值,获取一个简单值 $.ajax({            type: "GET",         url: ...

  9. [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传

    原文 [代码示例]用Fine Uploader+ASP.NET MVC实现ajax文件上传 Fine Uploader(http://fineuploader.com/)是一个实现 ajax 上传文件 ...

  10. MVC验证09-使用MVC的Ajax.BeginForm方法实现异步验证

    原文:MVC验证09-使用MVC的Ajax.BeginForm方法实现异步验证 MVC中,关于往后台提交的方法有: 1.Html.BeginForm():同步 2.Ajax.BeginForm():异 ...

随机推荐

  1. mySQl该数据库不能将中国的做法

    1. 更改MySQL安装文件夹(C:\Program Files\MySQL\MySQL Server 5.5)的my.ini文件 设置: default-character-set=utf8 cha ...

  2. PHP操作XML文件学习笔记

    原文:PHP操作XML文件学习笔记 XML文件属于标签语言,可以通过自定义标签存储数据,其主要作用也是作为存储数据. 对于XML的操作包括遍历,生成,修改,删除等其他类似的操作.PHP对于XML的操作 ...

  3. 基于注释配置bean和装饰bean

    1.组件扫描 Spring容器能够从classpath(类路径)下自动扫描.侦测和实例化具有特定注释的组件. 2.特定注释组件 –@Component: 基本注解, 标识了一个受 Spring 管理的 ...

  4. js中arguments

    arguments 每天一对象,JS天天见,今天我们来看看arguments对象及属性.arguments对象不能显式创建,arguments对象只有函数开始时才可用.函数的 arguments 对象 ...

  5. 使用myeclipse将Javaj项目标ar套餐邂逅classnotfound解决问题的方法

    做一件事的今天,该Java项目打包成jar文件.折腾2小时,最终运行jar文件报告classnotfound异常,我觉得程序写入依赖jar包不玩成,但是,我手动添加.或不.网上找了很多办法.或不.后. ...

  6. obj-c编程15[Cocoa实例03]:MVC以及归档化演示样例

    前面的博文里介绍了归档和解档,这里我们把它实际应用到一个简单的代码中去,将它作为一个多文档应用程序的打开和保存的背后支持.另外这里介绍一下MVC思想,这个在不论什么语言里都会有,它是一种设计思想,主要 ...

  7. 泛型方法动态生成表达式树 Expression

    public string GetGridJSON(TraderInfo model) { IQueryable<TraderInfo> Temp = db.TraderInfo; if ...

  8. 用DIV+css写Table

    做出的效果样式如下图, 1,首先考虑的是如何显示border,就像是分割代码,我把border分割为最外层DIV全border,和内层DIV的right和bottom的border,就是右边和下边. ...

  9. javascirpt怎样模仿块级作用域(js高程笔记)

    因为javascript没有块级作用域的概念,所以在块语句中定义的变量,实际上是在包括函数中而非语句中创建的. 如: function outputNumbers(count){ for(var i= ...

  10. java通过SVG导出图片

    import java.io.ByteArrayInputStream; import java.io.File; import java.io.FileOutputStream; import ja ...