martes, septiembre 06, 2011

Web Service en PHP consumido desde .Net

Para crear un Web Service en PHP, lo primero que hay que hacer es asegurarnos que tenemos instaladas las librerías NUSOAP. La última versión se puede descargar de http://sourceforge.net/projects/nusoap/. Luego debemos copiarlas al directorio www del servidor Apache (en mi caso utilizo WAMP)

A continuación un php de prueba:

    
        require_once('../lib/nusoap.php');
        $servidor=new soap_server();
        $servidor->configureWSDL('_jaacwsdl','urn:_jaacwsdl');
 
        $servidor->register('_jaac', 
                          array('nombre' => 'xsd:string'),
                          array('return' => 'xsd:string'),
                          'urn:_jaacwsdl',
                          'urn:_jaacwsdl#_jaac',
                          'rpc',
                          'encoded',
                          'este ejecuta _jaac'
                 );
 
        function _jaac($nombre){
                 return "HEY!!! Hola " . $nombre;
        }
 
        $HTTP_RAW_POST_DATA= isset($HTTP_RAW_POST_DATA) ? $HTTP_RAW_POST_DATA : '';
        $servidor->service($HTTP_RAW_POST_DATA);
    ?>

Para utilizarlo desde .Net, hay que añadir una referencia web a http://localhost/nusoap-0.9.5/samples/_jaac.php?wsdl (por ejemplo) y añadir un código similar al siguiente:

    var wsPHP = new PruebaWebServices.localhost._jaacwsdl();
    string ret = wsPHP._jaac("Leonardo da Vinci");

jueves, agosto 18, 2011

AJAX y otras funciones de javascript

En esta entrada del blog anieto2k se muestran algunas funciones interesantes escritas en javascript. Es de destacar la que sirve para obtener datos de un servidor mediante Ajax, y que la adjunto a continuación:

function ajaxObject(url, callbackFunction) {
var that=this;
this.updating = false;

this.update = function(passData,postMethod) {
if (that.updating==true) { return false; }
that.updating=true;
var AJAX = null;
if (window.XMLHttpRequest) {
AJAX=new XMLHttpRequest();
} else {
AJAX=new ActiveXObject("Microsoft.XMLHTTP");
}
if (AJAX==null) {
return false;
} else {
AJAX.onreadystatechange = function() {
if (AJAX.readyState==4) {
that.updating=false;
that.callback(AJAX.responseText,AJAX.status,AJAX.responseXML);
delete AJAX;
}
}
var timestamp = new Date();
if (postMethod=='POST') {
var uri=urlCall+'?'+timestamp.getTime();
AJAX.open("POST", uri, true);
AJAX.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
AJAX.send(passData);
} else {
var uri=urlCall+'?'+passData+'×tamp='+(timestamp*1);
AJAX.open("GET", uri, true);
AJAX.send(null);
}
return true;
}
}
var urlCall = url;
this.callback = callbackFunction || function () { };
}
Uso:
// Función que recibe la respuesta del servidor-
function fin(responseTxt,responseStat) {
alert(responseStat+' - '+responseTxt);
}

//Creamos el objeto ajax(test1) y le indicamos la ruta que ha de seguir para obtener los datos
// que se procesarán en la función fin().
var test1 = new ajaxObject('http://someurl.com/server.cgi',fin);
test1.update();

// Pasamos id=user4379 como parametro a la página indicada.
var test2 = new ajaxObject('http://someurl.com/program.php',fin);
test2.update('id=user4379');

// create a new ajaxObject but we'll overwrite the callback function inside
// the object to more tightly bind the object with the response hanlder.
var test3 = new ajaxObject('http://someurl.com/prog.py', fin);
test3.callback = function (responseTxt, responseStat) {
// we'll do something to process the data here.
document.getElementById('someDiv').innerHTML=responseTxt;
}
test3.update('coolData=47&userId=user49&log=true');

// create a new ajaxObject and pass the data to the server (in update) as
// a POST method instead of a GET method.
var test4 = new ajaxObject('http://someurl.com/postit.cgi', fin);
test4.update('coolData=47&userId=user49&log=true','POST');

martes, junio 14, 2011

Actualización de datos en página web mediante AJAX y JSON

Supongamos que tenemos una página web en la que queremos rellenar una lista o un combo en función de otro dato introducido o seleccionado por el usuario. ¿Cómo podemos hacerlo sin tener refrescar la página? La respuesta es AJAX.

Utilizando la técnica AJAX desde la página web (cliente) mediante Javascript se pueden hacer peticiones de datos al servidor (GET, POST). Para ello se utiliza el objeto XMLHttpRequest como se muestra en el siguiente ejemplo:

