首页 > 代码库 > 《ASP.NET MVC 4 实战》学习笔记 8:Ajax(下)
《ASP.NET MVC 4 实战》学习笔记 8:Ajax(下)
三、使用JSON和客户端模板的Ajax:
1.使用JSON的Ajax:
1)添加模型:
{ public class Speaker { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string PictureUrl { get; set; } public string Bio { get; set; } public string FullName { get { return string.Format("{0} {1}", FirstName, LastName); } } }}
2)添加模拟数据和方法:
namespace AjaxExamples.Models{ public class SpeakerRepository { //simulate an in memory database private static readonly List<Speaker> _speakers = new List<Speaker>(); static SpeakerRepository() { _speakers = new List<Speaker> { new Speaker { Id = 1, FirstName = "Jimmy", LastName = "Bogard", PictureUrl = "/content/jimmy.png", Bio = "Jimmy is a Principal Consultant at Headspring Systems in Austin, TX.", }, new Speaker { Id = 2, FirstName = "Jeffrey", LastName = "Palermo", PictureUrl = "/content/jeffrey.jpg", Bio = "Jeffrey Palermo is a Microsoft MVP and Chief Technology Officer of Headspring Systems in Austin, TX.", }, new Speaker { Id = 3, FirstName = "Eric", LastName = "Hexter", PictureUrl = "/content/eric.jpg", Bio = "Eric Hexter is an Enterprise Architect at Dell in Austin, TX.", }, new Speaker { Id = 4, FirstName = "Matt", LastName = "Hinze", PictureUrl = "/content/matt.jpg", Bio = "Matt Hinze is a Principal Consultant at Headspring Systems in Austin, TX.", }, new Speaker { Id = 5, FirstName = "Jeremy", LastName = "Skinner", PictureUrl = "/content/jeremy.jpg", Bio = "Jeremy Skinner is a C#/ASP.NET software developer in the UK.", } }; } public IEnumerable<Speaker> FindAll() { return _speakers; } public Speaker FindSpeaker(int id) { return _speakers.SingleOrDefault(x => x.Id == id); } }}
3)添加控制器:
namespace AjaxExamples.Controllers{ public class SpeakersController : Controller { private readonly SpeakerRepository _repository = new SpeakerRepository(); public ActionResult Index() { var speakers = _repository.FindAll(); return View(speakers); } public ActionResult Details(int id) { var speaker = _repository.FindSpeaker(id); return Json(speaker, JsonRequestBehavior.AllowGet);//将发言人序列成json } }}
4)添加视图:
@model IEnumerable<AjaxExamples.Models.Speaker><link href="@Url.Content("~/Content/speakers.css")" rel="stylesheet" /><script src="@Url.Content("~/Scripts/jquery-1.10.2.min.js")"></script><script src="@Url.Content("~/Scripts/Speakers.js")"></script><ul class="speakers"> @foreach (var speaker in Model) { <li> @Html.ActionLink(speaker.FullName, "Details", new { id = speaker.Id }) </li> }</ul><img id="indicator" src="~/Content/load.gif" alt="loading..." style="display:none;" />@*显示进度指示器*@
5)添加Speakers.js文件:
$(document).ready(function () { $("ul.speakers a").click(function (e) { e.preventDefault(); $("#indicator").show();//显示进程指示器 var url = $(this).attr(‘href‘);//接受URL $.getJSON(url, null, function (speaker) {//调用Ajax请求 $("#indicator").hide(); alert(speaker.FirstName); }); });});
上面的例子只是弹出发言人名字的模态对话框,下面我们将使用客户端模板显示更详细的信息。
2.客户端模板:
客户端模板能够在浏览器中动态地生成标记,而不必返回服务器。
1)下载jQuery-tmpl并引入项目:
2)修改视图:
@model IEnumerable<AjaxExamples.Models.Speaker><link href="@Url.Content("~/Content/speakers.css")" rel="stylesheet" /><script src="@Url.Content("~/Scripts/jquery-1.10.2.min.js")"></script><script src="@Url.Content("~/Scripts/jquery.tmpl.js")"></script><script src="@Url.Content("~/Scripts/Speakers.js")"></script><ul class="speakers"> @foreach (var speaker in Model) { <li> @Html.ActionLink(speaker.FullName, "Details", new { id = speaker.Id }) </li> }</ul><img id="indicator" src="~/Content/load.gif" alt="loading..." style="display:none;" />@*显示进度指示器*@<div class="selected-speaker" style="display:none"></div><br style="clear:both" /><script id="speakerTemplate" type="text/x-jquery-tmpl">@*定义模板*@ <img src="${PictureUrl}" alt="Speaker image" class="speaker-pic" />@*照片模板*@ <p class="speaker-bio">${Bio}</p>@*简历行模板*@ <br style="clear:both;" /></script>
3)修改Speakers.js:
$(document).ready(function () { $("ul.speakers a").click(function (e) { e.preventDefault(); $(".selected-speaker").hide().html(‘‘);//隐藏发言人细节模板 $("#indicator").show(); var url = $(this).attr(‘href‘); $.getJSON(url, null, function (speaker) { $("#indicator").hide(); $("#speakerTemplate") .tmpl(speaker) .appendTo(‘.selected-speaker‘);//渲染带有数据的模板 $(‘.selected-speaker‘).show(); }); });});
但是不幸的是会报错,没有找到原因,有没有人告诉我为什么。。。
3.最后润色:
如果浏览器禁用了javascript那么当点击发言人姓名时相应的JSON将作为文本文件下载而不会作为模板来渲染。
依然可以重写Details方法和添加Details视图解决:
public ActionResult Details(int id) { var speaker = _repository.FindSpeaker(id); if (Request.IsAjaxRequest()) { return Json(speaker, JsonRequestBehavior.AllowGet);//将发言人序列成json } return View(speaker); }
@model AjaxExamples.Models.Speaker@{ ViewBag.Title = "Details";}<h2>发言人详细信息: @Model.FullName</h2><p class="speaker"> <img src="@Model.PictureUrl" alt="@Model.FullName" /><p class="speaker-bio">@Model.Bio</p></p><br style="clear:both" />@Html.ActionLink("返回列表", "index")
但是也可以采用另一种方式--使用“动作方法选择器”来区分Ajax和非Ajax请求:
1)添加继承自ActionMethodSelectorAttribute的类:
namespace AjaxExamples{ [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class AcceptAjaxAttribute : ActionMethodSelectorAttribute { public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo) { return controllerContext.HttpContext.Request.IsAjaxRequest(); } }}
如果当前动作是通过Ajax请求的AcceptAjaxAttribute便在IsValidForRequest方法中返回true。
2)将Details拆分成两个方法:
[AcceptAjax] public ActionResult Details(int id) { var speaker = _repository.FindSpeaker(id); return Json(speaker, JsonRequestBehavior.AllowGet); } [ActionName("Details")] public ActionResult Details_NonAjax(int id) { var speaker = _repository.FindSpeaker(id); return View(speaker); }
上面方法第一个重载以AcceptAjaxAttribute注解用于处理Ajax请求,另一个用于常规请求。
四、创建自动完成文本框(jQuery UI):
1)下载并引入jQuery UI
2)添加City模型:
namespace AjaxExamples.Models{ public class City { public int Id { get; set; } public string Name { get; set; } public string State { get; set; } public string DisplayName { get { return Name + ", " + State; } } }}
3)添加模拟数据和方法:
namespace AjaxExamples.Controllers{ public class CityRepository { const string _csvFilename = "App_Data/cities.csv"; static readonly List<City> _cities; static CityRepository() { string path = Path.Combine(HttpRuntime.AppDomainAppPath, _csvFilename); _cities = new List<City>(); int id = 1; foreach (var line in File.ReadAllLines(path)) { var lineSegments = line.Split(‘,‘); var name = lineSegments[0]; var state = lineSegments[1]; var city = new City { Id = id++, Name = name, State = state }; _cities.Add(city); } } public City[] FindCities(string filter) { var cities = from city in _cities where city.DisplayName.StartsWith(filter, StringComparison.CurrentCultureIgnoreCase) select city; return cities.ToArray(); } }}
4)添加控制器:
namespace AjaxExamples.Controllers{ public class CitiesController : Controller { private readonly CityRepository _repository; public CitiesController() { _repository = new CityRepository(); } public ActionResult Index() { return View(); } public ActionResult Find(string term) { City[] cities = _repository.FindCities(term); var projection = from city in cities select new { id = city.Id, label = city.DisplayName, value = city.DisplayName }; return Json(projection.ToList(), JsonRequestBehavior.AllowGet); } }}
5)添加视图:
<link href="@Url.Content("~/Content/jquery-ui.css")" rel="stylesheet" /><p> <label for="city">城市</label> <input type="text" id="city" /></p><script src="@Url.Content("~/Scripts/jquery-1.10.2.min.js")"></script><script src="@Url.Content("~/Scripts/jquery-ui.js")"></script><script type="text/javascript"> $(function () { var autocompleteUrl = ‘@Url.Action("Find")‘; $("input#city").autocomplete({ source: autocompleteUrl, minLength: 2, select: function (event, ui) { alert("选中 " + ui.item.label); } }); });</script>
但是不幸的是还是会报错,原因应该和上面一样,有没有人告诉我为什么。。。
源码下载 密码:53my
《ASP.NET MVC 4 实战》学习笔记 8:Ajax(下)