Learning notes for ASP. net mvc 4 practice 8: Ajax (below ),
3. Ajax using JSON and client templates:
1. Use JSON Ajax:
1) Add a model:
{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) Add analog data and methods:
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 effecect 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) Add a controller:
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); // sequence the speaker into json }}}
4) Add a view:
@ 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> @ * display progress indicator *@
5) Add the Speakers. js file:
$ (Document ). ready (function () {$ ("ul. speakers "). click (function (e) {e. preventDefault (); $ ("# indicator "). show (); // display process indicator var url = $ (this ). attr ('href '); // accept URL $. getJSON (url, null, function (speaker) {// call Ajax request $ ("# indicator "). hide (); alert (speaker. firstName );});});});
The preceding example only shows the modal dialog box of the speaker name. The client template is used to display more detailed information.
2. Client template:
The client template can dynamically generate tags in the browser without returning them to the server.
1) download jQuery-tmpl and introduce the project:
2) modify the View:
@ 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> @ * display progress indicator * @ <div class =" selected-speaker "> @ * define template * @ @ * photo template * @ <p class =" speaker-bio ">$ {Bio} </p> @ * resume row Template * @ <br style = "clear: both; "/> </script>
3) Modify Speakers. js:
$ (Document ). ready (function () {$ ("ul. speakers "). click (function (e) {e. preventDefault (); $ (". selected-speaker "detail .hide(detail .html (''); // hide the speaker detail template $ ("# indicator "). show (); var url = $ (this ). attr ('href '); $. getJSON (url, null, function (speaker) {$ ("# indicator "). hide (); $ ("# speakerTemplate "). tmpl (speaker ). appendTo ('. selected-speaker '); // render the template with data $ ('. selected-speaker '). show ();});});});
However, unfortunately, an error is reported and no reason is found. Can someone tell me why...
3. Final retouching:
If the browser disables javascript, the corresponding JSON will be downloaded as a text file and not rendered as a template when the speaker name is clicked.
You can still rewrite the Details method and add the Details View to solve the problem:
Public ActionResult Details (int id) {var speaker = _ repository. findSpeaker (id); if (Request. isAjaxRequest () {return Json (speaker, JsonRequestBehavior. allowGet); // sequence the speaker into json} return View (speaker );}
@ Model AjaxExamples. models. speaker @ {ViewBag. title = "Details" ;}< h2> spokesman Details: @ Model. fullName
However, you can also use the "Action Method selector" to differentiate Ajax and non-Ajax requests:
1) Add a class inherited from 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(); } }}
If the current action is based on the AcceptAjaxAttribute of the Ajax request, true is returned in the IsValidForRequest method.
2) Split Details into two methods:
[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); }
The first overload of the above method is used to process Ajax requests with the AcceptAjaxAttribute annotation, and the other is used for regular requests.
4. Create an automatic text box (jQuery UI ):
1) download and introduce jQuery UI
2) Add the City model:
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) add analog data and methods:
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) Add a controller:
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) Add a view:
<Link href = "@ Url. Content ("~ /Content/jquery-ui.css ") "rel =" stylesheet "/> <p> <label for =" city "> 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 ("selected" + ui. item. label) ;}};}); </script>
But unfortunately, an error is still reported. The reason should be the same as above. Can someone tell me why...
Source code download password: 53my