Tema 3 – Aplicaciones Distribuidas: Servicios Web

Download Report

Transcript Tema 3 – Aplicaciones Distribuidas: Servicios Web

XML, Distribución y
Componentes
Tema 3 – Aplicaciones Distribuidas:
Servicios Web
http://paginaspersonales.deusto.es/dipina/MasterISW/
Dr. Diego Lz. de Ipiña Gz. de Artaza
http://paginaspersonales.deusto.es/dipina (Personal)
http://www.morelab.deusto.es (Research Group)
http://www.smartlab.deusto.es (Research Lab)
http://www.ctme.deusto.es (Cátedra de Telefónica Móviles)
http://www.tecnologico.deusto.es (Tecnológico-Fundación Deusto)
Temario

Procesamiento XML en .NET (21 y 22 Febrero)


Estándar .NET [XML.NET]
Soporte XML [XML-SAX, XML-DOM, Validación]
 XSL [XPath, XSLT, Scripts, Objetos de extensión]

Aplicaciones distribuidas (23 Febrero, 5 Marzo)

XML/SOAP
 .NET Remoting
 Mensajería

Componentes .NET (6 y 7 Marzo)







Metadatos y Reflexion
Componentes .NET y Enterprise Services
Complementos
Interoperabilidad COM y P/Invoke
COM+ y MTS
MSMQ (colas de mensajes)
Microsoft Communication Foundation (Indigo)
2/78
Contenidos Parte Aplicaciones
Distribuidas



WebServices y SOAP
.NET Remoting
Mensajería
3/78
Introducción I






Los Servicios Web son la piedra angular de la
iniciativa .NET
Los ordenadores hablan unos a otros a través de
la web usando HTTP y otros protocolos.
Un servicio web no tiene interfaz gráfica
Provee una API de métodos que pueden ser
invocados en la web
Diseñados para proveer “servicios”
.NET hace muy sencillo poder crear servicios web
4/78
Introducción II



Futuro en el que los negocios exponen
aplicaciones a clientes como Servicios Web en
los cuales se paga por su uso
Los sistemas de diferentes empresas cooperan
unos con otros a través de la Web
Mientras que DCOM está basado en estándares
propietarios, los Servicios Web lo están en XML y
HTTP
 Son
independientes de la plataforma y del lenguaje
como CORBA, pero más aceptados

En .NET, IIS y la infraestructura ASP.NET
compilan las fuentes, construyen contratos WSDL
y manejan las peticiones y respuestas de los
servicios web.
5/78
SOA

Los servicios web han dado lugar a un nuevo modo de diseñar
sistemas distribuídos:


SOA = colección de servicios


Arquitecturas SOA (Service Oriented Arquitecture)
Más información en http://www.service-architecture.com/
http://msdn.microsoft.com/Longhorn/understanding/pillars/Indigo/def
ault.aspx?pull=/library/en-us/dnbda/html/srorientwp.asp
6/78
SOA Find-By-Execute Paradigm
7/78
Servicios Web

Son un estándar basado en protocolos abiertos como
HTTP y SOAP

SOAP es un vocabulario XML que representa RPCs



http://www.w3.org/TR/SOAP
No necesitas ni Windows ni .NET para escribir servicios
web
Servicio web = aplicación que:




se ejecuta en un servidor web
expone métodos a clientes
escucha peticiones HTTP representando comandos que invocan a
métodos Web
ejecuta métodos web y devuelve resultados
8/78
Servicio Web Hola Mundo I

Creamos el directorio virtual ws:
1.
2.
Hacemos doble click en Herramientas
Administrativas
Doble click en Internet Information Services
9/78
Servicio Web Hola Mundo II

Creamos el directorio virtual ws:
3.
4.
Hacemos clic con el botón derecho del ratón en
Default Web Site y luego seleccionamos
NewVirtual Directory
Seleccionamos el directorio donde vamos a dejar
los fichero accesibles por el contexto ‘ws’
10/78
Servicio Web Hola Mundo III
<%@ WebService Language="C#" Class="HelloService1" %>
// file:
helloservice1.asmx
// description: hello web service - basic version
using System.Web.Services;
[WebService(
Description="A greeting Web service",
Namespace="http://tempuri.org/ws"
)]
public class HelloService1 : WebService {
[WebMethod(Description="Greet by name.")]
public string Greet(string name) {
if (name == "") name = "Stranger";
return "Hello, " + name + "!";
}
}
11/78
Servicio Web Hola Mundo IV


La primera línea indica que el fichero
helloservice1.asmx es un servicio web programado
en C#, contenido en una clase llamada HelloService1
El atributo WebService te permite añadir:



Para definir un método web es necesario etiquetar un
método público con el atributo WebMethod


