AJAX Helpers

You've seen the HTML helpers in ASP.NET MVC. You can use the HTML helpers to create forms and links that point to controller actions. There is also a set of AJAX helpers in ASP.NET MVC. AJAX helpers also create forms and links that point to controller actions, but they behave asynchronously. When using these helpers, you don't need to write any script code to make the asynchrony work.

Behind the scenes, these AJAX helpers depend on the unobtrusive MVC extensions for jQuery. To use the helpers, you need to have the jquery.unobtrusive-ajax script present. Because you might be using this functionality in a number of places in the application, you can include this file in the layout view (after including jQuery).

<script src="@Url.Content("∼/Scripts/jquery-1.4.4.min.js")" 
        type="text/javascript"></script>    
<script  src="@Url.Content("∼/Scripts/Scripts/jquery.unobtrusive-ajax.min.js")"
         type="text/javascript"></script>
@RenderSection("scripts", required:false);    

AJAX ActionLinks

AJAX helpers are available through the Ajax property inside a Razor view. Like HTML helpers, most of the methods on this property are extension methods (but for the AjaxHelper type).

The ActionLink method of the Ajax property creates an anchor tag with asynchronous behavior. Imagine you want to add a “daily deal” link at the bottom of the opening page for the MVC Music Store. When users click the link, you don't want them to navigate to a new page, but you want the existing page to magically display the details of a heavily discounted album.

To implement this behavior, you can add the following code into the Views/Home/Index.cshtml view, just below the existing album list:

<div id="dailydeal">
    @Ajax.ActionLink("Click here to see today's special!",
                     "DailyDeal", 
                     new AjaxOptions{ 
                         UpdateTargetId="dailydeal", 
                         InsertionMode=InsertionMode.Replace, 
                         HttpMethod="GET"
                     })
</div>

The first parameter to the ActionLink method specifies the link text, and the second parameter is the name of the action you want to invoke asynchronously. Like the HTML helper of the same name, the AJAX ActionLink has various overloads you can use to pass a controller name, route values, and HTML attributes.

One significantly different type of parameter is the AjaxOptions parameter. The options parameter specifies how to send the request, and what will happen with the result the server returns. Options also exist for handling errors, displaying a loading element, displaying a confirmation dialog, and more. In this scenario, you are using options to specify that you want to replace the element with an id of “dailydeal” using whatever response comes from the server. To have a response available, you'll need a DailyDeal action on the HomeController:

public ActionResult DailyDeal()
{
    var album = GetDailyDeal();

    return PartialView("_DailyDeal", album);
}

private Album GetDailyDeal()
{
    return storeDB.Albums
        .OrderBy(a => a.Price)
        .First();
}

The target action for an AJAX action link can return plain text or HTML. In this case, you'll return HTML by rendering a partial view. The following Razor code will live in a _DailyDeal.cshtml file in the Views/Home folder of the project.

@model MvcMusicStore.Models.Album

<p>
    <img alt="@Model.Title" src="@Model.AlbumArtUrl" />
</p>

<div id="album-details">
    <p>
        <em>Artist:</em>
        @Model.Artist.Name
    </p>
    <p>
        <em>Price:</em>
        @String.Format("{0:F}", Model.Price)
    </p>
    <p class="button">
        @Html.ActionLink("Add to cart", "AddToCart", 
        "ShoppingCart", new { id = Model.AlbumId }, "")
    </p>
</div>

Now when the user clicks the link, an asynchronous request is sent to the DailyDeal action of the HomeController. Once the action returns the HTML from a rendered view, the script behind the scenes takes the HTML and replaces the existing dailydeal element in the DOM. Before the user clicks, the bottom of the homepage would look something like Figure 8.2.

After the user clicks to see the special, the page (without doing a full refresh) looks like something like Figure 8.3.

note
UnFigure

If you want to see the code in action, use NuGet to install the Wrox.ProMvc3.Ajax.ActionLink package. The code in the package depends on data access classes from the MVC Music Store, so it is best to try the package out inside the MVC Music Store project. Once you've installed the package you can navigate to /ActionLink to see the new homepage.

Ajax.ActionLink produces something that will take a response from the server and graft new content directly into a page. How does this happen? In the next section, we'll look at how the asynchronous action link works behind the scenes.

HTML 5 Attributes

If you look at the rendered markup for the action link, you'll find the following:

<a data-ajax="true" data-ajax-method="GET" data-ajax-mode="replace" 
   data-ajax-update="#dailydeal" href="/Home/DailyDeal">
   Click here to see today&#39;s special!
</a>

