Вы находитесь на странице: 1из 8

Los 5 errores ms comunes en servicios web ASP.

NET
Posted on August 15th, 2007 by Christian Lpez Espnola Traduccin del artculo publicado por Paul Ballard el 27 de mayo de 2005 en TheServerSide.NET. Adems de la traduccin ingls-castellano, he traducido los ejemplos de VB.NET a C#. Puedes encontrar el original aqu: Top 5 Web Service mistakes. En este artculo vamos a comentar los 5 errores ms comunes que comenten las empresas cuando desarrollan servicios web en .NET. Es importante resaltar que no son errores de lgica o sintaxis. No hay errores de compilacin que te digan que algo est mal y no se lanzarn excepciones. Son problemas de arquitectura, no de tecnologa. La clave, por tanto, es evitarlos desde el principio, ya que intentar corregirlos despus de su puesta en produccin puede ser mucho ms complicado. 1. Usando tipos especficos de .NET. El concepto fundamental detrs de los servicios web es la creacin de lgica de aplicacin accesible en cualquier momento, desde cualquier sitio, por cualquier otra aplicacin independientemente de la tecnologa. Esto incluye tambin a aplicaciones no .NET. El aspecto ms importante para garantizar la interoperabilidad en servicios web no se encuentra en el cdigo, o al menos no directamente. Para que un servicio sea interoperable con cualquier tecnologa el contrato de datos que define debe estar basado en tipos definidos en un XML Schema, no en el framework .NET. Por tanto, si usas tipos especficos de .NET como parmetros o valores de retorno para un servicio web, el XML que produce puede no ser interoperable con Java u otra tecnologa. Quiz has visto las demos de cmo de fcil es crear un simple servicio web que consulta a una base de datos y devuelve los datos como un Dataset de ADO.NET. Un Dataset es una versin totalmente desconectada de datos relacionales, incluyendo tablas, claves, y relaciones y dems, por lo que puede parecer el objeto perfecto para transmitir datos entre distintas localizaciones. En el caso de los servicios web, las apariencias engaan. Pasar un Dataset como resultado o parmetro en un servicio web crea distintos problemas. El primero ocurre en el WSDL. WSDL es el schema XML que define como los clientes pueden interactuar con tu servicio y qu parametros y valores de retorno utiliza. WSDL es a menudo utilizado para generar clases proxy del lado del cliente, por lo que mientras ms descriptivo sea, ms fcil ser interactuar con nuestro servicio. Veamos un ejemplo de un simple servicio con un mtodo que devuelve un Dataset que contiene un fila de la tabla Customers de la base de datos Northwind. A continuacin se muestra el WSDL para ese servicio. Fjate en la elemento GetCustomersResponse.
<s:element name=GetCustomersResponse> <s:complexType> <s:sequence> <s:element minOccurs=0 maxOccurs=1 name=GetCustomersResult> <s:complexType>

<s:sequence> <s:element ref=s:schema/> <s:any/> </s:sequence> </s:complexType> </s:element> </s:sequence> </s:complexType> </s:element>