Una descripción para el servicio web (description)
El espacio de nombres evita colisiones con otros servicios web
creados por otras personas y con el mismo nombre (Namespace)
El parámetro Description describe el método
HelloService1 es derivado de
System.Web.Services.WebService

Esto le da acceso a la propiedad Context de ASP.NET y hace
disponible al servicio web los objetos Request, Response y
Session.
12/78
Servicio Web Hola Mundo V



Para instalar el servicio cópialo al directorio
Inetpub\wwwroot\ws
Lanza tu navegador e introduce la url:
http://localhost/ws/helloservice1.asmx
La página visualizada es generada por
DefaultWsdlHelpGenerator.aspx

Si quieres que la apariencia de tus servicios web varíe modifica


C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\CONFIG
\DefaultWsdlHelpGenerator.aspx
Y la entrada helpgenerator en
C:\WINDOWS\Microsoft.NET\Framework\<version>\CONFIG
\machine.config
13/78
Servicio Web Hola Mundo VI

Propiedades de los servicios web en .NET:
servicios web se implementan en ficheros asmx
 Todo servicio web comienza con la directiva
@WebService
 Los


Debe contener al menos el atributo Class identificando a la
clase que representa al servicio
Otros atributos opcionales que se pueden utilizar son ‘name’ y
‘description’, que aparecerán en la página web producida al
invocar calc.asmx
 HTTP,
XML y SOAP están escondidos
 Se pueden invocar usando HTTP GET y POST, aparte
de SOAP
14/78
Servicio Web Hola Mundo VII

Un mensaje SOAP es como un sobre moviéndose de un
lugar a otro



El WSDL generado soporta tres protocolos:




