How can you make an AJAX link that updates itself in ASP.NET MVC? My colleague Mikkel and I recently had that problem and we couldn't find any guidance on this topic, so now that we have a solution, I thought I'd share it.

The problem is simple: We needed a link that invoked some server side code and updated the text of the link itself based on the result of the operation. Here is a simplified example:

image

Each time you click the link, it should invoke a Controller Action and return a new number that should appear as the link text.

This is pretty simple to implement once you know how. The first thing to realize is that the link and all the AJAX stuff must be placed in a user control. The only thing that needs to go into the containing page is the containing element itself:

<h2>Self-updating AJAX link</h2>
Click the link to update the number:
<span id="thespan">
    <% this.Html.RenderPartial("NumberAjaxUserControl"); %>
</span>

Notice the id of the span element - this same id will be referenced from the user control.

To bootstrap this view, the Controller Action for the page contains code that assigns an initial value to the number (in this case 1):

public ActionResult Index()
{
    this.ViewData["number"] = 1.ToString();
    return this.View();
}

To keep the example simple, I simply add the number to the ViewData dictionary, but in any production implementation, I would opt to use a strongly typed ViewModel instead.

The NumberAjaxUserControl itself only contains the definition of the AJAX link:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
<%@ Import Namespace="System.Web.Mvc.Ajax" %>
<%= this.Ajax.ActionLink((string)this.ViewData["number"],
    "GetNext",
    new { number = this.ViewData["number"] }, 
    new AjaxOptions { UpdateTargetId = "thespan" })%>

The first parameter to the ActionLink method is simply the current number to render as the link text. Since I'm using the untyped ViewData dictionary for this example, I need to cast it to a string.

The next parameter ("GetNext") indicates the Controller Action to invoke when the link is clicked - I will cover that shortly.

The third parameter is a Route Value that specifies that the parameter number with the correct value will be supplied to the GetNext Controller Action. It uses the number stored in ViewData.

The last parameter indicates the id of the element to update. Recall from before that this name was "thespan".

The only missing piece now is the GetNext Controller Action:

public PartialViewResult GetNext(int number)
{
    this.ViewData["number"] = (number + 1).ToString();
    return this.PartialView("NumberAjaxUserControl");
}

In this example I simply chose to increment the number by one, but I'm sure you can imagine that this method could just as well perform a database lookup or something similar.

Notice that the method returns a PartialViewResult that uses the same user control that I used to bootstrap the thespan element. This means that every time the link is clicked, the GetNext method is updated, and the exact same user control is used to render the content that dynamically replaces the original content of the element.


Comments

anonymous
I kind of prefer the jQuery approach, it is much less intrusive: you render your link as usual and then you use the "live" function:

$("a#some_link").live('click', function(){ $('#thespan').load(this.href); });

This will automatically watch for DOM updates of the anchor tag and if it detects any it will automatically rebind the click function.
2009-09-08 07:00 UTC
Thank you for your comment

It looks pretty simple. The following questions are entirely based on my total (and very deplorable) lack of JQuery knowledge:

Will this allow me to query the server with particular parameter values (the number parameter in my example)?
Will it allow me to update the link with the result from the server?

From your snippet, I can't really see where it is specified which URL is requested, what are the query parameters, how the returned result is used to update the link text, etc.
2009-09-08 08:16 UTC


Wish to comment?

You can add a comment to this post by sending me a pull request. Alternatively, you can discuss this post on Twitter or Google Plus, or somewhere else with a permalink. Ping me with the link, and I may add it as a comment.

Published

Monday, 07 September 2009 18:14:39 UTC

Tags



"Our team wholeheartedly endorses Mark. His expert service provides tremendous value."
Hire me!