Compartir a través de


Este artículo proviene de un motor de traducción automática.

Estación de servicio

Crear clientes RESTful

Jon Flanders

Descargar el código de ejemplo

En esta entrega de la estación de servicio RESTful, Hablaré sobre clientes de creación contra los servicios RESTful. Creación de los clientes se percibe como difícil (principalmente debido a la falta de generación automática de cliente en los metadatos, à la SOAP y WSDL), pero en realidad es como cualquier otro tipo de código que se escribe: En primer lugar hay algún tiempo de rampa como acostumbrarse a un paradigma de programación determinado. A continuación, una vez que el bloqueo de ese paradigma, escribir código con ella resulta más fácil y más fácil. He encontrado es true para escribir los clientes contra los servicios RESTful, que tienen muchos otros programadores que ha interactuado con.

Fundamentos de cliente

Voy a mostrar los aspectos básicos de interacción entre un cliente y un servicio mediante REST. Un rápido resumen sobre REST antes podemos profundizar. REST es un estilo de arquitectura que se basa en los mismos principios que proporcionan la base de la Web. Los clientes interactúan con servicios realizando solicitudes HTTP y servicios responden con respuestas HTTP, que a menudo incluyen una representación de un recurso que puede utilizar código de cliente para una aplicación de unidad.

Imagine que tiene un servicio que expone la información y funcionalidad relacionada con Hyper-V (la tecnología de virtualización integrada en Windows Server 2008). Si "la entrada"URI de este servicio era http://localhost/HyperVServices/VMs.svc/, como un cliente que desea realizar una solicitud HTTP GET para recuperar una representación del recurso identificado por este URI. En este caso, el recurso tiene el formato XML y representa una lista de todos los s de máquinas virtuales (VM) instalado en un equipo determinado.


Figura 1 A HTTP simple solicitud GET

Como he mostrado en la primera de mis artículos Service Station sobre REST, en el número de enero de 2009 de MSDN Magazine (msdn.microsoft.com/magazine/2009.01.servicestation.aspx), una de las pequeñas ventajas del uso de que REST es que puede utilizar herramientas de la solicitud HTTP para realizar las solicitudes de prueba inicial contra un servicio. (Con estas herramientas para depurar problemas es también muy útil.) En este caso, Estoy utilizando una herramienta gratuita denominada Fiddler (fiddlertool.com) para realizar una solicitud HTTP GET para el recurso que representa todos mis equipos virtuales. Consulte de figura 1. Por supuesto, herramientas como Fiddler son valiosas, pero para crear una aplicación tiene que escribir código con el servicio. Voy a iniciar con los conceptos básicos de hacer un HTTP solicitar y obtener en el problema de realmente leer el recurso.

.NET Framework siempre ha ofrecido una API de HTTP básico que puede utilizarse para interactuar con servicios RESTful. En el Centro de esta API son los tipos de HttpWebRequest y HttpWebResponse. Para realizar una solicitud HTTP, crear y configurar una instancia de HttpWebRequest y pedirle después HttpWebResponse. En la figura 2 se muestra un ejemplo. Realizar una solicitud a un servicio RESTful es un sencillo conjunto de pasos:

  1. Asegúrese de que está utilizando el URI correcto.
  2. Asegúrese de que está utilizando el método correcto (verbo HTTP).
  3. Procesar la respuesta si el código de estado es 200 Aceptar.
  4. Tratar con otros códigos de estado como apropiado (más sobre este más adelante).

Dado que los pasos 1 y 2 son bastante fácil, general paso 3 (y a veces el paso 4) acaban siendo la más difícil de los pasos.

La mayoría de las tareas del paso 3 está procesando la representación de recursos de forma razonable. Puesto que XML es todavía la respuesta más habitual de recurso, voy a cubrir en este artículo. (El otro tipo de medio probablemente sería JSON). Cuando el recurso es XML, es necesario analizar ese recurso y escribir el código que puede extraer los datos que necesita ese resource.Using .NET, dispone de unas cuantas opciones para analizar XML. Es la clase XmlReader probado y es true. La clase XmlDocument también es una posibilidad y mediante uno de esos tipos manualmente puede analizar o utilizar XPath para desplazarse por la forma de evitar el XML. Con la llegada de .NET 3.0, obtendrá también XDocument clase, que, cuando se combina con LINQ to XML, ha convertido en la opción de facto para procesar XML. de la figura 3 muestra un ejemplo de código de procesamiento de la lista de máquinas virtuales mediante XDocument.