HelloService1 define un método Greet que cuando es
llamado devuelve un resultado
Tanto la petición como la respuesta son mensajes SOAP
HttpGet  usa HTTP GET para invocar el servicio
HttpPost  usa HTTP POST
SOAP
Sólo SOAP puede representar tipos de datos complejos y
lo usaremos de ahora en adelante.
15/78
Servicio Web Hola Mundo VIII
16/78
Servicio Web Suma y Resta I
<%@ WebService Language="C#" Class="CalcService" %>
using System;
using System.Web.Services;
[WebService (Name=“Servicio Web Calculadora",
Description=“Ejecuta sumas y restas simples sobre la web")]
class CalcService
{
[WebMethod (Description=“Calcula la suma de dos enteros")]
public int Add (int a, int b)
{
return a + b;
}
[WebMethod
(Description=“Calcula la diferencia de dos enteros")]
public int Subtract (int a, int b)
{
return a - b;
}
}
17/78
Servicio Web Suma y Resta II


Para desplegar la aplicación copia calc.asmx a
C:\Inetpub\wwwroot\ws
La invocación de http://localhost/ws/calc.asmx, para sumar 2 y 2,
produce:
POST /calc.asmx HTTP/1.1
Host: localhost
Content-Type: text/xml; charset=utf-8
Content-Length: 338
SOAPAction: http://tempuri.org/Add
<?xml version=“1.0” encoding=“utf-8”?>
<soap:Envelope xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd=http://www.w3.org/2001/XMLSchema
xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/>
<soap:Body>
<Add xmlns=http://tempuri.org/>
<a>2</a>
<b>2</b>
</Add>
</soap:Body>
<soap:Envelope>
18/78
Servicio Web Suma y Resta III

La respuesta del servicio web es:
HTTP/1.1 200 OK
Content-Type: text/xml; charset=utf-8
Content-Length: 353
<?xml version=“1.0” encoding=“utf-8”?>
<soap:Envelope xmlns:xsi=http://www.w3.org/2001/XMLSchemainstance xmlns:xsd=http://www.w3.org/2001/XMLSchema
xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/>
<soap:Body>
<AddResponse xmlns=http://tempuri.org/>
<AddResult>4</AddResult>
</AddResponse>
</soap:Body>
<soap:Envelope>
19/78
Implementación de servicios web
La parte más complicada para escribir
servicios web es procesar las peticiones
XML que llegan vía HTTP y generar las
respuestas HTTP
 .NET refugia al programador de los detalles
de bajo nivel de HTTP, SOAP y XML

20/78
Creando Servicios webs:
calc.asmx III
21/78
Creando Servicios webs:
calc.asmx IV

Si invocamos el formulario que aparece al ir a
http://localhost/ws/calc.asmx, haciendo clic en el enlace
Add, generado por ASP.NET obtenemos:
22/78
Creando Servicios webs:
calc.asmx V

Los formularios que genera ASP.NET de los ficheros ASMX
permiten probar los servicios web que escribes, sin desarrollar
un cliente web.
23/78
Code-Behind I


Sirve para mover las clases de un ASMX a una
DLL separada.
El ASMX
(wwwroot\wscodebehingwebservice.asmx)
contendría sólo una sentencia:
 <%@

Para compilar la clase utilizaríamos:
 csc

WebService Class=“CalcService” %>
/t:library calc.cs
Moveríamos el DLL a: wwwroot\ws\bin
24/78
Code-Behind II
// fichero: calc.cs
using System;
using System.Web.Services;
[WebService (Name=“Servicio Web Calculadora",
Description=“Ejecuta sumas y restas simples sobre la web")]
class CalcService
{
[WebMethod (Description=“Calcula la suma de dos enteros")]
public int Add (int a, int b)
{
return a + b;
}
[WebMethod
(Description=“Calcula la diferencia de dos enteros")]
public int Subtract (int a, int b)
{
return a - b;
}
}
25/78
La clase base WebService
Opcionalmente hacemos que los servicios web deriven de
System.Web.Services.WebService
 Provee objetos como Application, Session,
Context, Server y User a la clase derivada,
permitiendo al servicio web acceder a los objetos
ASP.NET
class CalcService: WebService
{
…
}

26/78
El atributo WebMethod


Etiqueta a un método como método Web
Soporta los siguientes parámetros:






BufferResponse  permite bufear repuestas
CacheDuration  cachea respuestas generadas por este
método
Description  añade una descripción textual a un método
EnableSession  permitir añadir estado de sesión a un método
MessageName  le da un nombre al método
TransactionOption  especifica el comportamiento de
transacción del método web
27/78
Ejemplos parámetros WebMethod
I

Cachea la salida por 10 segundos
[WebMethod (CacheDuration=“10”)]
public string GetCurrentTime ()
{
return DateTime.Now.ToShortTimeString();
}

Guarda estado a través de las invocaciones en una sesión:
class CalcService: WebService
{
[WebMethod (EnableSession=“true”,
Description=“Añade un elemento a la
cesta”
public void AddToCart(Item item)
{
ShoppingCart cart =
(ShoppingCart)Session[“MyShoppingCart”];
cart.Add(item);
}
}
28/78
Ejemplos parámetros WebMethod
II

No se pueden sobreescribir métodos en servicios
web
Solución: usar el parámetro MessageName, que da un
nombre al método diferente al método que implementa
[WebMethod (MessageName=“AddInts”)]
public int Add (int a, int b)
{
return a+b;
}


Los métodos web podrían ahora llamarse AddInts y
AddFloats
29/78
Web Services Description
Language (WSDL) I

Para exportar la interfaz y metadatos ofrecidos por un
servicio web (su CONTRATO) usamos WSDL.





WSDL es un vocabulario XML estándar documentado en
http://www.w3.org/TR/wsdl.


Métodos web exportados
Protocolos soportados
Las firmas de los métodos
Localización del servicio (URL)
Estas descripciones pueden guardarse en un repositorio UDDI
No entraremos en detalles ya que WSDL es para
máquinas, no humanos, y .NET genera los ficheros WSDL
de un servicio web muy sencillamente:

http://localhost/calc.asmx?wsdl
30/78
Web Services Description
Language (WSDL) II
31/78
Web Services Description
Language (WSDL) III

Si miramos al fichero WSDL encontraremos:





Elemento service que describe el servicio web
Elementos operation que documentan las operaciones
Elementos binding que documentan los protocolos soportados
por el servicio web
Etc.
Para publicar un servicio web deberemos publicar su
contrato, WSDL.


Otros desarrolladores pueden utilizar el contrato para desarrollar
clientes web
Nomalmente procesan el fichero WSDL a través de una
herramienta que genera clases wrapper
 En .NET se llama wsdl.exe
32/78
Tipos de datos complejos en
Servicios Web



¿Cómo se pasan estructuras de datos e instancias de
objetos en servicios web?
Son soportados porque cualquier tipo de dato puede
representarse en XML
El siguiente fragmento de código ilustra la utilización del
tipo de dato complejo Bookstore


El WSDL del servicio web proveerá el schema de este tipo de
dato.
Dos dificultades en la utilización de servicios web con
tipos complejos:


No se pueden invocar estos servicios web usando HTTP GET y
POST  todavía podemos usar SOAP
Todos los campos o propiedades de una clase a serializar
deben ser públicas
33/78
Locator.asmx I
<%@ WebService Language="C#" Class="LocatorService" %>
using
using
using
using
System;
System.Web.Services;
System.Data;
System.Data.SqlClient;
[WebService (Name="Bookstore Locator Service",
Description="Retrieves bookstore information from
the Pubs database")]
class LocatorService
{
[WebMethod (Description="Finds bookstores in a
specified state")]
public Bookstore[] FindStores (string state)
{
return FindByState (state);
}
34/78
Locator.asmx II
Bookstore[] FindByState (string state)
{
SqlDataAdapter adapter = new SqlDataAdapter
("select * from stores where state = \'" + state + "\'",
"server=DIPINA;database=pubs;uid=sa;pwd=ingeborg");
DataSet ds = new DataSet ();
adapter.Fill (ds);
DataTable table = ds.Tables[0];
Bookstore[] stores = new Bookstore[table.Rows.Count];
for (int i=0; i<table.Rows.Count; i++) {
stores[i] = new Bookstore (
table.Rows[i]["stor_name"].ToString ().TrimEnd
(new char[] { ' ' }),
table.Rows[i]["stor_address"].ToString ().TrimEnd
(new char[] { ' ' }),
table.Rows[i]["city"].ToString ().TrimEnd
(new char[] { ' ' }),
table.Rows[i]["state"].ToString ().TrimEnd
(new char[] { ' ' })
);
}
return stores;
}
}
35/78
Locator.asmx III
public class Bookstore
{
public string Name;
public string Address;
public string City;
public string State;
public Bookstore () {}
public Bookstore (string
string
string
string
{
Name = name;
Address = address;
City = city;
State = state;
}
}
name,
address,
city,
state)
36/78
Locator.asmx IV
37/78
Web Service Discovery – DISCO


¿Cómo encontrar un servicio web?
Dos soluciones:

DISCO


Universal Description, Discovery and Integration (UDDI)




Directorio global de servicios web implementado como un servicio web
Un fichero DISCO en tu servidor web describe los servicios web
disponibles en él.


Mecanismo basado en ficheros para el descubrimiento de servicios locales
Fichero XML que tiene un enlace a un contrato WSDL
Los clientes pueden interrogar el fichero DISCO para encontrar
servicios y sus contratos en forma de WSDL.
Para procesar un fichero DISCO se necesita saber la URL donde se
encuentra definido
Para generar un fichero DISCO: http://<url-servicioweb.asmx>?DISCO

También se pueden generar los documentos DISCO usando la utilidad
disco.exe
38/78
Ejemplo DISCO


El documento DISCO contiene un enlace al contrato WSDL
y un enlace a la documentación del mismo (docRef)
También provee la dirección e información binding del
servicio
39/78
Creando un fichero default.disco



Apunta a otros documentos DISCO construyendo una jerarquía de
búsqueda
Podríamos colgar este fichero de “http://<url-miempresa>/default.disco”
El contenido de este fichero sería:
<?xml version=“1.0” encoding=“uft-8”?>
<discovery
xmlns:xsi="http://www.w3.org/2001/XMLSchemainstance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.xmlsoap.org/disco/">
<discoveryRef
ref="http://localhost/ws/helloservice1.asmx?DISCO/">
<discoveryRef
ref="http://localhost/ws/helloservice2.asmx?DISCO/">
</discovery>
40/78
UDDI

UDDI es una especificación para construir bases de datos
distribuidas que permiten a las partes interesadas
“descubrir” los servicios web de las otras



Similar a las páginas amarillas
Un portal UDDI es en si mismo un servicio web.
UDDI define un par de APIs SOAP:



Una API para consultas (enquiry) para realizar consultas sobre
compañías y sus servicios web
Una API para publicar los servicios web de una empresa.
Cualquiera lo puede consultar, pero el acceso a la API de
publicación está normalmente restringido a miembros registrados.


https://uddi.ibm.com/testregistry/registry.html
http://uddi.microsoft.com
41/78
Clientes de Servicios Web I



Aplicaciones que usan o consumen servicios web
Herramienta Wsdl.exe de .NET facilita esta tarea
Web Service Proxy


Objeto local que provee una representación local de un Servicio
Web
Wsdl.exe genera clases proxy de Servicios Web

Invocar métodos en el servicio web es tan sencillo como invocar métodos en el
proxy
CalculatorWebService calc = new CalculatorWeb
Service ();
int sum = calc.Add (2, 2);
42/78
Clientes de Servicios Web II


Los métodos en el proxy tienen el mismo nombre que los nombres en el
servicio web
El proxy encapsula los detalles de bajo nivel de invocación del servicio
web


Invoca al servicio web traduciendo las invocaciones en SOAP y las
respuestas en XML a los tipos de datos del proxy
Generar el proxy es tan sencillo como pasarle la URL de un WSDL al
programa wsdl: wsdl http://tempuri.org/ws/calc.asmx?wsdl





Si el servicio web no fue realizado con .NET se puede bajar el WSDL y
pasarle el path local al fichero
Para dar un nombre al proxy usar el parámetro /out:NombreProxy.cs
Si deseas generar el proxy en VB, usa /language:vb
Para encapsular en un namespace, usa /namespace:Calc
Se puede incluso cambiar el protocolo de invocación por defecto (SOAP)



/protocol:httpget
/protocol:httppost
Con Visual Studio.NET sólamente hay que añadir una referencia web a
tu proyecto y los proxies generados son añadidos a tu proyecto
43/78
Cliente Web Sencillo

Pasos para escribir un cliente para Calc.asmx:
1.
2.
3.
4.
wsdl http://localhost/ws/calc.asmx
Crear una nueva clase ClienteCalculadora.cs
Compilar esa clase: csc CalcClient.cs
CalculatorWebService.cs
Ejecutar ClienteCalculadora.exe
44/78
ClienteCalculadora.cs
using System;
class MyApp
{
public static void Main ()
{
CalculatorWebService calc = new
CalculatorWebService ();
int sum = calc.Add (2, 2);
Console.WriteLine ("2 + 2 = " + sum);
}
}
45/78
Invocaciones asíncronas



Si abres el fichero CalculatorWebService.cs observarás que
wsdl genera wrappers tanto síncronos como asíncronos por cada
método del servicio web
Las invocaciones asíncronas son útiles cuando la ejecución de un
método puede tardar un largo periodo
Para el método Add del servicio web encontraríamos los siguientes
métodos:

BeginAdd  inicia la petición asíncrona y devuelve control


EndAdd  se bloquea hasta que la invocación finaliza



IAsyncResult res = calc.BeginAdd (2, 2, null, null);
int sum = calc.EndAdd (res);
res.IsCompleted  esta propiedad indica si la invocación ha
finalizado
Lo mejor es usar un AsyncCallback delegate que te avise a través
de un método de callback cuando la invocación ha finalizado
46/78
Ejemplo Invocación Asíncrona I
using System;
using System.Threading;
class MyAsyncApp
{
private bool waitingOnReply = true;
public MyAsyncApp()
{
CalculatorWebService calc = new CalculatorWebService ();
AsyncCallback ac = new AsyncCallback
(this.AddCompletedCallback);
IAsyncResult res = calc.BeginAdd (2, 2, ac, calc);
// Se bloquea esperando entrada de consola
while (this.waitingOnReply) Thread.Sleep(500);
Console.WriteLine("Done!");
}
47/78
Ejemplo Invocación Asíncrona II
private void AddCompletedCallback (IAsyncResult res)
{
CalculatorWebService calc =
(CalculatorWebService)res.AsyncState;
int sum = calc.EndAdd (res);
Console.WriteLine ("Callback 2 + 2 = " + sum);
this.waitingOnReply = false;
}
public static void Main ()
{
new MyAsyncApp();
}
}
48/78
Invocando Servicios Web a través de
Servidores Web Proxy

Dos opciones:
 wsdl
/proxy:http://myproxy http://localhos
t/ws/calc.asmx
 El segundo modo es inicializar la propiedad Proxy del
Servicio Web:
El parámetro ‘true’ de WebProxy indica que las invocaciones a
direcciones locales no deben pasar por el servidor proxy
CalculatorWebService calc =
new CalculatorWebService ();
calc.Proxy = new WebProxy
(http://myproxy, true);
int sum = calc.Add (2, 2);

49/78
Autenticación de Clientes de
Servicios Web


¿Quién invoca mi servicio web? ¿A quién tengo
que cobrar?
Tres soluciones:
 Cada
invocador autorizado debe pasar una clave como
parámetro en sus invocaciones
 Trasmitir nombres de usuario y contraseñas en
cabeceras de autenticación HTTP
 Transmitir credenciales en cabeceras SOAP
50/78
Cabeceras SOAP para
Autenticación

Proteger método Add requiriendo que se introduzca un
nombre de usuario y una cabecera
Para crear una cabecera SOAP es necesario definir una nueva
clase que deriva de
System.Web.Services.Protocols.SoapHeader
 El atributo SoapHeader añadido a un método web le indica a
ASP.NET que rechace invocaciones (lance
SoapHeaderExceptions) a invocaciones del método sin esta
cabecera
[SoapHeader ("header", Required="true")]
 En el siguiente ejemplo este atributo mapearía AuthHeaders al
campo header de la clase SafeService

51/78
SafeCalc.asmx
<%@ WebService Language="C#" Class="SafeService" %>
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
public class AuthHeader : SoapHeader
{
public string UserName;
public string Password;
}
class SafeService
{
public AuthHeader header;
[WebMethod]
[SoapHeader ("header", Required=true)]
public int Add (int a, int b)
{
if (header.UserName == “diego" &&
header.Password == “ipina")
return a + b;
else
throw new HttpException (401, "Not authorized");
}
}
52/78
SafeCalc.asmx en detalle

El tipo de datos AuthHeader se define en el contrato WSDL.
Cuando wsdl genera el proxy también genera la definición de AuthHeader y añade el campo
AuthHeaderValue a SafeService.
 Si asigna un objeto de tipo AuthHeader a este campo se transmitirá una cabecerá SOAP con su
valor.
 La petición SOAP saliente tendría la siguiente forma:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd=http://www.w3.org/2001/XMLSchema
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Header>
<AuthHeader xmlns="http://tempuri.org/">
<UserName>diego</UserName>
<Password>ipina</Password>
</AuthHeader>
</soap:Header>
<soap:Body>
<Add xmlns="http://tempuri.org/">
<a>2</a>
<b>2</b>
</Add>
</soap:Body>
</soap:Envelope>

53/78
SafeCalcClient.cs
using System;
class SafeCalcClient
{
public static void Main ()
{
SafeService calc = new SafeService ();
AuthHeader header = new AuthHeader ();
header.UserName = “diego";
header.Password = “ipina";
calc.AuthHeaderValue = header;
int sum = calc.Add (2, 2);
Console.WriteLine ("2 + 2 = " + sum);
}
}
54/78
Más sobre Autenticación


Una variación de esta técnica es incluir un manejador de
peticiones Application_Authenticate en el fichero
Global.asax
Por último se puede configurar IIS para requerir acceso de
autenticación al directorio donde se encuentra el servicio
web, a través del fichero Web.config. Luego derivar la
clase que implementa el servicio web de
System.Web.Services.WebService y usar la propiedad
User par obtener el nombre de usuario de invocador.
55/78
Manteniendo estado en Servicios
Web


Los servicios web funcionan como el modelo de activación
SingleCall de .NET Remoting
No mantienen estado como HTTP, sin embargo:


Pueden hacer uso de las capacidades de manejo de estado de
ASP.NET
Ejemplo: Hola mundo que cuenta las veces que se invoca
al servicio

Como si fuese el modo de activación Singleton de .NET
Remoting
56/78
Servicio Web con Estado I
<%@ WebService Language="C#" Class="HelloService2" %>
// file:
helloservice2.asmx
using System.Web.Services;
[WebService(Description="A stateful greeting Web service",
Namespace="http://tempuri.org/ws")]
public class HelloService2 : WebService {
public HelloService2() {
if (newSession) {
newSession = false; // no longer a new session
numInst = 0;
// no instances so far
numGreet = 0;
// no greetings yet either
}
numInst++;
}
[WebMethod(
Description="Greet by name.",
EnableSession= true
)]
public string Greet(string name) {
numGreet++;
if (name == "") name = "Stranger";
return "Hello, " + name + "!";
}
57/78
Servicio Web con Estado II
[WebMethod(
Description="Get number of greetings.",
EnableSession= true
)]
public int NumGreet() {
return numGreet; // return private property
}
[WebMethod(
Description="Get number of times constructor invoked.",
EnableSession= true
)]
public int NumInst() {
return numInst; // return private property
}
private bool newSession {
// wraps Session["newSession"] in a private property
get {
if (Session["newSession"] == null) return true;
return (bool) Session["newSession"];
}
set {
Session["newSession"] = value;
}
}
58/78
Servicio Web con Estado III
private int numGreet {
// wraps Session["newGreet"] in a private property
get {
return (int) Session["numGreet"];
}
set {
Session["numGreet"] = value;
}
}
private int numInst {
// wraps Session["newInst"] in a private property
get {
return (int) Session["numInst"];
}
set {
Session["numInst"] = value;
}
}
}
59/78
Servicio Web con Estado IV




Usa la propiedad Session para hacer referencia
HttpSessionState
numInst guarda el número de veces que se invoca el
constructor
numGreet el número de veces que se invoca el método
Greet
El atributo WebMethod debe asignar la propiedad
EnableSession=true para que el método pueda usar
estado

Usaremos cookies en el cliente

Con el switch /state permitiendo cookies el número correcto de
invocaciones es devuelto  .NET Remoting client-activated
60/78
Cliente con Estado
// file:
helloclient2.cs
// compile: csc /out:helloclient2.exe helloclient2.cs helloservice2.cs
namespace Hello {
using System;
using System.Net;
class HelloClient2 {
public static void Main(string[] args) {
HelloService2 h = new HelloService2();
string argLine = String.Join(" ", args).ToLower() + " ";
if (argLine.IndexOf("/state") >= 0)
h.CookieContainer = new CookieContainer(); // enable state
else
h.CookieContainer = null; // stateless
for (int i = 0; i < 3; i++) {
Console.WriteLine(h.Greet(“Diego"));
Console.WriteLine("Num. Greet.: {0}", h.NumGreet());
Console.WriteLine("Num. Inst.: {0}", h.NumInst());
}
}
}
}
61/78
Otro Ejemplo Autenticación I
<%@ WebService Language="C#" Class="StringCaseService" %>
// file:
stringcaseservice.asmx
// description: A web service to change string case. Requires user to
login first.
using System.Web.Services;
using System.Security;
[WebService(Description="A web service to change case. Requires login.",
Namespace="http://tempuri.org/ws")]
public class StringCaseService : WebService {
[WebMethod(Description="Login with username and password.",
EnableSession= true)]
public bool Login(string username, string password) {
loggedIn = false; // logout existing user, if any
if (username == “diego" && password == “ipina")
loggedIn = true;
return loggedIn;
}
[WebMethod(Description="Logout.",
EnableSession= true)]
public void Logout() {
loggedIn = false; // logout existing user
}
62/78
Otro Ejemplo Autenticación II
[WebMethod(Description="Uppercase a string. Must be logged in to
call.",
EnableSession= true)]
public string ToUpper(string s) {
requireLogin();
return s.ToUpper();
}
[WebMethod(Description="Lowercase a string. Must be logged in to
call.",
EnableSession= true)]
public string ToLower(string s) {
requireLogin();
return s.ToLower();
}
[WebMethod(Description="Return string length.")]
public int GetLength(string s) {
// login not necessary...
return s.Length;
}
63/78
Otro Ejemplo Autenticación III
private void requireLogin() {
if (!loggedIn)
throw new SecurityException("Client not logged in!");
}
private bool loggedIn {
get {
if (Session["loggedIn"] == null) return false;
return (bool) Session["loggedIn"];
}
set {
Session["loggedIn"] = value;
}
}
}
64/78
Otro Ejemplo Autenticación IV


stringcaseservice.asmx permite la
conversión a mayúsculas o minúsculas de un
string
Lanza un SecurityException si el cliente no
ha hecho login
65/78
Otro Ejemplo Autenticación V
// file:
stringcaseclient.cs
// compile: csc /out:stringcaseclient.exe stringcaseservice.cs stringcaseclient.cs
namespace StringCase {
using System;
using System.Net;
class StringCaseClient {
public static void Main(string[] args) {
StringCaseService scs = new StringCaseService();
scs.CookieContainer = new CookieContainer(); // enable state
string s = "Hello";
Console.WriteLine("length of {0} : {1}", s, scs.GetLength(s));
Console.WriteLine("logging in mmouse:secret : {0}",
scs.Login(“loginPrueba", “clavePrueba")
);
Console.WriteLine("logging in diego:ipina : {0}",
scs.Login(“diego", “ipina")
);
Console.WriteLine("ToUpper {0} : {1}", s, scs.ToUpper(s));
Console.WriteLine("ToLower {0} : {1}", s, scs.ToLower(s));
Console.WriteLine("Logging out...");
scs.Logout();
Console.WriteLine("Logged out.");
// following call will raise a client-side SoapException...
Console.WriteLine("ToLower {0} : {1}", s, scs.ToLower(s));
}
}
}
66/78
Otro Ejemplo Autenticación VI


Usamos cookies para soportar estado de sesiones
Para implementar bien un sistema de logeo, el servicio
debería usar Secure Sockets Layer (SSL)


Si no el nombre de usuario y clave van en claro por la red
De hecho, debería implementarse un servicio de login en
vez de como parte de un servicio mayor
67/78
Estado sin cookies

Se puede utilizar la identidad de un cliente para generar una clave con la sesión de
duración
[WebMethod(Description=“Login to Web Service”)]
public string Login(string username, string password) {
if (isSubscriber(username, password))
{
string key = genKey(userName,
Context.Request.UserHostAddress,
DateTime.Now.ToString());
addKey(key, username);
return key;
}
return “”;
}
[WebMethod(Description=“Greet by name”)]
public string Greet(string key, string name) {
if (!validKey(key))
throw new SecurityException(“Invalid session key”);
return “Hello, “ + name;
}
68/78
Emulando un Servicio Singleton


Esto es, todas las llamadas a un servicio web son
ejecutadas por un mismo objeto
Vamos a user el estado por aplicación de
ASP.NET
69/78
Servicio Web Singleton I
<%@ WebService Language="C#" Class="HelloService3" %>
// file:
helloservice3.asmx
// description: hello web service with application state info
using System.Web.Services;
[WebService(
Description="A stateful greeting Web service",
Namespace="http://tempuri.org/ws"
)]
public class HelloService3 : WebService {
[WebMethod(Description="Greet by name.")]
public string Greet(string name) {
numGreet++;
if (name == "") name = "Stranger";
return "Hello, " + name + "!";
}
70/78
Servicio Web Singleton II
[WebMethod(Description="Get number of greetings.")]
public int NumGreet() {
return numGreet;
}
private int numGreet {
get {
if (Application["numGreet"] == null) return 0;
return (int) Application["numGreet"];
}
set {
Application.Lock();
if (Application["numGreet"] == null)
Application["numGreet"] = 0;
Application["numGreet"] = value;
Application.UnLock();
}
}
}
71/78
Web Service Enhancements
(WSE 2.0)

Web Service Enhancements (WSE)



http://msdn.microsoft.com/webservices/building/wse/default.aspx
Artículo de introducción:
http://msdn.microsoft.com/webservices/building/wse/defau
lt.aspx?pull=/library/en-us/dnwse/html/programwse2.asp
Todo sobre los estádares ws-* en:
http://www.specifications.ws/default.asp
72/78
Evitando URLs absolutas en
Proxies

En CalculatorWebService.cs encontramos:
public CalculatorWebService() {
this.Url = "http://localhost/ws/calc.asmx";
}

Para evitar modificar el cs cada vez que la localización del servicio web
cambie, usar el switch urlkey
wsdl /urlkey:CalcUrl http://localhost/ws/calc.asmx

Ahora habría que asignar un valor a CalcUrl en la sección
appSettings del fichero Web.config
<configuration>
<appSettings>
<add key="CalcUrl"
value="http://localhost/ws/calc.asmx" />
</appSettings>
</configuration>
73/78
Una cliente Web SMTP I
<%@ WebService Language="C#" Class="WebMailService" %>
// file:
WebMailService.asmx
// description: SMTP mail Web service
using System;
using System.Web.Services;
using System.Web.Mail;
[WebService(
Description="An SMTP mail Web service",
Namespace="http://tempuri.org/ws"
)]
public class WebMailService : WebService {
[WebMethod(Description="Send an SMTP mail message")]
public string Send(string from,
string to,
string subject,
string cc,
string bcc,
string body) {
74/78
Una cliente Web SMTP II
try {
MailMessage msg = new MailMessage();
msg.From = from;
msg.To = to;
msg.Subject = subject;
msg.Cc = cc;
msg.Bcc = bcc;
msg.Body= body;
// set SMTP server here, if necessary
SmtpMail.SmtpServer = "smtp2.ya.com";
SmtpMail.Send(msg);
return "OK";
} catch (Exception e) {
return "ERROR : " + e.Message;
}
}
}
75/78
Una nueva era




Los servicios web tienen el potencial de cambiar la manera en que
desarrollamos aplicaciones distribuidas
El paradigma SOA (Service Oriented Arquitecture) propone un
modelo en el que Internet estará poblado por miles de servicios web,
exponiendo diferente contenido y lógica de negocio a los invocadores
de servicios.
.NET esconde HTTP, XML, y SOAP para que nosotros nos
concentremos en la lógica de la aplicación en vez de en los detalles
de comunicación con la parte servidora.
La computación distribuida a través de plataformas ha sido el sueño
de los informáticos por mucho años

Con la llegada de los servicios web y las herramientas que facilitan su
uso podemos por fin hacer ese sueño realidad.
 CORBA lo intentó y es y será la solución más eficiente para la
programación distribuida

Sin embargo por fin todos los mayores productores de la industria (incluido
Microsoft) abogan por los Servicos Web
76/78
Nuevas Caracacterísticas .NET
2.0

ASP.NET Web Services soporta ahora tanto SOAP 1.1 como
protocolos SOAP 1.2


Desactivar o activar en elementos de ficheros machine.config y
web.config
Ejemplo de atributos más comunes:
[WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_
1, EmitConformanceClaims=true)]
[WebService(Namespace="Microsoft.Samples.XmlMessaging.We
bServices")]
public class BPConformance_asmx
{
[WebMethod]
public string HelloWorldBP()
{
//implement method here
}
}



Nuevo método de invocaciones asíncronas
Selección en tiempo de ejecución de un servicio
Revisar ejemplos en: WebServicesExamples
77/78
XML, Distribución y
Componentes
Tema 3 – Aplicaciones Distribuidas:
Servicios Web – Preguntas y Sugerencias
Dr. Diego Lz. de Ipiña Gz. de Artaza
http://paginaspersonales.deusto.es/dipina (Personal)
http://www.morelab.deusto.es (Research Group)
http://www.smartlab.deusto.es (Research Lab)
http://www.ctme.deusto.es (Cátedra de Telefónica Móviles)
http://www.tecnologico.deusto.es (Tecnológico-Fundación Deusto)