Using the fetchParameters property to pass values to the web service method
In the previous posts, we’ve seen how to configure the DataView control so that it gets the data from a remote web service. In this post, we’ll see how we can take advantage of the fetchParameters to pass info to the web service. The idea is simple: we’ll update the previous sample so that it renders a table with clickable headers used for sorting the displayed data. Sorting the data will be done on the server. This means we need to start updating the server side code so that the web service method gets the info used for sorting (notice I’m only showing the changes made to the initial code):
public class PeopleService {
static List<Person> _people = new List<Person>
{
new Person{ Name = "luis", Address = "fx"},
new Person{ Name = "john", Address = "lx"},
new Person{ Name = "peter", Address = "pt"}
};
[OperationContract]
[WebGet]
public IEnumerable<Person> GetPeople(SortOrder sort) {
var ordered = _people.OrderBy(
p => (sort == SortOrder.Name ?
p.Name : p.Address) );
return ordered;
}
}
public enum SortOrder {
Name,
Address
}
As you can see, changes are really minimal: we’ve added an enumeration used for indicating the sort order that should be applied to the collection and we’ve updated the GetPeople method so that it orders the collection accordingly. Now, let’s see the client code:
<head runat="server">
<title></title>
<style type="text/css">
.sys-template{
display: none;
}
</style>
<script src="Scripts/MicrosoftAjax/start.debug.js"
type="text/javascript">
</script>
<script type="text/javascript">
Sys.require([Sys.scripts.jQuery,
Sys.scripts.WebServices,
Sys.components.dataView],
function () {
Sys.loadScripts(
["PeopleService.svc/jsdebug"],
function () {
Sys.Application.activateElement(
Sys.get("#view"));
$("thead td").click(function () {
var view = Sys.get("$view");
view.get_fetchParameters()
.sort =
($(this).text() === "Name" ?
SortOrder.Name :
SortOrder.Address);
view.fetchData();
})
});
});
</script>
</head>
<body xmlns:sys="BLOCKED SCRIPTSys"
xmlns:dv="BLOCKED SCRIPTSys.UI.DataView">
<table>
<thead>
<tr>
<td>Name</td>
<td>Address</td>
</tr>
</thead>
<tbody id="view"
class="sys-template"
sys:attach="dv"
dv:autofetch="true"
dv:httpverb="GET"
dv:dataprovider="{{ PeopleService }}"
dv:fetchoperation="GetPeople"
dv:fetchparameters="{{ { sort: SortOrder.Name } }}">
<tr>
<td>{{name}}</td>
<td>{{address}}</td>
</tr>
</tbody>
</table>
</body>
Most of the code is similar to what we had before. There are, however, some differences:
- I’ve added JQuery to set a click handler to all the TD elements of the header (I still love jQuery :) );
- we’ve attached the DataView control to the tbody element of the table. This is the easiest way to define the templates without ending up with crappy HTML (thanks go once again to Dave Reed for pointing me in the right direction);
- in response to a click event on one of the header TDs, we set the sort parameter to the correct value. In a real world app, I’d check that the user was really asking for a different sorting before starting the remote call which refreshes the control (after all, if the data is already ordered by Name, there really isn’t any need to reorder it again by name, right?);
- after setting everything up, we refresh the data presented by the control by calling the fetchData method. This method will perform the remote call and will automatically refresh the DataView control with the new sorted data.
And there you go: quick and easy, right? Stay tuned for more on MS AJAX.