Figura 2 simple código HttpWebRequest

string uri = "http://localhost/HyperVServices/VMs.svc/";
var webRequest = (HttpWebRequest)WebRequest.Create(uri);
//this is the default method/verb, but it's here for clarity
webRequest.Method = "GET";
var webResponse = (HttpWebResponse)webRequest.GetResponse();
Console.WriteLine("Response returned with status code of 0}",
webResponse.StatusCode);
if (webResponse.StatusCode == HttpStatusCode.OK)
ProcessOKResponse(webResponse);
else
ProcessNotOKResponse(webResponse);

LINQ to XML, junto con los tipos anónimos, proporciona una forma interesante, fácil de tratar con convertir XML en objetos que puede procesar una aplicación y, por supuesto, también puede utilizar un tipo predefinido en lugar de un tipo anónimo.

Otro enfoque es popular cuando programación con servicios basados en SOAP y basado en REST hacer que las respuestas a deserializarse automáticamente en tipos de .NET. En el caso de SOAP, esto generalmente sucede en el proxy generado por el WSDL. Con Windows Communication Foundation (WCF) y REST, esto puede realizarse en un par de formas. Una forma (que es realmente no recomienda, pero estoy mencionar para integridad) es utilizar la naturaleza simétrica de WCF para utilizar una definición de contrato de servicio WCF en el cliente. De hecho, la compatibilidad WCF para REST incluye un tipo denominado WebChannelFactory que puede utilizarse para crear un canal de cliente con una definición de contrato de servicio. No recomiendo este tipo de cliente de programación por dos motivos. En primer lugar, crear al cliente se convierte en una operación muy manual y proclive a error. En segundo lugar, el uso de un contrato de servicio inflexible, crea un estrecho acoplamiento entre el cliente y el servicio. Evitar estrecho acoplamiento es una de las razones principales que el Web ha tenido éxito y desea continuar esa tendencia al utilizar el Web mediante programación.

Otra forma de utilizar la serialización XML es utilizar el método HttpWebResponse.GetResponseStream y deserializar el XML en el objeto manualmente. Puede hacerlo mediante la clase XmlSerializer o el serializador de DataContract de WCF. En la mayoría de los casos, la clase XmlSerializer es el método preferible porque ocupa más variaciones en documentos XML (por ejemplo, atributos y elementos incompleto) que el serializador de DataContract.

de la figura 3 procesamiento de una respuesta RESTful con XDocument

var stream = webResponse.GetResponseStream();
var xr = XmlReader.Create(stream);
var xdoc = XDocument.Load(xr);
var vms = from v in xdoc.Root.Elements("VM")
select new { Name = v.Element("Name").Value};
foreach (var item in vms)
{
Console.WriteLine(item.Name);
}

El problema parece aún con un círculo al hecho de que servicios RESTful normalmente no exponen metadatos que se pueden utiliza para autogenerate algunos o todos de este código. Aunque muchos en el campamento RESTful no aparecen como un problema (nuevo, algo que autogenerates contra servicio definiciones pueden verse como el agente malintencionado del estrecho acoplamiento), hay ciertamente veces cuando no tiene estas herramientas es un obstáculo para la adopción de REST.

Una interesante realizadas por el WCF REST Starter Kit (asp.net/downloads/starter-kits/wcf-rest/), que es una mejora de Microsoft sobre el modelo en .NET 3.5, de programación de REST de consiste en proporcionar una característica de autogeneración parcial. Si instala el starter kit, tendrá un nuevo elemento de menú en Visual Studio 2008 en el menú Edición, como puede ver en figura 4.


Figura 4 pegar XML como tipos de elemento de menú