<head>
<script type="text/javascript">
    peticion = new XMLHttpRequest();
    function obtenerDatos(url) {
        if (peticion) {
            peticion.open("GET", url, false); // Abrimos la url de forma síncrona (que no es lo habitual en AJAX)
            peticion.send(null); // Enviar la petición, sin datos adicionales.
            document.getElementByID('listaDeDatos').innerHTML = peticion.responseText; //Escribir la respuesta en el campo listaDeDatos
        }
    }
script>
head>
 
<body>
    <button onclick="obtenerDatos('miPagina/datosDeLoQueSea.xml')" >Obtener datosbutton>
    <table>
        <tr>
            <td>
                <span id="listaDeDatos">Pulsar botón para obtener datosspan>
            td>
        tr>
    table>
body>

En el ejemplo anterior se incrusta el fichero de datos datosDeLoQueSea.xml en la página web. Pero si lo que queremos es obtener un conjunto de datos y trabajar con ellos en nuestro fragmente de Javascript, necesitaremos un método en la parte servidor (identificable por una url determinada) que retorne los datos.


public JsonResult Combinaciones(subconjunto)
{
    private MyEntities db = new MyEntities();

    var list = from medida in db.MedidasNeumaticos
where medida.Subconjunto = subconjunto
        select new { Text = medida.Ancho, Value = medida.Ancho };
 
    return this.Json(list.ToList(), JsonRequestBehavior.AllowGet);
}

En este caso, la url a la que se debería llamar en el open es ruta/Combinaciones/225, donde 225 es el parámetro que se le para al método Combinaciones. En peticion.responseText tendremos el resultado. Obsérvese el uso de JSON en vez de XML. La gran ventaja de JSON frente a XML es que para utilizar los datos JSON desde Javascript es suficiente con hacer un eval:


var miObjeto = eval('(' + peticion.responseText + ')');

Esto tiene alguna implicaciones respecto a la seguridad, porque el eval de JavaScript acepta cualquier cádena valida que contenga código JavaScript. Para evitar esto problemas es mejor usar un parser de JSON para JavaScript, que solo acepta JSON valido. El parser permite hacer:

var miObjeto = miobjeto_como_Json_string.parseJSON();

para reconstruir el objeto JavaScript desde su representación textual en JSON y
 
var miobjeto_como_Json_string = miobjeto.toJSONString();

para obtener la representación JSON del objeto, por ejemplo para devolverlo usando técnicas AJAX al servidor.


Un ejemplo utilizando el modo asíncrono:

    var http_request = new XMLHttpRequest();
    var url = "http://example.net/jsondata.php"// Esta URL debería devolver datos JSON
 
    // Descarga los datos JSON del servidor.
    http_request.onreadystatechange = handle_json;
    http_request.open("GET", url, true);
    http_request.send(null);
 
    function handle_json() {
        if (http_request.readyState == 4) {
            if (http_request.status == 200) {
                var json_data = http_request.responseText;
                var the_object = eval("(" + json_data + ")");
            } else {
                alert("Ocurrio un problema con la URL.");
            }
            http_request = null;
        }
    }


Más información en:

http://es.wikipedia.org/wiki/AJAX
http://es.wikipedia.org/wiki/JSON
http://www.json.org/ 
http://geeks.ms/blogs/rcorral/archive/2006/06/23/545.aspx#8422
http://www.elrincondeajax.com/manual-ajax/
http://geekswithblogs.net/michelotti/archive/2008/06/28/mvc-json---jsonresult-and-jquery.aspx

miércoles, abril 20, 2011

Hacer post a una URL externa

