Twitter Facebook RSS Feed

Llamar a métodos de una página ASP.NET desde JavaScript con jQuery

28
ASP.NETjQuery

Sábado, 16 de abril de 2011 a las 18:12hs por Gustavo Cantero (The Wolf)

Cada vez es más frecuente ver aplicaciones que utilizan AJAX para obtener información de algún proceso del servidor y con ella actualizar la página. Con .NET esto se puede hacer fácilmente utilizando el ScriptManager para llamar a servicios web, pero muchas veces no queremos agregar tanta complejidad porque simplemente necesitamos llamar a un método que nos devuelva, por ejemplo, la hora de nuestro server.

Para hacer lo mencionado podemos crear un WebMethod en nuestra página y llamarlo utilizando jQuery (casi todos los sitios web actualmente utilizan jQuery para alguna tarea).

Vamos a explicar cómo hacerlo creando un ejemplo sencillo, en el cual vamos a tomar dos números ingresados por el usuario en campos de texto, los vamos a enviar al WebMethod donde vamos a sumarlo (esta tarea se va a realizar en el servidor) y luego devolveremos el resultado a la página.
En el código de nuestra página vamos a agregar el método pero teniendo en cuenta que debemos agregarle el atributo “WebMethod” como muestro a continuación:

using System;
using System.Web.Services;
 
namespace Ejemplo
{
    public partial class Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
 
        }
 
        [WebMethod]
        public static double Sumar(double Valor1, double Valor2)
        {
            return Valor1 + Valor2;
        }
    }
}

Pero para que este método pueda ser llamado desde una página también debemos agregar en el web.config la referencia al HttpModule que maneja estas llamadas:

<?xml version="1.0"?>
 
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0" />
    <httpModules>
      <add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </httpModules>
  </system.web>
</configuration>

Con esto ya terminamos de hacer todo lo necesario en .NET para que nuestros scripts puedan utilizar este método. Ahora debemos agregar la llamada desde nuestra página. Para hacerlo debemos agregar el archivo de JavaScript con la librería de jQuery a nuestra página. Podemos descargar esta librería y “apuntar” a este archivo o simplemente podemos hacer que nuestra página la descargue de los servidores de Microsoft, Google o jQuery (en el ejemplo hago esto último). En la página http://docs.jquery.com/Downloading_jQuery podemos ver las distintas opciones de descarga o utilización de los CDN (Content Delivery Network) que podemos utilizar.

Entonces, en nuestra página de ejemplo, agregamos el siguiente elemento de HTML para que obtenga la librería del CDN de Microsoft:

<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.2.min.js" type="text/javascript"></script>

Ahora que tenemos la librería podemos llamar a nuestro método desde nuestra página de la siguiente manera:

$.ajax({
    //Tipo de llamada
    type: "POST",
 
    //Dirección del WebMethod, o sea, Página.aspx/Método
    url: "Default.aspx/Sumar",
 
    //Parámetros para pasarle al método 
    data: '{Valor1: 22, Valor2: 33}', 
 
    //Tipo de contenido
    contentType: "application/json; charset=utf-8",
 
    //Tipo de datos
    dataType: "json",
 
    //Función a la cual llamar cuando se pudo llamar satisfactoriamente al método
    success: resultado,
 
    //Función a la cual llamar cuando se producen errores
    error: errores
});

A continuación les dejo el HTML completo de nuestra página de ejemplo, donde toma los dos números, los envía a nuestro método y luego pone el resultado en otro campo de texto:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.2.min.js" type="text/javascript"></script>
    <script type="text/javascript">
        $(function () {
            $('#btnSumar').click(function () {
                var num1 = $('#num1').val(); //Obtenemos el primer número
                var num2 = $('#num2').val(); //Obtenemos el segundo número
                $.ajax({
                    type: "POST",
                    url: "Default.aspx/Sumar",
                    data: '{Valor1: ' + num1 + ', Valor2: ' + num2 + '}',
                    contentType: "application/json; charset=utf-8",
                    dataType: "json",
                    success: resultado,
                    error: errores
                });
            });
        });
        function resultado(msg) {
            //msg.d tiene el resultado devuelto por el método
            $('#num3').val(msg.d);
        }
        function errores(msg) {
            //msg.responseText tiene el mensaje de error enviado por el servidor
            alert('Error: ' + msg.responseText);
        }
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <br />
        <br />
        <br />
        <input type="text" id="num1" />
        +
        <input type="text" id="num2" />
        <input type="button" value="=" id="btnSumar" />
        <input type="text" id="num3" disabled />
    </div>
    </form>