El modelo de uso de este comando es bastante sencillo. Copia la representación de recurso XML en el Portapapeles (ya sea desde alguna documentación legible por el servicio expone o haciendo clic en una solicitud con una herramienta como Fiddler). Una vez hecho esto, un conjunto de tipos XmlSerializable se crea, que luego puede usar para activar la secuencia de HttpWebResponse en un objeto. Consulte de figura 5 (no se muestra el cuerpo de los tipos generados para simplificar de brevedad).

Figura 5 código generado desde pegar utilizando XML como tipos

var stream = webResponse.GetResponseStream();
//in a real app you'd want to cache this object
var xs = new XmlSerializer(typeof(VMs));
var vms = xs.Deserialize(stream) as VMs;
foreach (VMsVM vm in vms.VM)
{
Console.WriteLine(vm.Name);
}
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
[System.Xml.Serialization.XmlRootAttribute(Namespace = "",
IsNullable = false)]
public partial class VMs
{
private VMsVM[] vmField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("VM")]
public VMsVM[] VM
{
get
{
return this.vmField;
}
set
{
this.vmField = value;
}
}
}
/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "2.0.50727.4918")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true)]
public partial class VMsVM
{
//omitted
}

El Starter Kit de REST no sólo simplifica el uso de XmlSerializer, pero también proporciona una API muy interesante en parte superior de la API HttpWebRequest y WebResponse. El código siguiente muestra la solicitud GET sencilla de volver a escribir utilizando HttpClient API del Kit de inicio de REST figura 1:

 

string uri = "http://localhost/HyperVServices/VMs.svc/";
var client = new HttpClient();
var message = client.Get(uri);
ProcessOKResponse(message.Content.ReadAsStream());

La clase HttpClient enormemente simplifica (y hace explícita qué verbos estás utilizando) el uso de la API de HTTP de .NET. Además, como puede ver en el siguiente código, simplifica el uso de la característica de Pegar como tipos XML generado:

var vms = XmlSerializerContent.ReadAsXmlSerializable<VMs>(
message.Content);

Aunque el Starter Kit de REST oficialmente no se admite todavía por Microsoft, lo muestran un punto muy importante: ese cliente REST de programación se puede simplificar y automatiza parcialmente sin un servicio RESTful tener metadatos completado à la de un archivo WSDL.

Mediante HTTP

Uno que un cliente y un servicio pueden beneficiarse de HTTP consiste en utilizar correctamente los códigos de estado y los encabezados. Obtener más información acerca de códigos de estado puede encontrarse en w3.org/Protocols/rfc2616/rfc2616-sec10.html de.

Como ha pasado todo el mundo habla acerca de REST, una de las ventajas de servicios RESTful que señale a menudo es que pueden almacenar en caché las solicitudes GET. Comete no, la escalabilidad y el éxito de la Web es en gran parte debido de almacenamiento en caché de HTTP.

Una forma de aprovechar HTTP almacenamiento en caché es utilizar GET condicional. GET condicional permite que el cliente "(agente de usuario de"en jerga HTTP) para realizar una solicitud GET para un recurso que el agente de usuario ya tiene una copia de. Si no ha cambiado el recurso, el servidor indica al agente de usuario que el recurso es exactamente igual a la versión ya está retenida por el agente de usuario. La ventaja de eficiencia de GET condicional es una reducción de uso del ancho de banda de la red entre el servidor y el agente de usuario, liberar el ancho de banda ser utilizado por las solicitudes para los recursos recién creados o modificados. Además, guarda el tiempo de procesamiento adicional necesario para serializar el recurso, aunque no el procesamiento tiempo para generar o recuperar el recurso (ya que necesita una copia del recurso actual para compararlo con la información enviada por el agente de usuario con el GET condicional).

de la figura 6 implementación de servidor de GET condicional

