ASP.NET PageMethods: Using Generic Lists

1/15/2010 10:52:18 AM

I was working on a project and decided to get a little bit more "hands-on" with my client-side work.  Instead of trying to do things with server-side controls and an UpdatePanel, I thought I would go ahead and tackle the issue with some ASP.NET PageMethods and some jQuery. I was surprised at the adventure that I got myself into. 

Here is a sample of how to use Generic Lists in the .NET Framework as both a result of PageMethod call and as a parameter of a PageMethod call.  I'll use some players from the 2010 Winter Olympics' Team Canada.  You can download this sample from the attachment at the bottom of the post.

Before we get begin, the following things will be required in this sample:
jQuery
JSON2.js - Used to encode javascript into a JSON object


The Server Side

Let's start with a basic player class in our project. The overloaded constructor is just to decrease the initialization of the list.  The parameterless constructor will be required when we send the list of players back to the server.

public class Player
{
    public String Name { get; set; }
    public String Position { get; set; }
    public int Number { get; set; }

    public Player() { }

    public Player(String name, String position, int number)
    {
        this.Name = name;
        this.Number = number;
        this.Position = position;
    }
}


This is a PageMethod to create a list of players and ship them to the client.  For our methods to be available to the clients, we must assign the WebMethod attribute so the framework will create all of the necessary bits.

[WebMethod]
public static List<Player> GetPlayers()
{
	List<Player> players = new List<Player>();
	players.Add(new Player("Sidney Crosby", "Center", 87));
	players.Add(new Player("Chris Pronger", "Defense", 20));
	players.Add(new Player("Nicklas Lidstrom", "Defense", 5));
	players.Add(new Player("Dany Heatley", "Left Wing", 15));
	players.Add(new Player("Corey Perry", "Right Wing", 10));
	return players;
}



This will be our method that takes a list as a parameter.  For simplicity of the example we'll just report the number of players that were in the list back to the client.

[WebMethod]
public static String SubmitPlayers(List<Player> players)
{
	return String.Format("{0} players submitted", players.Count.ToString());
}

 

The Client Side

Now let's add some markup to our page to interact with the server and the resulting data. Note the use of the ScriptManager's CompositeScript which will combine scripts to reduce the number of files downloaded by the client.

<asp:ScriptManager ID="ScriptMan" runat="server" EnablePageMethods="true">
	<CompositeScript>
		<Scripts>
			<asp:ScriptReference Path="~/jquery.min.js" />
			<asp:ScriptReference Path="~/json2.min.js" />
		</Scripts>
	</CompositeScript>
</asp:ScriptManager>

<button id="getPlayers">Get Players</button>

<ul id="players">
</ul>

<button id="submitPlayers">Submit Players</button>

 

Now that we have our markup, let's add the necessary javascript to get our list and display the results.  

// initialize events on our buttons
$(function() {
	$("#getPlayers").bind('click', function() { getPlayerList(); return false; });

	$("#submitPlayers").bind('click', function() { submitPlayerList(); return false; });
});

function getPlayerList() {
	// call server-side webmethod using jQuery
	$.ajax({
		type: "POST",
		contentType: "application/json; charset=utf-8",
		url: "Default.aspx/GetPlayers",
		data: "{ }", // send an empty object for calls with no parameters
		dataType: "json",
		success: displayPlayers,
		failure: reportError
	});
}

function displayPlayers(result) {
	// ASP.NET encapsulates JSON responses in a property "d"
	if (result.hasOwnProperty("d")) { result = result.d; }
	// iterate through player list and add info to the markup
	var ul = $("#players");
	for (i = 0; i < result.length; i++) {
		var li = $("<li>" + result[i].Name + "," + result[i].Number + "," + result[i].Position + "</li>");
		ul.append(li);
	}        
}

function reportError(msg) {
	if (msg.hasOwnProperty("d")) { msg = msg.d; }
	alert(msg);
}

Things to note about these functions:

  • Since the function we are calling has no parameters, you must send an empty JSON object:  "{ }".  This is not necessary when making the call via the framework's PageMethods function (PageMethods.GetPlayers).
  • The "d" property that ASP.NET uses to encapsulate JSON responses.  We'll simply make sure it is there and pull the data out.  One thing to note about the "d" property is that if you make the call using the framework's PageMethods function (PageMethods.GetPlayers) you will not have to test for "d" because the framework pulls the data up a layer for you.


Now that we have our data on the client side, let's package it back up and send it to the server:

function submitPlayerList() {
	// compile player list from markup
	var players = [];
	var i = 0;
	$("#players li").each(function() {
		var player = {};
		var data = $(this).html().split(",");
		player.Name = data[0];
		player.Number = data[1];
		player.Position = data[2];
		//player.__type = "Player";  // Object type
		players[i] = player;
		i++;
	});
	// wrap our list in a data transfer object
	// note the JSON object containing the list is named the same as our parameter
	var DTO = { "players": players };
	// send list to server
	$.ajax({
		type: "POST",
		contentType: "application/json; charset=utf-8",
		url: "Default.aspx/SubmitPlayers",
		data: JSON.stringify(DTO),  // use JSON2 script to encode transfer object to JSON
		dataType: "json",
		success: submitPlayersResponse,
		failure: reportError
	});
}

function submitPlayersResponse(msg) {
	if (msg.hasOwnProperty("d")) { msg = msg.d; }
	alert(msg);
}

Things to note about this snippet:

  • Since we are working with a list, we'll store out objects in an array
  • To fill the array we create a new object for each player and add the necessary properties
  • We are wrapping the array in a data transfer object (DTO) and naming the object "Players" which matched the parameter in our PageMethod signature.  If the name does not match, the framework will claim that no parameter was submitted for "Players"
  • We use the JSON2 script to encode our data transfer object into JSON for transmission.
  • Again we check for the "d" property since we used jQuery rather than the framework's PageMethods call.

 

That's it folks!  I hope this helps someone else avoid the hassle that I went through.

Attachments:
ASP.NET_PageMethods_Using_Lists.zip

Tags:ASP.NET jQuery
273a0186-8297-4ae7-b325-b42aa6166222

Comments:

No comments yet
Name:
Email: (Your email will not be displayed or distributed in any way)
Comment:
  • © brentman.com 2009-2010 | This site licensed under a Creative Commons license
  • The opinions expressed on this site are my own and not those of my employer.
Log In
 
 
login