Debido a que la estructura del Dataset no se conoce hasta tiempo de ejecucin, no hay manera para el WSDL de describir su estructura interna. Para resolver esto, el valor de retorno (elemento GetCustomersResponse) del mtodo GetCustomers tiene dos elementos, un elemento de tipo any (<s:any/>) que es en efecto un tipo de objeto y un XML Schema (<s:schema>) que en tiempo de ejecucin describir la estructura del Dataset de retorno. Esto es el equivalente en servicios web a late binding. Debido a que el desarrollador del cliente no sabe la estructura del objeto que tu mtodo devolver, no podrn generar un proxy muy til. Podrn usar tu servicio web, pero debern parsear el XML de retorno para encontrar los datos que estn buscando. La seguridad de tipos se ha tirado por el retrete y has hecho que el trabajo de cualquier desarrollador de un cliente no .NET sea ms difcil. Ahora deberas estar dicindote a t mismo: Si el WSDL no define un tipo de retorno Dataset, cmo funcionan todas esas demos?. La respuesta est en el XML devuelto en tiempo de ejecucin. A continuacin se muestra el resultado de llamar a nuestro mtodo GetCustomers.
<?xml version=1.0 encoding=utf-8?> <DataSet xmlns=http://tempuri.org/> <xs:schema id=NewDataSet xmlns= xmlns:xs=http://www.w3.org/2001/XMLSchema xmlns:msdata=urn:schemasmicrosoft-com:xml-msdata> <xs:element name=NewDataSet msdata:IsDataSet=true msdata:UseCurrentLocale=true> <xs:complexType> <xs:choice minOccurs=0 maxOccurs=unbounded> <xs:element name=Table> <xs:complexType> <xs:sequence> <xs:element name=CustomerID type=xs:string minOccurs=0 /> <xs:element minOccurs=0 /> <xs:element minOccurs=0 /> <xs:element minOccurs=0 /> <xs:element /> <xs:element name=CompanyName type=xs:string name=ContactName type=xs:string name=ContactTitle type=xs:string name=Address type=xs:string minOccurs=0 name=City type=xs:string minOccurs=0 />

<xs:element name=Region type=xs:string minOccurs=0 /> <xs:element name=PostalCode type=xs:string minOccurs=0 /> <xs:element name=Country type=xs:string minOccurs=0 /> <xs:element name=Phone type=xs:string minOccurs=0 /> <xs:element name=Fax type=xs:string minOccurs=0 /> </xs:sequence> </xs:complexType> </xs:element> </xs:choice> </xs:complexType> </xs:element> </xs:schema> <diffgr:diffgram xmlns:msdata=urn:schemas-microsoft-com:xml-msdata xmlns:diffgr=urn:schemas-microsoft-com:xml-diffgram-v1> <NewDataSet xmlns=> <Table diffgr:id=Table1 msdata:rowOrder=0> <CustomerID>ALFKI</CustomerID> <CompanyName>Alfreds Futterkiste</CompanyName> <ContactName>Maria Anders</ContactName> <ContactTitle>Sales Representative</ContactTitle> <Address>Obere Str. 57</Address> <City>Berlin</City> <PostalCode>12209</PostalCode> <Country>Germany</Country> <Phone>030-0074321</Phone> <Fax>030-0076545</Fax> </Table> </NewDataSet> </diffgr:diffgram> </DataSet>

Fjate en que el elemento NewDataSet tiene un atributo especfico de Microsoft llamado IsDataSet. Esta es una pista de Visual Studio de que el resultado debera ser deserializado como Dataset. Por supuesto, esto no significa nada si ests llamando a este servicio web desde un cliente no .NET como J2EE. El segundo problema cuando pasamos Datasets a y desde un servicio web es la gran cantidad de datos que se enva. El XML que vimos anteriormente slo describe la estructura de un dataset con una tabla. Mientras aades tablas, relaciones y claves, el schema se vuelve ms complejo y ms grande. De hecho, rpidamente puede convertirse en mayor que los datos que se devuelven. Recuerda, mientras ms datos enves a / desde un servicio ms lenta se volver la peticin. El Dataset es probablemente la forma ms comn de usar tipos especficos de .NET en servicios web pero no es el nico caso. Tiene mucho sentido para un desarrollador .NET

querer usar las caractersticas avanzadas y las clases provistas por el framework .NET. Sin embargo, si la interoperabilidad real es tu objetivo, tendrs que controlar tus impulsos. Para interoperabilidad mxima, la clave es asegurarse que todos los tipos que se utilizan como parmetros y valores de retorno pueden describirse usando los tipos bsicos del XML Schema estndar. Puedes encontrar la definicin de todos esos tipos en http://www.w3.org/TR/xmlschema-2/ 2. No aprovecharse de ASP.NET La mayor desventaja de consumir servicios web es el rendimiento. Cualquier mejora que se pueda realizar para incrementar el rendimiento merece el esfuerzo. Los servicios web desarrollados en .NET se despliegan en ASP.NET y por tanto puedes acceder a todas esas grandes caractersticas de cualquier aplicacin web ASP.NET. Para el rendimiento, las caractersticas ms importantes son el Caching y el SessionState. Los servicios web pueden usar dos tipos de cacheo. El primero y el ms sencillo es cacheo de salida. El cacheo de salida permite que el resultado de un servicio web se almacene en la cach del servidor. Las siguientes peticiones a ese mtodo que usen los mismos parmetros obtendrn los valores cacheados en el servidor sin llamar al mtodo del servicio y por tanto, sin consulta de datos, lgica, etc. Cuando los parmetros del mtodo cambian se aade una entrada a la cach del servidor con el tiempo de expiracin especificado. Para usar esta caracterstica, slo aade la propiedad CacheDuration a la clase WebMethodAttribute. Aqu hay un ejemplo simple que cachea el resultado de un mtodo durante 120 segundos.
[WebMethod(CacheDuration=120)] public Quote GetQuote ()