En C# podemos utilizar el siguiente código para simular un post a una URL externa para, por ejemplo, saltarnos la página de login si conocemos los datos.


            string FormName = "loginForm";
            string Method = "post";
            string Url = "http://www.workshop-data.com/login.do";
 
            System.Web.HttpContext.Current.Response.Clear();
            System.Web.HttpContext.Current.Response.Write("");
            System.Web.HttpContext.Current.Response.Write(string.Format("", FormName));
            System.Web.HttpContext.Current.Response.Write(string.Format("", FormName, Method, Url));
            System.Web.HttpContext.Current.Response.Write(string.Format("""demouser""false"));
            System.Web.HttpContext.Current.Response.Write(string.Format("""username""xxx"));
            System.Web.HttpContext.Current.Response.Write(string.Format("""password""xxxxxx"));
            System.Web.HttpContext.Current.Response.Write("");
            System.Web.HttpContext.Current.Response.Write("");
            System.Web.HttpContext.Current.Response.End();
 
 
En este caso, estaríamos haciendo un post a www.workshop-data.com desde su pantalla de login pasándole un formulario con los datos pertinentes (usuario y password).

Para averiguar cómo se llama el formulario (en mi caso loginForm) y los campos, se puede utilizar Firebug (ver https://addons.mozilla.org/es-ES/firefox/addon/firebug/).

NOTA: Más info en http://www.c-sharpcorner.com/uploadfile/desaijm/asp.netposturl11282005005516am/asp.netposturl.aspx

viernes, abril 01, 2011

Aplicación web de datos dinámicos

Crear un mantenimiento simple a partir de un conjunto de tablas relacionadas de una base datos SQL es sencillo y rápido en ASP.Net. Pasos a seguir:

  1. Crear un nuevo proyecto de tipo Aplicación web de Linq to SQL (datos dinámicos ASP.NET).
  2. En la pestaña de Explorador de servidores añadir una conexión de datos a la B.DD que nos interesa.
  3. Añadir al proyecto un nuevo elemento de tipo Clases de LINQ to SQL.
  4. En el editor gráfico arrastrar desde la conexión de datos los objectos deseados.
  5. En el fichero Global.asax cambiar "YourDataContextType" por el nuevo tipo de contexto creado en el punto 3, y sustituir ScaffoldAllTables = false por ScaffoldAllTables = true.
... Y listo.

Muestra:

martes, febrero 08, 2011

Control de versiones con Subversion

En primer lugar, ¿qué es/para qué sirve?

Como su propio nombre indica se trata de un software que ayuda a llevar el control de versiones de cualquier aplicación que desarrollemos (es independiente de la plataforma de programación). Facilita la gestión de versiones y mantiene un registro de todos los cambios que se van realizando, con la posibilidad de echarlos atrás en cualquier momento. En entornos en los que trabajan varias personas en un mismo proyecto, es muy recomendable utilizar algo como esto porque permite que cada uno trabaje con una porción del proyecto sin peligro de que el que grabe último machaque las modificaciones de los demás.
 

El repositorio


El repositorio es el almacén del control de versiones. En nuestro caso lo he ubicado en http://192.168.1.187/svn, y en el servidor es E:\SVN. Esta carpeta no es ftp ni está compartida, sino que se trata de un recurso WebDav. Para tener acceso a este repositorio es necesario utilizar un usuario y password.

Si se entra en el repositorio desde el navegador, podréis moveros por una estructura similar a esta:

·         Repositories (raíz de todos los repositorios)
o   DotNetProjects (la carpeta que he creado para alojar los proyectos de .Net)
§  GestInc (el Portal de Gestión de Incidencias Informáticas)
·         trunk (versión actual)
·         tags
o   v1.0 (versión 1.0, foto, no modificar)
·         branches
§  SorteoYofindo.
·         trunk (versión actual)
·         tags
o   v1.0 (versión 1.0, foto, no modificar)
·         branches (para parches)


Aplicaciones en el servidor

En el servidor 192.168.1.187 he instalado 2 aplicaciones (gratuitas):
·         VisualSVN Server, que nos ayuda a gestionar el repositorio. Tiene una consola y un cliente web. Algunas de las cosas para las que va bien:
o   Crear la estructura para alojar un nuevo proyecto (crea las carpetas trunk, tags y branckes)
o   Gestión de usuarios

·         TortoiseSVN. Plugin para el explorador de Windows, que permite facilita:
o   Añadir cualquier documento/fichero al repositorio, mediante la opción Import


Ambas aplicaciones son clientes para Subversion, el “core” del meollo y pueden convivir sin problemas.


Aplicaciones cliente

·         TortoiseSVN, la misma del servidor, en realidad está más pensada para cliente, permitiendo:
o   Obtener cualquier versión de un proyecto/documento/fichero.
o   Comparar versiones
o   Hacer merge de versiones
o   Etc.
·         Plugins para Visual Studio, Eclipse (por si tenemos que hacer algo para Android), etc. En el caso del que me instalado para Visual Studio 2010 (AnkhSVN), permite hacer, entre otras cosas:
o   Abrir una versión de un proyecto del repositorio
o   Hacer Ckeckin/checkout/merge/etc. Ejemplo de modificación de un fichero + “commit changes

jueves, febrero 03, 2011

Aplicaciones abiertas

En muchos proyectos de Tecnologías de la Información tendemos a reinventar la rueda, a invertir tiempo del equipo de desarrollo en reinventar los gestores de contenidos, los blogs, el comercio electrónico… Estos proyectos han sido hechos y rehechos en cientos de ocasiones por diferentes equipos.
Durante todo este tiempo, la comunidad de desarrolladores ha creado iniciativas de colaboración alrededor de estas temáticas. Estos proyectos de la comunidad no son juguetes, son proyectos con cientos de horas de desarrollo invertidas y gran número de implantaciones por todo el mundo. Son gratuitos y altamente personalizables a través de plantillas, aunque en caso de necesitarlo tienen el código fuente disponible para que podamos hacer algún ajuste para nuestro proyecto.
Aquí tienes un pequeño resumen de las aplicaciones web gratuitas más utilizadas. Y recuerda… si ya existe, ¿por qué reinventarlo?


Umbraco CMS es un gestor de contenidos utilizado en más de 85000 sitios web. Es muy fácil de utilizar y de extender, además de las posibilidades de integración con sistemas existentes. Umbraco está basado en tecnología .NET


Wordpress comenzó en el año 2003 como un proyecto para mejorar la tipografía y con pocos usuarios. Desde entonces ha crecido para convertirse en la herramienta de blogging más utilizada del mundo, cientos de miles de sitios con decenas de millones de usuarios en todo el mundo. Wordpress está basado en tecnología PHP.


Joomla! Es un gestor de contenidos de código abierto. Su potente framework para aplicaciones facilita la creación de plugins para extender su funcionalidad a Nuevo ámbitos. La funcionalidad básica de Joomla! facilita la creción de sistemas de inventarios, generación de informes, catálogos de productos, sistemas de e-commerce, directories de necogios y muchos más escenarios. Joomla! esta basado en tecnología PHP.

nopCommerce es la solución lider para comercio electrónico basada en ASP.NET. nopCommerce se puede utilizer y configurar por cualquiera con mínimos conocimientos sobre web y ordenadores. Es una solución segura, escalabrla y extensible. Tiene una sencilla herramienta de administración para gestionar el frontal, clientes, listas, descuentos,… además de soporte multilingüe y multidivisa.

¡Y muchas más!
BlogEngine.NETDrupalScrewTurnWikiMoodledotNetNukeOrchard CMS… seguro que alguna se ajusta a tus necesidades.

Para simplificar la instalación de estos proyectos y sus dependencias, los hemos recogido y empaquetado en una Galería de Aplicaciones Web donde puedes escoger la que más se ajuste a tus necesidades.
Videos Relacionados
Instalación nopCommerce
Instalación Joomla
Instalación Wordpress
Instalación Umbraco
Instalación ScrewTurnWiki
Instalacion Drupal

Además, puedes utilizar la herramientaWebMatrix para descargar la aplicación que prefieras, modificarla y posteriormente publicarla en internet
Wordpress via Webmatrix
Umbraco CMS via WebMatrix
nopCommerce via WebMatrix



martes, enero 25, 2011

Uso de tuplas de C#

Ejemplo de definición de una función que retorna una tupla:


/// 
/// Retorna la asignación (técnico y mail) asociado a cierto tipo de elemento (equipamiento), o, en su defecto, de la categoría a la que pertenece.
/// 
/// Categoría del elemento
/// Tipo del elemento
/// Tupla Técnico/MailTo
public Tuple<Userstring> GetAssignmentForEquipmentType(string equipmentCategoryID, string equipmentTypeID)
{
    using (AIMModelConnection dc = new AIMModelConnection())
    {
        var query =
            from p in dc.EquipmentAssignments
            where (p.EquipmentCategoryID == equipmentCategoryID && p.EquipmentTypeID == equipmentTypeID) || (p.EquipmentCategoryID == equipmentCategoryID && p.EquipmentTypeID == null)
            orderby p.EquipmentCategoryID, p.EquipmentTypeID descending
            select p;
 
        EquipmentAssignment assignment = query.FirstOrDefault<EquipmentAssignment>();
 
        if (assignment != null)
            return Tuple.Create<Userstring>(assignment.User, assignment.CopyMailTo);
        else
            return null;
    }
}


... Y uso

// Obtener asignación en función de categoría y tipo del elemento afectado.
Tuple<Userstring> assignment = GetAssignmentForEquipmentType(equipmentCategory, equipmentType);

if (assignment != null)
{
    if (assignment.Item1 != null)
        this.txtAssignedTo.Text = assignment.Item1.UserName;

    if (assignment.Item2 != null)
        this.txtMailTo.Text = assignment.Item2;
}