Ever since MVC has come out for Asp.Net I have been wanting to understand jQuery. MVC seems like it will make doing client side programming a little easier than web forms because I don’t have to deal with the long client ids and controls using there viewstate values when a postback occurs. The other night I decided to take my first step, I haven’t done a lot of web development lately so that was another motivating factor. A while back I blogged about an extension method I made for paging thru records in MVC. I decided to try and make it so the results could be paged without posting back.

The first thing I did was take the markup I had for displaying the results on my View and move it into a partial view. I made the partial view use the same data type as the whole View. Here is the markup for the partial view:

  1. <% if (Model.Results.Topics != null && Model.Results.Topics.Count > 0)
  2.    {
  3.        foreach (var topic in Model.Results.Topics)
  4.        { %>
  5. <div>
  6.     <span>
  7.         <%= Html.ActionLink(topic.Name, "Index", "Topic", new { id = topic.TopicUId }, null)%></span><br />
  8.     <span>
  9.         <%= Html.Encode(topic.Summary)%></span>
  10. </div>
  11.       <%}  %>
  12. <% int page; %>
  13. <%= Html.Pager(int.TryParse(Request.Params["page"], out page) ? page : 1, Model.Results.PageSize, Model.Results.TopicCount, Request.Params["search"], PagerTypeEnum.Topic)%>
  14.    <%} %>

And here is the markup for the View:

  1. <div class="page-body">
  2.         <h2>
  3.             Search</h2>
  4.         <div class="page-body-content">
  5.                 <% Html.RenderPartial("TopicSearch", Model); %>
  6.         </div>
  7.     </div>

 

Nothing special here, the part to focus on is the pager at the bottom. All the extension method does is take in information about the results and generate page numbers with links similar to a gridview. The only change I made in the extension method was to give the “a” tags it generated a class. I decided to name it “search” for this example. Then in the original View I replaced the markup with the markup to display the partial view above. Then in the header of the page I added the following javascript code to manipulate the links generated by the pager once the page was loaded.

  1. <script type="text/javascript">
  2.         $(document).ready(function() {
  3.             SetupLinks();
  4.         });
  5.  
  6.         function SetupLinks() {
  7.             $("a.search").click(function(event) {
  8.                 event.preventDefault();
  9.                 $.get(this.href.replace("Search", "AjaxSearch"), function(data) {
  10.                 $("div.page-body-content").html(data);
  11.                     SetupLinks();
  12.                 });
  13.             });
  14.         }
  15.         
  16.     </script>

 

What this code is doing is using the jQuery ready function to setup the links once the page is loaded. The SetupLinks function is saying for every “a” tag with the class “search”, set its click function to the following method. The method is telling the link to do a jQuery get and using the inline function to place the result in the div with the class “page-body-content”. Once places the result in the div I am calling the SetupLinks function again to tell it to manipulate the links that just came down in the result. You have to rebind the links otherwise they will behave as they normally do since they weren’t on the page when it was loaded, we got them via the asynchronous request. I adidn’t know the best way to handle this on the controller.  If you notice the Url I am using in the get All I did was a simple string replace for the target Url since other than the controller method in the route everything else was the same. I originally had a Method named “Search” that the Url would route to. I pretty much copied it and made another one called “AjaxSearch” that would only return the partial view instead on the whole view like the “Search” method. The code in the controller looks like this:

  1. //for normal requests
  2.         public ActionResult Search()
  3.         {
  4.             return View(GetSearchView());
  5.         }
  6.  
  7.         //for the jQuery get
  8.         public ActionResult AjaxSearch()
  9.         {
  10.             return View("TopicSearch", GetSearchView());
  11.         }
  12.  
  13.         private Biz.DataTypes.SearchView GetSearchView()
  14.         {
  15.             Entity.SearchCriteria criteria = new Alner.Entity.SearchCriteria();
  16.             criteria.SearchType = Alner.Entity.SearchTypeEnum.Topic;
  17.             criteria.PageSize = 3;// Alner.UI.Properties.Settings.Default.DefaultPageSize;
  18.             int pageNum = criteria.PageNumber = 1;
  19.  
  20.             if (!string.IsNullOrEmpty(Request.Params["search"]))
  21.                 criteria.SearchText = Request.Params["search"];
  22.  
  23.             if (!string.IsNullOrEmpty(Request.Params["page"]))
  24.                 if (int.TryParse(Request.Params["page"], out pageNum))
  25.                     criteria.PageNumber = pageNum;
  26.  
  27.             return new Biz.DataTypes.SearchView(criteria);
  28.         }

 

That’s all there was to it. The next step would be doing a true Ajax call and just replacing the necessary values but I’ll leave that for another day.