首页 > 代码库 > 《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); }        }    }}
View Code

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);        }    }}
View Code

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();        }    }}
View Code

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(下)