[OperationContract]
[WebGet(UriTemplate = "/{name}")]
public VMData GetOne(string name)
{
VMManager.Connect();
var v = VMManager.GetVirtualMachine(name);
var newVM = FromVM(v);
string etag = GenerateETag(newVM);
if (CheckETag(etag))
return null;
if (newVM == null)
{
OutgoingWebResponseContext ctx =
WebOperationContext.Current.OutgoingResponse;
ctx.SetStatusAsNotFound();
ctx.SuppressEntityBody = true;
}
SetETag(etag);
return newVM;
}
private bool CheckETag(string currentETag)
{
IncomingWebRequestContext ctx =
WebOperationContext.Current.IncomingRequest;
string incomingEtag =
ctx.Headers[HttpRequestHeader.IfNoneMatch];
if (incomingEtag != null)
{
if (currentETag == incomingEtag)
{
SetNotModified();
return true;
}
}
return false;
}
string GenerateETag(VMData vm)
{
byte[] bytes = Encoding.UTF8.GetBytes(vm.ID +
vm.LastChanged.ToString());
byte[] hash = MD5.Create().ComputeHash(bytes);
string etag = Convert.ToBase64String(hash);
return string.Format("\"{0}\"", etag);
}
void SetETag(string etag)
{
OutgoingWebResponseContext ctx =
WebOperationContext.Current.OutgoingResponse;
ctx.ETag = etag;
}

Como la mayoría de la otra "avanzados" Conceptos HTTP, WCF no admite GET condicional automáticamente porque la implementación de GET condicional es muy variable entre las implementaciones del servicio. Sin embargo, como lo hace otros "avanzados" Conceptos HTTP, WCF ofrece las herramientas para implementar condicional GET. Existen dos métodos para conseguirlo: utilizando la hora de que última modificación el recurso, o mediante un identificador único conocido como un ETag.

ETags se han convertido en la forma más popular para implementar la condición GET. En de figura 6, puede ver el código para implementar un GET condicional basada en ETag en el servicio VM. Tenga en cuenta que ésta es la implementación de servidor;Familiarizará con el cliente en un momento.

El flujo básico es para que el servidor para buscar la etiqueta ETag en el encabezado If-None-Match HTTP enviado por el cliente y para intentar coincidir con la etiqueta ETag actual generada para el recurso. En este caso, Estoy utilizando el identificador único de cada máquina virtual más la marca de hora de última modificación (convertido en bytes y, a continuación, convertirse en un hash MD5, que es una implementación bastante común). Si los dos valores coinciden, el servidor envía un encabezado HTTP no modificado 304 con un cuerpo vacío, guardar el momento de la serialización, así como ancho de banda. El cliente obtiene una mucho más rápida respuesta y sabe que puede utilizar el mismo recurso ya tiene.


Figura 7 un Simple Client de WPF VM

Imagine una aplicación cliente como la mostrada en 7. figura de que esta aplicación muestra el nombre de cada máquina virtual, además de la imagen del estado actual de la máquina virtual. Ahora imagine que desea actualizar esta aplicación para que coincida con el estado actual de cada máquina virtual. Para ello, tendría que escribir algún código en un temporizador y actualizar cada registro si era distinta de su registro local. Y es probable que desea actualizar todo en cada iteración sólo para simplificar la aplicación, pero esto sería una pérdida de recursos.

Si ha utilizado en su lugar GET condicional en el cliente, no se pudo sondear el servicio para cambios enviando una solicitud GET condicional, que puede utilizar un encabezado If-None-Match para indicar la etiqueta ETag del recurso. Colección de máquinas virtuales, el servicio puede utilizar la VM modificada más recientemente para generar ETag y el cliente se actualizará sólo si uno o más de las máquinas virtuales han cambiado su estado. (Si tiene gran cantidad de máquinas virtuales, quizás desee hacerlo para cada máquina virtual. Pero puesto que se enlaza a datos a la colección de esta aplicación, soy Aceptar con actualizar toda la colección).

Ahora, implementar esta lógica no es muy difícil, pero es una de las características que implementa REST Starter Kit para. En los ejemplos de código incluye que un archivo denominado PollingAgent.cs, que tiene un cliente GET condicional automático que sondea un extremo RESTful en un intervalo que defina. Cuando el PollingAgent determina que el recurso ha cambiado (porque el servicio ya no está devolviendo un 302), se desencadena una devolución de llamada.

Por lo tanto, en mi aplicación sencilla de WPF, sólo el resultado de dicha devolución de llamada (que es el objeto HttpResponseMessage) y volver a enlazar los controles a los datos nuevos. La figura 8 muestra el código para implementar esta aplicación mediante el PollingAgent.

Hipertexto siguiente

