static void

ASP Webforms AJAX

Webforms UpdatePanels

These are very easy way of updating webform sections with ajax. Under the covers it's fairly heavyweight, but for a traditional webform pages it's very effective.
Remember to add EnablePartialRendering

<asp:ScriptManager ID="ScriptManager1" runat="server" EnablePartialRendering="true" />

A ScriptManagerProxy can be used on content pages if the ScriptManager is in a MasterPage
By default, each panel update is fired by its children (ChildrenAsTriggers). Add triggers, either a PostBackTrigger to force a full page refresh, or a AsyncPostBackTrigger to fire a partial update from any control on the page.
Use asp:Timer either inside the UpdatePanel, or outside with a trigger, to refresh at Interval (ms).
Use asp:UpdateProgress (with displayAfter="1000") with a <ProgressTemplate> to show a loading image or text.

For back/forward support (MSDN):

<asp:ScriptManager ID="ScriptManager1" runat="server"
    EnableHistory="true" EnableSecureHistoryState="false"
    onNavigate="ScriptManager1_Navigate">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
    <ContentTemplate>
        <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />
        <asp:Label ID="Label1" runat="server" />
    </ContentTemplate>
</asp:UpdatePanel>

Record the history transitions in code behind with AddHistoryPoint and handle the ScriptManager.OnNavigate event.

protected void Button1_Click(object sender, EventArgs e)
{
    ShowData(DateTime.Now.ToLongTimeString());
}
 
private void ShowData(string s)
{
    Label1.Text = s;
    if (ScriptManager1.IsInAsyncPostBack && !ScriptManager1.IsNavigating)
    {
        ScriptManager1.AddHistoryPoint("History", s, s);
    }
}
 
protected void ScriptManager1_Navigate(object sender, HistoryEventArgs e)
{
    ShowData(e.State["History"]);
}

Asmx ScriptService

Just add the [ScriptService] to the class and [WebMethod].
Client side it's much more lightweight with jQuery (see jQuery notes)

var notify = $("#notification");
$.ajax({
    url: '<%= ResolveClientUrl("~/NotificationService.svc") %>/Load',
    success: function (data) {
        data = data.d ? data.d : data;
        notify.text(data.message);
        notify.show("slow");
    },
    error: function (jqXHR, msg) { notify.show("slow").text("Error: " + msg); }
});

With a POST

$.ajax({
    type: "POST",
    contentType: "application/json",
    url: "WebService.asmx/WebMethodName",
    data: "{}",
    success: function (x) {
        data = data.d ? data.d : data;
        alert(x.Message); }
});

Important: the jQuery data parameter should be quoted (a string - eg use JSON.stringify()), otherwise jQuery URL encodes your object (and asmx MUST be json).
$.getJSON(url) doesn't send the contentType of application/json (apparently) so doesn't work.
You may need to add a jQuery dataFilter to deal with ASP.Net dates (json doesn't have native date support).

Caution: unlike ASP MVC's DefaultDataBinder, the WCF is very fussy so [DataContract] inputs must match the posted json exactly. Here's the pattern:

var data = { category: {
    id: $('#<%= SelectId.ClientID %>').val(),
    name: $('#<%= CategoryName.ClientID %>').val()
    }
};
var s = JSON.stringify(data);
var throbber = $('#<%= Throbber.ClientID %>');
throbber.toggleClass("hidden");
$.ajax({
    type: "POST",
    contentType: "application/json",
    url: "Service1.svc/SaveCategory",
    data: s,
    success: function (data) {
        data = data.d ? data.d : data;
        show(data); },
    error: function (msg) { show(msg); throbber.toggleClass("hidden"); }
});

The contract must match in case.

[DataContract(Name = "category")]
public class Category
{
    [DataMember(Name = "name", IsRequired = false)]
    public string CategoryName { get; set; }
 
    [DataMember(Name = "id", IsRequired = false)]
    public string CategoryId { get; set; }

ASP.Net 3.5+ returns a Json object wrapped with a "d" to prevent XSS. Either
data = data.d ? data.d : data;
or (slightly safer if you return a boolean)
data = data.hasOwnProperty("d") ? data.d : data;

IE json caching: set cache:false.

AjaxMethods

Full details here, but basically you need:

Exposing WCF to Ajax

See also WCF; MSDN RESTful WCF

Use Add New Item = AJAX-enabled WCF Service template.

On service class add

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
 

You can delete all the WCF configuration if you change the .svc to use the WebScriptServiceHostFactory.

<%@ ServiceHost Language="C#" Debug="true" Service="MyWebApp.Service1" CodeBehind="Service1.svc.cs"
Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" %>
 

In WCF, you can authenticate using ASP.Net authentication by creating an svc/endpoint with Service="System.Web.ApplicationServices.AuthenticationService". Enable the services in system.web.extensions/scripting/webServices/authenticationService enabled="true".

WCF vs Ajax ScriptService

AsmxWCF
[ScriptService] [ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[WebMethod] [OperationContract] plus [WebInvoke]/ [WebGet]
Ajax's JavascriptSerializer is better with dictionaries with string keys than WCF's DataContractJsonSerializer, and more flexible with dates