</body>
</html>

Como verán utilizar WebMethods de ASP.NET desde jQuery es muy sencillo y útil, y puede servirnos en muchas tareas, por ejemplo, en formularios de envío de mail para no tener que recargar la página, para crear campos con “autocomplete”, para obtener información actualizada por otros usuarios sin necesidad de refrescar la página (como hace Facebook), etc.

También les dejo un proyecto con el ejemplo anterior funcionando:

Espero que les sea de utilidad.

Suerte!

VN:F [1.7.3_972]
Rating: 7.5/10 (27 votos cast)

28 comentarios »

  1. Ernesto dice:

    Hola, excelente página.

    Intente desarrollar el efecto de Autocompletar tomando como base tu ejemplo y agregandole una consula a una BD SQL, pero en la lista me devuelve “Undefined”, es decir, si encuentra 3 coincidencias ne la base de datos con la palabra escrita en el cuadro de autocompletar en la lista me aparece varias veces “Undefined”, podiras ayudarme si te envio el ejemplo???

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
  2. Ernesto dice:

    “namespace Ejemplo
    {
    public partial class Materiales : System.Web.UI.Page
    {
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    [WebMethod]
    public static List ObtenerMateriales(string Palabra)
    {
    var dc = new LinqMaterialesDataContext();
    var Resultado = from e in dc.T_AnexoC5
    where e.Concepto.Contains(Palabra)
    select new ListC5 {id=e.Partida, value = e.Concepto };
    return Resultado.ToList ();
    }

    public class ListC5
    {
    public string id { get; set; }
    public string value { get; set; }

    }

    }
    }”

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
    • Hola, Ernesto, perdón por la demora en responder.
      Yo creo que el problema es porque estás devolviendo un objeto “List”, el cual no existe en JavaScript.
      Te recomiendo que lo pases a un vector, como te muestro a continuación:

      [WebMethod]
      public static ListC5[] ObtenerMateriales(string Palabra)
      {
          var dc = new LinqMaterialesDataContext();
          var Resultado = from e in dc.T_AnexoC5
                          where e.Concepto.Contains(Palabra)
                          select new ListC5 { id = e.Partida, value = e.Concepto };
          return Resultado.ToArray();
      }

      Suerte!

      VN:F [1.7.3_972]
      Rating: 0.0/5 (0 votos cast)
  3. Ernesto dice:

    “la parte del Jquerye es esta

    $(function () {
    $(“#TextBox2″).autocomplete({
    source: function (request, response) {
    $.ajax({
    url: “Materiales.aspx/ObtenerMateriales”,
    data: “{ ‘Palabra’: ‘” + request.term + “‘ }”,
    dataType: “json”,
    type: “POST”,
    contentType: “application/json; charset=utf-8″,
    dataFilter: function (data) { return data; },
    success: function (data) {
    response($.map(data.d, function (item) {
    return {
    value: item.Email
    }
    }))
    },
    error: function (XMLHttpRequest, textStatus, errorThrown) {
    alert(textStatus);
    }
    });
    },
    minLength: 2
    });
    });

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
  4. Juan Carlos dice:

    Amigo, solo quisiera hacerle una consulta con respecto a seguridad. Es esto sugúro para por ejemplo implementar este código en un Inicio de sesión? Que pasa si alguien hace ver codigo? mostraría el password escrito por el usuario, ¿no?
    Desde ya muchas gracias.

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
    • El código no contiene el password, por lo cual, es seguro.
      De todas formas siempre está la posibilidad de que alguien snifee la red y vea tu contraseña, para lo cual, lo mejor sería implementar https para encriptar tus comunicaciones entre el javascript (que es el que va a enviar tu password) y el servidor (que es el que va a validar el password).
      Saludos.

      VN:F [1.7.3_972]
      Rating: 0.0/5 (0 votos cast)
  5. Juan Carlos dice:

    Gracias Gustavito. Gracias por responder. De todas maneras puedo encriptarla yo y enviar los datos encriptados para no usar https, verdad?
    Desde ya mil gracias.
    Un gran abrazo desde Argentina.

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
    • El problema es que cualquier podría ver la forma en que encriptás los datos revisando tus scripts y luego desencriptar lo que snifee.
      Para evitar esto deberías hacer un método de encriptación asimétrico. En este artículo tenés explico los distintos métodos de cifrado y otros conceptos de criptografía: Conceptos de Certificado Digital y Firma Digital.
      Otra posibilidad que se me acaba de ocurrir es que calcules el hash de la contraseña y que sea esto lo que enviás al servidor (no la contraseña), para luego compararlo con el hash de la contraseña guardada en la base de datos. En este artículo explico como calcular el hash en .NET: Como calcular el Hash de un vector de bytes o un string y en esta página hay un algoritmo para calcular el hash MD5 desde javascript: JavaScript MD5.
      Suerte!

      VN:F [1.7.3_972]
      Rating: 0.0/5 (0 votos cast)
  6. Jose dice:

    NO me funciono el codigo.
    No hace nada.
    Estoy utilizando Master page y el codigo que pusiste arriba lo estoy usando en el default y no en el master page.
    que puede ser.

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
  7. felipe marin dice:

    muchas gracias por el ejemplo en verdad me sirvio para lo que tenia que hacer solo una duda en el web.config configure el httpModules y generaba un error, pero no lo utilice en el web.config y igual fuciono perfecto

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
  8. tito dice:

    Buen día!

    Tu sugerencia es útil y sencilla, pero ¿es posible evitar que el método “Sumar” sea static?

    Gracias!

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
  9. Bruno dice:

    Hola Gustavo: muy bueno tu blog. Te cuento que estoy desarrollando un Framework para crear aplicaciones sin PostBacks, en donde hago uso y abuso de los WebMethods. Me parece que es la solución cuando las aplicaciones se tornan mas y mas ricas en posibilidades.
    Te invito a participar de esta experiencia, que si no me equivoco, te va a interesar.
    Te mando un abrazo

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
  10. emanuel dice:

    Muy bueno y bien explicado.. Lo he probado con datos de tipo string y me da error. Como lo puedo solucionar

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
    • Fijate que en la columan 14 está armando un JSON como si fueran números, si le ponés string debería tener comillas.
      Prueba cambiando la linea por esto:

                          data: '{Valor1: "' + num1 + '", Valor2: "' + num2 + '"}',

      Suerte!

      VN:F [1.7.3_972]
      Rating: 0.0/5 (0 votos cast)
  11. emanuel dice:

    Ok. Funciona perfecto, muchas gracias!! Saludos

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
  12. emanuel dice:

    Hola, de nuevo por el blog, me gustaria consultar si el parametro que resive el
    evento success que llama a function resultado debe ser siempre un tipo primitivo
    o puede ser tambien un objeto o lista?

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
    • El valor que recibe la función definida en la propiedad “sucess”, en nuestro ejemplo la función de javascript “resultado”, puede recibir un valor complejo. Para esto desde .NET deberías devolver una estructura o clase y el motor te lo convierte en una estructura JSON.
      Aprovecho para recomendarte que, si necesitás devolver datos complejos, crees tus propias clases con la mínima información a devolver, ya que esta info va a viajar por internet y puede generar demoras en la ejecución.
      Saludos.

      VN:F [1.7.3_972]
      Rating: 0.0/5 (0 votos cast)
  13. Jorge Alberto dice:

    Hola Gustavo, con respecto a llamar metodos con jQuery, tengo una pregunta sobre algo relacionado, Como realizar post basados en Cross Domain de Manera Syncrona, algo que pueda funcionar tanto en iExplorer 7 o superiores, Firefox y Chrome! Se que iexplorer tiene el objeto XDomainRequest, que aparece a partir de la version 8, jQuery tiene algo como jsonp, con la particularidad de que son procesos asyncronos!

    Gracias y Saludos!

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
    • Ya hice un par de cosas con JSONP y funcionaba bien, pero nunca de forma sincrónica. Creo que lo mejor sería que hagas un diálogo modal para esperar a que termine llamada.
      Saludos.

      VN:F [1.7.3_972]
      Rating: 0.0/5 (0 votos cast)
  14. Janet dice:

    Hola, me ha servido mucho tu ejemplo, pero para pasar los parámetros que recibe el [webmethod] a otra función dentro del mismo aspx.cs me marca el error “Referencia a objeto no establecida como instancia de un objeto.” justo en la línea en la que mando a llamar la otra función con los parámetros, la pregunta es se tiene que instanciar desde el page o cómo se instancia?

    Este es el código del webmethod

    [WebMethod]
    public static decimal Sumar(decimal Valor0, decimal Valor1, decimal Valor2,decimal Valor3,decimal Valor4,decimal Valor5,decimal Valor6,decimal Valor7, decimal Valor8, decimal Valor9,decimal Valor10, decimal Valor11, decimal Valor12, decimal Valor13, decimal Valor14, decimal Valor15, decimal Valor16, decimal Valor17, decimal Valor18, decimal Valor19)
    {
    int modificado = 0;
    modificado = (new busquedaIni()).depurarControlDoctos(Valor0, Valor1, Valor2, Valor3, Valor4, Valor5, Valor6, Valor7, Valor8, Valor9, Valor10, Valor11, Valor12, Valor13, Valor14, Valor15, Valor16, Valor17, Valor18, Valor19);
    return Valor1 + Valor2;
    }
    y la función depurarControlDoctos

    public partial class busquedaIni : System.Web.UI.Page
    {
    private int depurarControlDoctos(decimal Valor0, decimal Valor1, decimal Valor2,decimal Valor3,decimal Valor4,decimal Valor5,decimal Valor6,decimal Valor7, decimal Valor8, decimal Valor9,decimal Valor10, decimal Valor11, decimal Valor12, decimal Valor13, decimal Valor14, decimal Valor15, decimal Valor16, decimal Valor17, decimal Valor18, decimal Valor19)
    {
    decimal[] valores;
    valores = new decimal[20]{Valor0, Valor1, Valor2, Valor3, Valor4, Valor5, Valor6, Valor7, Valor8, Valor9, Valor10, Valor11, Valor12, Valor13, Valor14, Valor15, Valor16, Valor17, Valor18, Valor19};
    string ControlDoc = “”;
    int indiceCtrlDoc = gvControlDoctos.Rows.Count;
    int modificado;

    for (int i = 0; i < indiceCtrlDoc; i++)
    {
    ControlDoc = gvControlDoctos.DataKeys[i].Values[2].ToString();

    if (!(valores[i].ToString().Equals(ControlDoc)) && !(valores[i].ToString().Equals('0')))
    {
    gvControlDoctos.DataKeys[i].Values[2] = valores[i];
    decimal estatusdoc_id, docto_id;
    estatusdoc_id = Convert.ToDecimal(gvControlDoctos.DataKeys[i].Values[2]);
    docto_id = Convert.ToDecimal(gvControlDoctos.DataKeys[i].Values[0]);
    string matricula = "";
    matricula = gvBusquedaInicial.SelectedDataKey.Values[0].ToString();

    modificado = (new negocioControlDoctos()).modificaCtrlDoctos(matricula, docto_id, estatusdoc_id);
    }

    }
    return Convert.ToInt32(Valor1);
    }
    }

    bueno también hay otras cosas pero según yo éstas son las importantes.

    De antemano gracias por la atención prestada.

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)
    • Janet, el problema es que los webmethods son métodos estáticos que se ejecutan de forma “aislada” del ciclo de vida de la página, por lo cual, la misma no está instanciada ni se puede acceder a ningún control de ésta del lado del servidor.
      Lo que puedes hacer es leer el valor de los controles que necesites en el cliente usando javascript o alguna librería como jQuery y enviar estos valores como parámetros al webmethod.
      Suerte!

      VN:F [1.7.3_972]
      Rating: 0.0/5 (0 votos cast)
  15. Jandy dice:

    Hola, una pregunta: Tengo una MasterPage, en la cual en la parte del html mando a llamar el metodo $.ajax , pero si redirecciono un WebForm (Ejemplo Response.Redirect(Inicio/Presentacion.aspx) ) que no este al nivel de la MasterPage nunca se ejecuta la funcion estatica con el atributo “WebMethod”, en cambio si redirecciono un WebForm que este al mismo nivel (directorio) de la MasterPage (Ejemplo Response.Redirect(Presentacion.aspx) ) la funcion si se ejecuta

    VA:F [1.7.3_972]
    Rating: 0.0/5 (0 votos cast)

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos necesarios están marcados *

Puedes usar las siguientes etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Buscar