The hallmark of unobtrusive JavaScript is not seeing any JavaScript in the HTML, and you certainly have no script code in sight. If you look closely, you'll see all the settings specified in the action link are encoded into the HTML element as attributes, and most of these attribute have a prefix of data- (we say they are data dash attributes).

The HTML 5 specification reserves data dash attributes for private application state. In other words, a web browser does not try to interpret the content of a data dash attribute, so you are free to put your own data inside and the data does not influence the display or rendering of a page. Data dash attributes even work in browsers released before an HTML 5 specification existed. Internet Explorer 6, for example, ignores any attributes it doesn't understand, so data dash attributes are safe in older version of IE.

The purpose of the jquery.unobtrusive-ajax file you added to the application is to look for specific data dash attributes and then manipulate the element to behave differently. If you know that with jQuery it is easy to find elements, you can imagine a piece of code inside the unobtrusive JavaScript file that looks like the following:

$(function () {
        $("a[data-ajax]=true"). // do something
    });

The code uses jQuery to find all the anchor elements with the attribute data-ajax holding the value true. The data-ajax attribute is present on the elements that need asynchronous behavior. Once the unobtrusive script has identified the async elements, it can read other settings from the element (like the replace mode, the update target, and the HTTP method) and modify the element to behave accordingly (typically by wiring up events using jQuery, and sending off requests using jQuery, too).

All the ASP.NET MVC AJAX features use data dash attributes. By default, this includes the next topic: asynchronous forms.

AJAX Forms

Let's imagine another scenario for the front page of the music store: You want to give the user the ability to search for an artist. Because you need user input, you must place a form tag on the page, but not just any form—an asynchronous form.

@using (Ajax.BeginForm("ArtistSearch", "Home", 
    new AjaxOptions {
     InsertionMode=InsertionMode.Replace,
     HttpMethod="GET",
     OnFailure="searchFailed",
     LoadingElementId="ajax-loader",
     UpdateTargetId="searchresults",               
  }))
{
    <input type="text" name="q" />
    <input type="submit" value="search" />
    <img id="ajax-loader" 
         src="@Url.Content("∼/Content/Images/ajax-loader.gif")" 
         style="display:none"/>
}

In the form you are rendering, when the user clicks the submit button the browser sends an asynchronous GET request to the ArtistSearch action of the HomeController. Notice you've specified a LoadingElementId as part of the options. The client framework automatically shows this element when an asynchronous request is in progress. You typically put an animated spinner inside this element to let the user know there is some work in progress in the background. Also, notice you have an OnFailure option. The options include a number of parameters you can set to catch various client-side events that flow from every AJAX request (OnBegin, OnComplete, OnSuccess, and OnFailure). You can give these parameters the name of a JavaScript function to invoke when the event occurs. For the OnFailure event, you specify a function named searchFailed, so you'll need the following function to be available at run time (perhaps by placing it in your MusicScripts.js files):

function searchFailed() {
    $("#searchresults").html("Sorry, there was a problem with the search.");
}

You might consider catching the OnFailure event because the AJAX helpers all fail silently if the server code returns an error. If users click the search button and nothing happens, they might become confused. By displaying an error message like you do with the previous code, at least they know you tried your hardest!

The output of the BeginForm helper behaves like the ActionLink helper. In the end, when the user submits the form by clicking the submit button, an AJAX request arrives at the server, and the server can respond with content in any format. When the client receives the response, the unobtrusive scripts place the content into the DOM. In this example, you replace an element with the id of searchresults.

For this example, the controller action needs to query the database and render a partial view. Again, you could return plain text, but you want the artists to be in a list, so the action renders a partial view:

public ActionResult ArtistSearch(string q)
{
    var artists = GetArtists(q);

    return PartialView(artists);
}

private List<Artist> GetArtists(string searchString)
{
    return storeDB.Artists
        .Where(a => a.Name.Contains(searchString))
        .ToList();
}

The partial view takes the model and builds the list: This view is named ArtistSearch.cshtml and lives in the Views/Home folder of the project.

@model IEnumerable<MvcMusicStore.Models.Artist>

<div id="searchresults">
    <ul>
        @foreach (var item in Model) { 
            <li>@item.Name</li>
        }
    </ul>
</div>
note
UnFigure

To run the search code in your own MVC Music Store project, install the Wrox.ProMvc3.Ajax.AjaxForm package using NuGET and navigate to /AjaxForm to see the new home page.

We'll return to this search form later in the chapter to add some additional features. For now, turn your attention to another built-in AJAX feature of the ASP.NET MVC framework—the support for client-side validation.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.14.134.130