Antes de abandonar al asunto de los clientes, deseo táctil en otra de las restricciones importantes de REST: utilizar hipermedia como el motor de estado de aplicación (conocido como HATEOAS).

Creo que es más fácil comprender en el contexto de la Web humano HATEOAS. Cuando se utiliza el Web humano, a veces, debemos marcadores sitios que sabemos que desea visitar. Dentro de esos sitios, sin embargo, generalmente seguimos hipervínculos según nuestras necesidades del día. Podría tener un marcador para www.amazon.com, pero cuando desea comprar algo, siga los vínculos en cada página (recurso) para agregar un elemento a mi carro. Y siga los hipervínculos (a veces formularios y) en cada página posteriores para procesar mi pedido. En cada fase del procesamiento de pedidos, los vínculos en la página representan el estado actual de la aplicación (en otras palabras, lo que, como el agente de usuario, puedo?).

Una consideración importante al generar a clientes RESTful (aunque parte de esto es incumbent en así los implementadores de servicio RESTful) consiste en mantener "marcadores"en un mínimo. Qué significa esto prácticamente es que los clientes deben tener como poco conocimiento posible sobre la estructura URI de las representaciones, pero tanto como sea posible deben saber cómo "desplazarse""los hipervínculos de"dentro de esos recursos. Colocar "hipervínculos"comillas porque cualquier dato en el recurso puede ser un URI relativo para generar el siguiente "vínculo"para el cliente.

Figura 8 condicional GET mediante el sondeo del agente REST Starter Kit

public Window1()
{
InitializeComponent();
string uri = "http://localhost/HyperVServices/VMs.svc/";
var client = new HttpClient();
var message = client.Get(uri);
var vms = XmlSerializerContent.ReadAsXmlSerializable<VMs>(
message.Content);
_vmList.DataContext = vms.VM;
var pa = new PollingAgent();
pa.HttpClient = client;
pa.ResourceChanged += new EventHandler<ConditionalGetEventArgs>(
pa_ResourceChanged);
pa.PollingInterval = new TimeSpan(0, 0, 5);
pa.StartPolling(new Uri(uri), message.Headers.ETag, null);
}
void pa_ResourceChanged(object sender, ConditionalGetEventArgs e)
{
var vms = XmlSerializerContent.ReadAsXmlSerializable<VMs>(
e.Response.Content);
_vmList.DataContext = vms.VM;
}

En mi ejemplo, nombre de cada VM es realmente un vínculo, porque un cliente puede solicitar datos de máquina virtual determinada pidiendo el nombre como parte de la dirección URI. Por lo tanto, http://localhost/HyperVServices/VMs.svc/MyDesktop (donde miescritorio es el valor del elemento nombre en elemento de la máquina virtual de dentro de la colección) es el URI del recurso de VM miescritorio.

Imagine que este servicio RESTful permite para aprovisionamiento e iniciar las máquinas virtuales. Tendría tiene sentido incrustar dentro de cada hipervínculos de recurso VM a los diferentes estados que se podría colocar una VM en un momento determinado, en lugar de dejar el cliente inicie una máquina virtual que no ha configurado correctamente todavía.

Utilizando HATEOAS ayuda a comprobar el estado actual de la aplicación, y también anima acoplamiento más flexible de los clientes (dado que los clientes no tienen que saber tanta sobre la estructura URI del servicio).

Más fácil que es la reflexión

Hay hay duda de creación de clientes RESTful es más difícil iniciar hacer que la creación de clientes basados en SOAP admitidos metadatos WSDL. Como escribí en mi columna anterior, "REST es sencillo, pero sencillo no significa necesariamente fácil. SOAP es fácil (debido de WSDL), pero fácil no siempre significa "con buenas prácticas de codificación y herramientas como el Starter Kit de REST, creación RESTful clientes pueden ser más fácil que piensa simple.. Y al final Creo que encontrará que las ventajas que obtenga de utilizando el estilo de arquitectura se componen más para cualquier retraso temporal en la creación de clientes.

Jon Flanders es un consultor independiente, altavoces y el instructor para Pluralsight. Está especializado en BizTalk Server, Windows Workflow Foundation y Windows Communication Foundation. Póngase en contacto puede con él en masteringbiztalk.com/blogs/jon de.