A “Web Service”, according to Wikipedia, is any software that is meant to provide computer to computer communication but is typcally comveyed using HTTP.

Just with the Microsoft Development stack there are lots of ways to expose application logic via HTTP.

  • ASMX
  • WCF
  • CSHTML
  • MVC
  • ASHX (ASP.NET Handler)
  • etc..

As we increase our client side user experience we will certainly be adding cient side behaviors with JavaScript, CSS, and in the future HTML5.

As we add dynamic behavior to our web application user interfaces, we’ll be updating the browser stsate with data retrieved by our client side code.

Often , the server side logic that will delivger this code will have no contextual value outside the “Web Page” that calls it.

Enter ASP.NET Page Methods. “Page Methods” live inside an ASP.NET page. They are callable via JavaScript and therefore require no seperate file, endpoint or infrastructure.

Since I (and many of you) have adopted jQuery as your client side development model, and since Microsoft has officially embraced jQuery, I’ve been moving all my new AJAX code to jQuery.

Since a first stab at calling page methods using jQuery syntax might be a bit tricky, I”ve created this demo.

Joel Carlson blogged a sample using an interesting Page Method Factory and I’m using that method (and code) in this demo.

Starting with the standard ASP.NET Web Forms web site template I’ve addede two page methods, one that is “Read Only” (no parameters) and one that sends data and recieves a return value.

When running it looks like this.

The Code-Behind includes only the Page Service Methods. If you doen’t use code-behind your Page Methods will live in your .aspx page.


[sourcecode language=”csharp”]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

//————————————————–+
// Added for access to the WebMethod Atribute |
//————————————————–+
using System.Web.Services;

public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}

[WebMethod()]
public static string TestNoParams()
{
return ‘You called at : ‘ + DateTime.Now.ToString();
}

[WebMethod()]
public static string TestWithParams(string YourName, string YourZipCode)
{
return ‘PAGE : Thanks ‘ + YourName + ‘ from ‘ + YourZipCode;
}
}
[/sourcecode]


There is nothing special about ourpage markup:


[sourcecode language=”xml”]
<%@ Page Title=’Home Page’ Language=’C#’ MasterPageFile=’~/Site.master’
AutoEventWireup=’true’ CodeFile=’Default.aspx.cs’
Inherits=’_Default’ %>

<asp:Content ID=’HeaderContent’ runat=’server’
ContentPlaceHolderID=’HeadContent’>
<script src=’Scripts/jquery-1.4.1.js’ type=’text/javascript’></script>
<script src=’Scripts/Default.js’ type=’text/javascript’></script>
</asp:Content>
<asp:Content ID=’BodyContent’ runat=’server’
ContentPlaceHolderID=’MainContent’>
<h2>Calling ASP.NET Page Methods with jQuery AJAX</h2>
<hr /><br />
Enter Your Name :
<asp:TextBox ID=’TextBoxInName’ runat=’server’ Text=”
ClientIDMode=’Static’ />
<br /><br />
Enter Zip Code :    
<asp:TextBox ID=’TextBoxInZip’ runat=’server’ Text=”
ClientIDMode=’Static’ />
<br /><br /><hr />
<div style=’background-color: #CED9E6’><h2> – Page Methods – </h2></div>
<hr /><br />
<input id=’ButtonPageTestNoParams’ type=’button’ value=’Test No Params’
onclick=’return ButtonPageTestNoParams_onclick()’ />
       
<input id=’ButtonPageTestWithParams’ type=’button’
value=’Test WITH Params’
onclick=’return ButtonPageTestWithParams_onclick()’ />
<br /><br />
<hr />
</asp:Content>
[/sourcecode]


Note the seperation pattern in use here:

The same as my C# code is in a seperate code behind file (Default.aspx/cs), my page specifric JavaScript code is also in a seperate file (Default.js).

See Line #6.

The magic is in the unobtrusive JavaScript.


[sourcecode language=”javascript”]

//————————————————————————–+
// jQuery call AJAX Page Method |
//————————————————————————–+
function PageMethod(fn, paramArray, successFn, errorFn) {
var pagePath = window.location.pathname;
//———————————————————————-+
// Create list of parameters in the form: |
// {‘paramName1′:’paramValue1′,’paramName2′:’paramValue2’} |
//———————————————————————-+
var paramList = ”;
if (paramArray.length > 0) {
for (var i = 0; i < paramArray.length; i += 2) {
if (paramList.length > 0) paramList += ‘,’;
paramList += ”’ + paramArray[i] + ”:” + paramArray[i + 1]
+ ”’;
}
}
paramList = ‘{‘ + paramList + ‘}’;
//Call the page method
$.ajax({
type: ‘POST’,
url: pagePath + ‘/’ + fn,
contentType: ‘application/json; charset=utf-8’,
data: paramList,
dataType: ‘json’,
success: successFn,
error: errorFn
});
}
//————————————————————————–+
// jQuery call AJAX WEB Method |
//————————————————————————–+

function WebMethod(fn, paramArray, successFn, errorFn) {

//———————————————————————-+
// Create list of parameters in the form: |
// {‘paramName1′:’paramValue1′,’paramName2′:’paramValue2’} |
//———————————————————————-+
var paramList = ”;
if (paramArray.length > 0) {
for (var i = 0; i < paramArray.length; i += 2) {
if (paramList.length > 0) paramList += ‘,’;
paramList += ”’ + paramArray[i] + ”:” + paramArray[i + 1]
+ ”’;
}
}
paramList = ‘{‘ + paramList + ‘}’;

//———————————————————————-+
// Call the WEB method |
//———————————————————————-+
$.ajax({
type: ‘POST’,
url: ‘MyWebService.asmx’ + ‘/’ + fn,
contentType: ‘application/json; charset=utf-8’,
data: paramList,
dataType: ‘json’,
success: successFn,
error: errorFn
});
}
//———————————————+
// jQuery AJAX Call Succeeded. |
//———————————————+
function AjaxSucceeded(result) {
alert(result.d);
}

//————————————————+
// jQuery AJAX Call FAILED. |
//————————————————+
function AjaxFailed(result) {
alert(‘SERVICE Failed : ‘ + result.d);
}

//————————————————+
// Client Side No Param Button Event Handler |
//————————————————+
function ButtonPageTestNoParams_onclick() {

PageMethod(‘TestNoParams’, [], AjaxSucceeded, AjaxFailed);

}

//————————————————+
// Client Side WITH Params Button Event Handler |
//————————————————+
function ButtonPageTestWithParams_onclick() {

PageMethod(‘TestWithParams’, [‘YourName’, $(‘#TextBoxInName’).val(),
‘YourZipCode’, $(‘#TextBoxInZip’).val()],
AjaxSucceeded, AjaxFailed);
}
[/sourcecode]


When you click on the “No Params” button the server side page method returns a string that contains the server Data/Time and the client code pops it up in an alert.

Take special note of line 80 in the JavaScript code above. This empty parameter list is required.

Nest, if I enter data into the two text boxes (like name and zip code) and click the “With Params” button, the Page Method uses those vales from the client to build a string and return it to the client where client side JavaScript shows the returned string in an alert.

In the next post I’ll show you why I like Joel Carlson’s factory pattern so much. I can use the same factory to call external web service !!

You can download the working sample [ HERE ]