Tambin puedes usar el cacheo de datos de aplicacin para almacenar datos especficos entre peticiones. Datos que se utilizan a menudo pero que no cambian tan frecuentemente son los primeros candidatos a ser almacenados en la cach de la aplicacin. Para ilustrar esto vamos a construir un servicio ficticio para obtener cotizaciones de acciones. Una funcin que ofrece este servicio es la posibilidad de obtener el smbolo de una empresa utilizando su nombre. Una funcin como sta debe ser llamada a menudo, a pesar de que los cambios en los datos apenas varan. En este caso querremos consultar la base de datos una vez al inicio y devolver un array conteniendo todos los nombres de empresas y sus correspondientes smbolos y almacenar ese array en la cach con una expiracin diaria. Cuando un cliente busca el smbolo de una empresa, en vez de hacer una llamada a la base de datos con cada peticin podemos buscarla en el array almacenado en cach. A continuacin se muestra el cdigo necesario para implementar este tipo de cacheo.
[WebMethod] public Symbol[] GetAllSymbols () { Symbol [] symbols; if (HttpContext.Current.Cache ["AllSymbols"] == null) {

symbols = _QuotesData.GetAllSymbols(); // extrae datos de la BBDD HttpContext.Current.Cache.Add(AllSymbols, symbols, null, DateTime.MaxValue, new TimeSpan(24, 0, 0), System.Web.Caching.CacheItemPriority.Normal, null); } else { symbols = HttpContext.Current.Cache ["AllSymbols"] as Symbol[]; } return symbols; }

Los servicios web tambin pueden usar la persistencia en el estado de la sesin ofrecida a travs de ASP.NET incluyendo estado fuera del proceso del servidor y SQL Server. Para habilitar esta caracterstica aade EnableSession=True al atributo WebMethod. Esto es muy til para almacenar informacin especfica del cliente entre peticiones. Por ejemplo, continuando el desarrollo de nuestro sistema de anlisis de stock vamos a decir que nuestro servicio web permite a los clientes crear una lista personalizada de stocks que estn siguiendo. Cuando el cliente solicita la lista de stocks para ese usuario la primera vez, almacenamos la lista en la sesin antes de devolverlo al cliente. Ahora podemos modificar nuestro mtodo para obtener la lista de los stocks desde el SessionState si el cliente no ha mandado una nueva lista. Esto puede aumentar el rendimiento de las actualizaciones sustancialmente. La siguiente figura muestra ejemplos de mtodos que utilizan el estado de la sesin.
[WebMethod(CacheDuration = 60, EnableSession = true)] public Quote [] GetQuotes (string [] symbols) { List<Quote> lQuotes = new List<Quote>(); foreach (string symbol in symbols) { lQuotes.Add(GetQuote(symbol)); } // Store in SessionState just in case the client wants to recall without // sending the list again HttpContext.Current.Session ["SymbolList"] = symbols; return lQuotes.ToArray(); } [WebMethod(CacheDuration = 60, EnableSession = true)] public Quote [] GetQuotesFromSession () { string [] symbols = (string[]) HttpContext.Current.Session ["SymbolList"]; return GetQuotes(symbols); }

ASP.NET utiliza cookies en el cliente para identificar de manera nica cada sesin, por tanto, para utilizar esta caracterstica, necesitars cierto trabajo en el cliente. Con .NET es

muy simple, slo necesitamos crear un nuevo CookieContainer para almacenar las cookies recibidas desde el servicio. Aqu est el cdigo de cliente necesario para hacer esto:
myService.CookieContainer = new System.Net.CookieContainer();

Aunque usar el estado de la sesin puede aumentar el rendimiento, rompe las reglas de la orientacin a servicios atendiendo a que los servicios no deben tener estado. Es muy importante recordar tambin que no todos los clientes son capaces de aceptar tus cookies. La mejora de rendimiento es sustancial y con algunas advertencias, creo que merece la pena usarlo. Advertencia 1: Cualquier mtodo web que use el estado de la sesin debe tener su correspondiente versin sin estado. Advertencia 2: Por claridad, debes nombrar a tus mtodos con estado de modo que el desarrollador del cliente sepa que el uso del estado de la sesin est habilitado. 3. Not Enough Bang for the Buck Si t personalmente tuvieras que seguir a pie el camino que las peticiones a tu servicio web hacen a travs de la compaa o a travs del mundo, una cosa es cierta: querras hacer el viaje slo una vez. Esta es la misma razn por la que hacemos una lista antes de ir al supermercado en vez de hacer el viaje para cada producto. Hay siempre una disminucin de rendimiento o un aumento del trfico de red con cada peticin. Tus servicios web deberan disearse para maximizar la cantidad de trabajo que se realiza con cada peticin. Asegrate de que la funcionalidad que ests ofreciendo a travs del servicio valga el tiempo y el esfuerzo que el cliente gast en hacerte la peticin. Como ejemplo, vamos a trabajar en nuestro servicio de cotizaciones. Probablemente has visto demos que muestran lo sencillo que es enviar un smbolo y recibir una cotizacin actual de mercado. Pero y si quieres conocer el precio de 10 smbolos a la vez? Usando la versin de la demo, deberas hacer diez peticiones al servidor. Querras dar esa caminata? Para mejor rendimiento, considera combinar esas pequeas peticiones en una nica peticin mayor. En el caso de los precios de las acciones, es sencillo combinar los smbolos de entrada en un array de cadenas y devolver un array de Quotes en el mtodo. Esta implementacin del mtodo GetQuotes se puede ver en el fragmento de cdigo anterior. En casos ms complejos, tus servicios pueden comenzar a asemejarse al patrn RequestBroker y de hecho muchos servicios web se construyen de este modo. Cada peticin contiene una o varias peticiones ms pequeas. Los valores de retorno se integran en una nica respuesta y devueltos al cliente. Precaucin, pues esto puede convertirse en un servicio con una interfaz que es tan genrica que bsicamente recibe y enva cualquier mensaje. Una vez ms, llegamos a la situacin en la que la aplicacin cliente es incapaz de crear un proxy til y es dependiente de documentacin externa para la interoperabilidad.

Estimar cmo equilibrar la agregacin de peticiones para mejorar el rendimiento con la complejidad creciente es una de las tareas del arquitecto de la aplicacin y slo puede ser determinado estudiando caso por caso. 4. Usando servicios web para acceso a datos. Este error viene de un acerca de los servicios web. Algunos arquitectos y desarrolladores tienden a ver los servicios web como un modo de compartir datos. La confusin es comprensible: Microsoft misma ensucia el agua con mejoras como la nueva caracterstica de SQL Server 2005 que permite a procedimientos almacenados ser accedidos como servicios web con una par de clicks. Esto permite grandes demos pero mal diseo de aplicaciones. Los servicios web no proveen simplemente acceso a datos: proveen acceso al conocimiento del negocio de la organizacin. Organizaciones de todos los tamaos, desde departamentos hasta grandes corporaciones, estn definidas por sus conocimientos del negocio. No vas a Starbucks por tus necesidades bancarias, ni el Banco de Espaa hace cafs. Pero las organizaciones a menudo quieren compartir su experiencia con otras organizaciones. Starbucks puede querer que el Banco de Espaa valide una compra con tarjeta de crdito de una de sus bebidas. Esta informacin compartida significa que Starbucks no tiene que reinventar cmo los pagos con tarjeta se procesan y puede concentrarse en hacer cafs. Cmo una organizacin implementa su experiencia en el negocio? Una manera es desarrollando aplicaciones personalizadas que creen, mejoren o automaticen el uso de esa experiencia. Ah es donde aparecen los servicios web y la orientacin a servicios: proveyendo acceso a esas aplicaciones a otras organizaciones estn compartiendo su conocimiento. Quiz el mejor ejemplo de un servicio web exponiendo funcionalidad y no datos es el servicio web de Google para buscar en sitios web. Cmo sera de til el servicio si slo devolviera datos, informacin sobre millones de pginas, y tuvieras que buscar a travs de ellas? Google pone sus amplios conocimientos de cmo buscar en la web y de ah viene el valor de su servicio web, no de sus datos. Cuando desarrollas tus servicios web, recuerda que lo que tus clientes quieren de tu servicio es tu conocimiento del negocio, no slo tus datos. Deberas cuestionar cada mtodo de un servicio web que nicamente consulta y devuelve datos. Ests colocando la lgica de negocio en el lado errneo del servicio y forzando a tus clientes a reinventar tu conocimiento del negocio. 5. Confiar en la aplicacin cliente La responsabilidad de un servicio web va ms all de permitir acceso a nuestras reglas de negocio. Es tambin responsable de proteger el negocio y la integridad de los datos. Muchas veces un servicio web se desarrolla a la vez que la interfaz de usuario que lo consume. El servicio web acta como back end de la aplicacin y comnmente se deja la seguridad a la interfaz de usuario. Si la seguridad se aplica slo en el lado del cliente de la

aplicacin, tu servicio web es vulnerable a ataques y la integridad de tu negocio est en bragas. La clave es separar, tanto en tu cabeza como en el diseo, la seguridad de la interfaz de usuario de la seguridad del servicio web. Cada componente requiere una aplicacin correcta de las tcnicas de seguridad incluyendo autenticacin, autorizacin, encriptacin de los datos Ten en mente que otras aplicaciones desarrolladas por otras organizaciones podran utilizar tu back end, por tanto asegrate de que est protegido. La seguridad es un tema complejo fuera del mbito de este artculo, pero aqu tienes algunos puntos en los que centrarte:

Debes asumir que no puedes confiar en los datos que recibes como parmetros en los mtodos del servicio. Los servicios web se despliegan en ASP.NET y por tanto son susceptibles de los mismos tipos de ataques que cualquier aplicacin web ASP.NET, incluyendo SQL Injection, DoS, Replay Attacks Afortunadamente, tambin puedes utilizar las mismas contramedidas para defender tus servicios de dichos ataques. Los datos que se devuelven deben ser protegidos. Si te preocupa la integridad de los datos a travs de la red, la mejor manera es usar SSL para encriptar los datos entre el cliente y el servidor. Tambin puedes aliviar algunas amenazas de SQL Injection o XPath Injection no devolviendo objetos definidos dinmicamente como Datasets y XmlDocuments. La auditora es una importante y a menudo infravalorada medida de seguridad. Mediante la habilidad de controlar el uso de tus servicios web permites controlar las violaciones de acceso y tienes la capacidad de responder a esos ataques cuando se producen. Claras violaciones de los datos podran mandar un mensaje a un administrador o cancelar el acceso del usuario al servicio. Ataques DoS se eliminan mediante mecanismos basados en el uso.

Desde el punto de vista de la arquitectura, la clave para evitar problemas de seguridad despus del despliegue de un servicio es tener en cuenta la seguridad desde los principios. No te engaes pensando que securizando el cliente basta. Conclusin Los servicios web proveen una mejora sin precedentes en cmo se construyen las aplicaciones distribuidas fsicamente o en las organizaciones. Visual Studio.NET y el .NET framework permiten desarrollar servicios web de una manera simple y sencilla, incluso los mal hechos. Desarrollando tus servicios evitando estos clsicos errores asegurar a tu organizacin lo mejor de los servicios web.

Вам также может понравиться