Muchas veces se requiere hacer desde el lado cliente llamadas a métodos del lado servidor, sin necesidad de refrescar la página, incluso sin necesidad de disparar eventos. Gracias a AJAX esto es posible, pero con la programación convencional se requiere que un control dispare un evento, por ejemplo que un botón dispare un click, para trapearlo del lado servidor. En ocasiones queremos llamar a métodos del lado servidor sin necesidad de disparar eventos, incluso desde Javascript necesitamos poolear iterativamente alguna función que realice alguna validación contra una base datos, o solamente validar datos iungresados por el usuario. Con los PageMethods podemos disparar un método del lado servidor, directamente desde el código Javascript del lado cliente y obtener el resultado del mismo, e incluso trapear excepciones.
Lo indispensable para que esto funcione, es agregar el atributo EnablePageMethods="true" dentro del ScriptManager. Esto nos habilita un objeto PageMethods en Javascript, el cual contiene una llamada al método del lado servidor con el mismo nombre. Otro requisito es que el método del lado servidor, debe estar decorado con el atributo [WebMethod] y además debe ser obligatoriamente estático (static en C# y shared en VB).
<body onload="$get('TxtNombre').focus();">
<form id="FormDatos" runat="server">
<asp:ScriptManager ID="ScriptManager" runat="server" EnablePageMethods="true" />
Ingresá tu nombre: <input type="text" id="TxtNombre" onblur="Verificar(this.value);" /><span id="Resultado" />
<script language="javascript" type="text/javascript">
function Verificar(nombre) {
PageMethods.VerificarValor(nombre, OnSucceeded, OnFailed);
}
function OnSucceeded(resultado) {
$get("Resultado").innerText = resultado;
}
function OnFailed(error) {
$get("Resultado").innerText = error.get_message();
}
</script>
</form>
</body>
Este es el código del lado aspx, la caja de texto dispara una función Javascript llamada Verificar cuando se pierde el foco (por ejemplo apretando TAB). Desde esta función se llama al método del lado servidor a través de la sentencia "PageMethods.VerificarValor". El método "VerificarValor" recibe un parámetro de tipo texto, y además se le deben agregar los nombres de las dos funciones Javascript que se disparan al retornar desde el servidor al cliente. La función "OnSucceeded" se dispara si anduvo todo bien, y recibe como parámetro el valor devuelto por el método. La función "OnFailed" se dispara si el método del lado servidor dispara una excepción, y recibe como parámetro el objeto "error".
[WebMethod]
public static string VerificarValor(string nombre)
{
if (string.IsNullOrEmpty(nombre))
{
throw new Exception("ERROR: No ingresaste tu nombre.");
}
return "Tu nombre comienza con la letra " + nombre[0].ToString().ToUpper();
}
El código del lado servidor es muy sencillo, recuerden referenciar a "System.Web.Services" para que puedan utilizar web methods.
¿Porqué los métodos web deben ser estáticos?
Es una pregunta que a todos nos surgió al implementar PageMethods por primera vez. Esto se debe a que por un lado, tienen un comportamiento similar a los web services, de hecho el ScriptManager los llama de la misma manera que a un web service convencional. Además tienen una eficiencia muy superior a los postbacks de los UpdatePanels, y esto se debe fundamentalmente a que no envían la información del viewstate ni tampoco crean una instancia de la página, con lo cual tampoco pueden acceder directamente a los valores de los controles de la página, ni tampoco ejecutar otros métodos que dependan de la instancia.