60
dotNetManía nº14 abril 2005 • 6,00 (España) ToDotNet Q&A Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET Framework • Windows Server System Legal Consideraciones de rendimiento dotNetManía www.dotnetmania.com Dedicada a los profesionales de la plataforma .NET Protección formal de un programa de ordenador dotNetSolidario, el lado huma- no de la tecnología Comunidad.net Seguridad en los servicios Web • Manipulación de imágenes con ADO.NET • Sistemas distribuidos en .NET con Remoting (y III) • Interoperabilidad no administrada y migración (y III) PDF Caja transparente Entrevista a Brian Goldfarb Technical Product Manager de la Developer Division de Microsoft Entrevista a Brian Goldfarb Technical Product Manager de la Developer Division de Microsoft PDF Caja transparente MVP Online MZ-Tools

Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Embed Size (px)

Citation preview

Page 1: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotNetManíanº

14 a

bril

2005

• 6

,00

€(E

spañ

a)

ToDotNet Q&A

Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET Framework • Windows Server System

Legal

Consideraciones de rendimiento

dotNetManíawww.dotnetmania.com Dedicada a los profesionales de la plataforma .NET

Protección formal de un programa de ordenador

dotNetSolidario, el lado huma-no de la tecnología

Comunidad.net

Seguridad en los servicios Web •Manipulación de imágenes con

ADO.NET • Sistemas distribuidos en.NET con Remoting (y III) • Interoperabilidad noadministrada y migración (y III)

PDFCaja transparente

Entrevista a Brian GoldfarbTechnical Product Manager de la Developer Division de Microsoft

Entrevista a Brian GoldfarbTechnical Product Manager de la Developer Division de Microsoft

PDFCaja transparente

MVP OnlineMZ-Tools

Page 2: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que
Page 3: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Bienvenidos al número 14 dedotNetManía de abril de 2005.

En este mes no tenemos grandesnoticias que publicar, pero, en cambio,sí tenemos un par de eventos que anun-ciarle, muy importantes para los desa-rradores de la plataforma .NET. Por unlado, los Solid Quality LearningUniversity Summits, que se impartiránen Madrid entre el 25 y 29 de abril y enBarcelona entre el 2 y 6 de mayo conla mayoría de sesiones en castellano; y,por otro, el evento más importante paradesarrolladores que Microsoft Ibéricacelebra cada año: el DevDays, que esteaño se celebrará en el mes de mayo ydonde tendremos ocasión de escuchar,entre otros, a los Regional Directors deEspaña. ¡Será cuestión de hacerse unhueco en la agenda!

Para este número hemos preparadouna estupenda entrevista con BrianGoldfarb, Technical Product Manager dela Developer Division de Microsoft Corp.,y con el que tuvimos la ocasión de char-lar en Madrid, adonde vino con ocasióndel ASP.NET 2.0 Tour. Con él hablamoslargo y tendido de la nueva versión deASP.NET.

A destacar, el artículo de BraulioDíez sobre el formato de los archivosPDF. Enfocado a quien necesite incluiren sus programas la generación de estetipo de archivos, y lo hace desde trespuntos de vista diferentes: de quienquiera currárselo desde cero –hay quever lo que nos gusta eso a todos–; de

los que opten por el uso de una libre-ría gratuita y de código abierto; y delos que quieran rascarse el bolsillo ycomprar alguna librería. Hay unaopción más en la sección dnm.laborato-rio.net, para los que no queden con-formes con lo expuesto. Y aún así que-dan muchas opciones en el mercado,pero nada más gratificante que rein-ventar la rueda y pegarse con el for-mato de los archivos PDF y hacérselouno mismo ¿verdad?. Tan bonito, comoimproductivo, por otra parte.Aprovecho para agradecer a Fran Remde TallComponents BV por su ines-timable colaboración en la preparaciónde este artículo.

Y nos queda más, cómo no: losúltimos artículos de las series deSistemas distribuidos con .NETRemoting, de Rodrigo Corral, y deInteroperabilidad no administrada yMigración de José Miguel Torres, alos que liberamos para que nos escri-ban sobre otros temas que seguro quele van a interesar. Y los artículos, comosiempre con buenos fundamentos, dePepe Hevia sobre Seguridad en los ser-vicios Web y de Luis Miguel Blancosobre Manipulación de imágenes conADO.NET.

Por último, no olvide hacer el cru-cigrama que estrenamos este mes.Parece que los autores del GrupoWeboo se han empeñado en volver-nos realmente dotnetmaníacos.

Espero que le guste.do

tNet

Man

ía<<

3

Eventos a la vistadotNetManíaDedicada a los profesionales de la plataforma .NET

Vol. II •Número 14 • Abril 2005Precio: 6€ (España)

EditorPaco Marín

([email protected])

AdministraciónPilar Pérez

([email protected])

Asesor Técnico/CoordinaciónMarino Posadas

([email protected])

RedactoresAntonio Quirós, Dino Esposito, Guillermo

'guille' Som, Jorge Serrano, José ManuelAlarcón, Luis Miguel Blanco,y Pedro Pozo.

Colaboradores habitualesÁngel Esteban, Braulio Díez, Eladio Rincón,

Erich Bühler, Fernando Nogueras, JorgeCrespo Cano, José Miguel Torres, ManuelImaz, Miguel Egea, Miguel Katrib Mora

(Grupo Weboo), Octavio Hernández, PabloAbbate, Pepe Hevia, Rodrigo Corral y

Salvador Ramos.

Además colabora en este númeroJavier Aragonés Miranda (Suárez de la Dehesa

Abogados)

Edición y Suscripciones.netalia

c/ Robledal, 13528529 Rivas-Vaciamadrid (Madrid)

Tf. (34) 91 666 74 77Fax (34) 91 499 13 64

PublicidadMediadev

Sophie Mancini ([email protected])Tf. 93 426 22 57 - 670 99 74 64

Fax. 93 423 11 40

ImprimeGráficas Vallehermoso

www.graficasvallehermoso.com

ISSN1698-5451

Depósito LegalM-3.075-2004

<<

dnm.editorial

Page 4: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

14dnm.sumario

Protección formal de un programa de ordenador 8-9En este artículo se intentarán exponer brevemente las principales opciones que tiene unprogramador cuando se plantea proteger su creación.

Entrevista a Brian Goldfarb 10-13Con motivo del ASP.NET 2.0 Tour que impartieron por toda Europa Eric Ruddery Brian Goldfarb, tuvimos ocasión, durante su estancia en Madrid, de entrevistara éste último, en calidad de Product Manager de la próxima versión de ASP.NET,y aprovechamos para preguntarle por los pormenores de esta nueva versión.

Seguridad en los servicios Web 14-18Mucho se ha hablado de la seguridad de las páginas ASP.NET. Pero más importante aúnes el hecho de asegurar nuestros servicios de negocio. Veremos como proteger nuestrosservicios con modelos de autenticación / autorización y cómo escribir nuestros clientes paradiseñar entornos distribuidos seguros.

Manipulación de imágenes con ADO.NET 19-24Cualquier desarrollador que se haya acercado a la tecnología .NET, en su vertientede acceso a datos, dominará la arquitectura de ADO.NET cuando se trata de crearun proceso de mantenimiento de datos típico, utilizando los tipos de datos habituales.Pero, ¿qué ocurre cuando entran las imágenes como parte del mantenimiento?, ¿cómoagregamos estos elementos a una gestión de datos? En el este artículo describimos losrecursos que nos ofrece .NET, y las técnicas a nuestra disposición para integrar lasimágenes como parte de los procesos de manipulación de datos.

Sistemas distribuidos en .NET con Remoting (y III) 25-28Último artículo sobre Sistemas distribuidos en .NET con Remoting. Una vez visto cómoconfigurar las opciones de los objetos, los canales que usaremos y la ubicación de éstosmediante RemotingConfiguration, veremos cómo configurar .NET Remoting mediantearchivos. Finalmente veremos cómo utilizar un servicio o IIS como host en lugar de unaaplicación de consola como hemos venido haciendo hasta ahora.

Interoperabilidad no administrada y migración (y III) 29-33En esta última parte describiremos cómo llamar a funciones externas con un ejemplo auna API de Windows. También describiremos la utilización de TypeLibConverter, en elproceso de exportación e importación de la biblioteca de tipos, clave para llevar acabo lainteroperabilidad COM.

PDF.Caja transparente 36-44Para la mayoría de la gente, el formato PDF es un tipo de documento universal que sepuede ver desde cualquier máquina sin perder detalle. ¿Cómo se crea un PDF?Herramientas especiales, conversores…, en definitiva: “cajas negras”. En este artículovamos a convertir dicha caja opaca, en transparente, estudiando su formato y viendo lasdiversas formas de generarlo; para ello usaremos C#.

dnm.mvp.online 46-49MZ-Tools de Carlos Quintero.

dnm.comunidad.net 50-51dotNetSolidario. El lado humano de la tecnología.

dnm.todotnet.qa 52-54Consideraciones de rendimiento.

dnm.laboratorio 55-56ASP.NET Version Switcher, Localization Manager, ISAPI URL Mapper y Sharp PDF

dnm.biblioteca.net 57La Cara Oculta de C# (Ian Maartens)Windows Forms Programming in C# (Chris Sells)

dnm.desvan 58dnm

.sum

ario

Page 5: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que
Page 6: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

6

dnm.noticias<<dnm.noticias

Microsoft presenta las nuevas ediciones de SQLServer 2005 y Visual Studio 2005

no

ticia

s.n

oti

cia

s.n

oti

cia

s.n

oti

cia

s.n

oti

cia

s.n

oti

cia

s

Microsoft ha presentado las nuevas ediciones de SQL Server 2005 y VisualStudio 2005, con las que la compañía espera responder a las necesidadesde cada segmento de clientesEdiciones de SQL Server 2005 y nueva ver-sión CTP pre-beta 3

Las ediciones previstas así como susprecios (en dólares, aún no tenemos losprecios en euros para España) son:

• SQL Server 2005 Enterprise Editionestá pensada para aplicaciones de nego-cio de misión crítica de grandes empre-sas.Esta edición ofrecerá partición dedatos, alta disponibilidad avanzada concapacidades de database mirroring, analí-ticas complejas e integración, generaciónde informes ad hoc con Report Builder,etc. Disponible a un precio de venta esti-mado de 24.999$ por procesador,13.499$ por servidor (25 CAL).

• SQL Server 2005 Standard Editionestá diseñada para las medianas empre-sas e infraestructuras que requieren sis-temas altamente disponibles. Esta edi-ción proporcionará funcionalidadmejorada que antes sólo estaba inclui-da en SQL Server 2000 EnterpriseEdition, tales como alta disponibilidadavanzada con capacidades de databasemirroring y clustering y soporte inte-grado de 64 bit. Esta edición soportahasta cuatro procesadores, base dedatos de tamaño ilimitado y sistema dememoria ilimitado. También incluyeSQL Server Integration Services, SQLServer Analysis Services y SQL ServerReporting Services, lo que aporta a losclietnes una potente funcionallidad de

business intelligence sin coste adicional.Disponible a un precio estimado de5.999$ por procesador ó 2.799$ porservidor (10 CAL).

• SQL Server 2005 Workgroup Editiones el producto más novedoso disponibletanto para SQL Server 2000 como SQLServer 2005, y proporciona una soluciónde base de datos asequible, fácil de usary sencilla de gestionar, diseñada especí-ficamente para las pequeñas y medianasorganizaciones. Workgroup Editionsoporta hasta dos procesadores, base dedatos de tamaño ilimitado y 2 Gb dememoria. Disponible a un precio de ven-ta estimado de 3.899$ por procesador y739$ por servidor.

• SQL Server 2005 Express Edition esuna versión gratuita y redistribuible delmotor de base de datos de SQL Server2005, diseñada para construir sencillasaplicaciones de base de datos, que susti-tuye a MSDE (Microsoft Data Engine)para SQL Server 2000. Los clientespodrán incrustar y redistribuir SQLServer 2005 Express Edition con sus apli-caciones. Se puede descargar gratuita-mente de la Web e incluye una herra-mienta gráfica de gestión, controles y unasistente para informnes, replicación, uncliente SQL Service Broker, encripta-ción de base de datos nativa, soporteXML y CLR.

Y ya está disponible la tercera CTPde SQL Server 2005, posiblemente laúltima antes de la beta 3, que incluyenuevas características, de las que quizá lamás significativa es la incorporación deReport Builder, un nuevo componente deSQL Server 2005 Enterprise Edition, quese basa en la tecnología adquirida deActvieViews en el 2004. Gracias a estaherramienta el reporting empresarial serámás fácil para los usuarios finales.

Ediciones de Visual Studio 2005 y nueva ver-sión CTP pre-beta 2

Asimismo, Microsoft Corp. haanunciado las ediciones de Visual

Studio 2005, que estarán disponibles afinales de año junto con SQL Server2005 -según Prashant Sridharan, LeadProgram Manager del equipo de desa-rrollo de Visual Studio 2005-, así comola nueva CTP de la ediciónProfessional disponible para suscrip-tores MSDN y betatesters. Las edi-ciones de Visual Studio 2005 serán:

• Visual Studio 2005 Team System.Con herramientas integradas para lagestión del ciclo de vida de desarrollode software.

• Visual Studio 2005 Professional Edition,una edición asequible destinada a losdesarrolladores profesionales que traba-jan en pequeños grupos de trabajo.

• Visual Studio 2005 Standard Edition,una edición para desarrolladores a tiem-po parcial o aplicaciones de negocio quele permitirá desarrollar aplicacionesWindows, Web o para dispositivos móvi-les. Esperamos una beta 2 en castellanode esta edición para el mes de abril.

• Visual Studio 2005 Tools for theMicrosoft Office System, la edición parael desarrollador profesional que cons-truya soluciones para Microsoft OfficeSystem usando Excel, Word e Infopath.

• Ediciones Visual Studio 2005 Express:– Visual Web Developer 2005Express Edition, una herramientaligera para la construcción de sitiosWeb dinámicos y servicios Web.– Visual Basic 2005 Express Edition,Visual C# 2005 Express Edition,Visual C++ 2005 Express Edition yVisual J# 2005 Express Edition.Igualmente ediciones ligeras paraayudar a los programadores queempiezan a construir aplicacionespara Windows.

En breve estarán disponibles las versio-nes beta 2 públicas de estas ediciones queincluiremos en el número correspondiente dedotNetManía (mayo o junio) de forma gra-tuita.

Page 7: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Las correcciones incluidas en este Service Packestán relacionadas con las mejoras de estabilidady seguridad realizadas en muchas áreas del pro-ducto. La lista completa de revisiones solicitadaspor los usuarios desde el lanzamiento de VisualStudio .NET 2002 e incluidas en este Service Packse puede encontrar en: http://support.microsoft.com/kb/837234. Para descargar el Service Pack 1 paraVisual Studio 2002 debe ir a: http://msdn.micro-soft.com/vstudio/downloads/updates/sp

Service Pack 1 para VisualStudio .NET 2002

dnm.noticias<<

dnm.noticias

dotN

etM

anía

<<

7

M i c r o s o f tCorp. ha anuncia-do la primera CTP( C o m m u n i t yTechnology Preview)de Indigo, el próxi-mo subsistema decomunicaciones yque estará disponiblepara su descarga paralos suscriptores a

MSDN, el 31 de marzo, dato que al cie-rre de esta revista no hemos podido com-probar y no sabemos si finalmente se harádisponible para el “38 de marzo” comoEric Rudder, Vicepresidente Senior de laDivisión de Servidores y Herramientas deMicrosoft Corp, dijo, bromeando -creemos-, en el pasado VSLive! de San Franciscoen el que ya anunciaba estas versiones jun-

to con Ari Bixhorn, Lead ProductManager of Web services Strategy deMicrosoft.

Ari Bixhorn ha publicado unapequeña entrevista en el sitio de pren-sa de Microsoft Corp. y que puede leeren http://www.microsoft.com/presspass/fea-tures/2005/mar05/03-16WebServicesPreview.asp.

Junto con esta versión de Indigo,también se liberará la segunda CTP deAvalon, el susbsitema de presentaciónde Longhorn y que, igualmente, estarádisponible para suscriptores MSDN...el 31 de marzo.

Si desea más información sobreIndigo y, en general, sobre todo el nue-vo entorno de programación deLonghorn, WinFX, puede visitar:http://winfx.msdn.microsoft.com.

Microsoft anuncia la disponibilidad dela primera CTP de Indigo y la segundade AvalonLos desarrolladores pueden probar por primera vez lanueva generación de programación orientada a servicios

Otras noticias

El 17 de mayo se celebrará en el cineKinepolis de Pozuelo de Alarcón en Madrid elMicrosoft Developer Day, un clásico en even-tos orientados a la comunidad de desarrolladores,reproducido en la mayoría de los países a lo lar-go del mundo. Este evento está patrocinado tra-dicionalmente por los Regional Directors, peroen esta ocasión también participarán algunos part-ners de Microsoft. Será un evento técnico, paradesarrolladores, en el que se verán las novedadeslas novedades más importantes en la próxima ver-sión de la plataforma de desarrollo Visual Studio2005 y también de SQL Server 2005. Aún espronto, pero por lo que hemos podidos saber, sehará un repaso de las mejoras introducidas en cadauno de los pilares que forman ambos productos.

Aún no tiene una direción definitiva peropodrá encontrarlo en la web de MSDN Españaen: www.microsoft.com/spain/msdn

Microsoft Developer Day 2005

Solid Quality Learning viene impartien-do a lo largo de ciudades de todo el mundo loseventos formativos “SQL Quality LearningUniversity Summits”. Después de pasar porViena y Buenos Aires, pasarán por Madrid entreel 25 y el 29 de abril y por Barcelona entre el 2al 6 de mayo.

La mayoría de los ponentes serán de hablacastellana, entre los que se encuentran MiguelEgea, Eladio Rincón, Fernando Guerrero,Antonio Soto, Guillermo “El Guille” Som,Jordi Rambla, Daniel Seara, Pablo Peláez,Alejando Leguízano, Michael Hotek y RonTalmage. También contarán con CesarGalindo-Legaria, Manager del SQL ServerQuery Optimizer Group de Microsoft Corp.

Más información: http://www.solidqualityle-arning.com/view.aspx?source=SQLUMadrid2005Summit y en Barcelona: http://www.solidqua-litylearning.com/view.aspx?source=SQLUBarcelona2005Summit.

SQLU 2005 Summit

Ari Bixhorn

Junto con la segu-ridad y las mejoras en elproducto, este SP2incluirá dos SharePointWeb Parts, que permiti-rán a los usuarios explo-rar y ver informes loca-lizados en un servidorde informes a través deWindows SharePointServices o SharePoint

Portal Server. Los Web Parts facilitarán a losclientes, la creación de portales de business inte-lligence con Sharepoint que incluyan informesde Reporting Services. SP2 también permitiráal cliente la impresión de informes directa-mente desde Internet Explorer.

Microsoft lanza también SQL ServerReport Pack para IIS Logs. Este Report Pack

facilitará a los clientes el desarrollo de reportal proporcionar a los usuarios plantillas delos informes de uso más común de SQLServer Reporting Services, que estos pue-den modificar fácilmente para crear sus pro-pios informes personalizados de acuerdo consus propias necesidades. El Report Pack estádisponible desde finales de marzo para serdescargado de la Web.

“Nuestro objetivo desde que introdujimoscapacidades de business intelligence en SQLServer ha sido proporcionar a tantos usuarioscomo sea posible un conocimiento más ampliode sus negocios y del mercado, para que tomenlas mejores decisiones, y Reporting Services esel componente principal para conseguirlo.”, hadeclarado Fernando Bocigas, responsa-ble de negocio de SQL Server enMicrosoft Ibérica.

Nuevo Service Pack 2 de SQL Server2000 Reporting ServicesDesde su lanzamiento,en enero de 2004,se han descargadomás de 153.000 copias de SQL Server 2000 Reporting Servicesy 116.000 copias adicionales del Service Pack 1.

Fernando Bocigas

Page 8: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Protección formal de un programa de ordenador

En este artículo se intentarán exponer brevemente las principalesopciones que tiene un programador cuando se plantea proteger sucreación.

hay que dejar claro que el mero hecho decrear un programa de ordenador, sin necesidad de nin-gún otro requisito más que el de la originalidad, yasupone que dicho programa se encuentra protegidopor la legislación de propiedad intelectual.

Sin embargo, para hacer valer esa protección legal,conviene utilizar algún procedimiento que permita pro-bar que dicho programa fue creado por una determi-nada persona en un determinado momento, y es ahídonde se plantean diferentes alternativas que sirvenpara acreditar la autoría del programador. Las opcio-nes a las que nos referimos son las siguientes:

• Inscripción de la obra en el Registro de laPropiedad Intelectual y

• Depósito del programa ante Notario

Junto a estas dos opciones disponemos de otrosmedios que también constituirán prueba de la auto-ría, y que son complementarias de las dos vías deprotección que hemos citado,como son las denominadas mar-cas de agua o la introducción delíneas de código neutras.

Inscripción de la obra enel Registro de laPropiedad Intelectual

Con respecto a la inscrip-ción de derechos de la obra enel Registro de la PropiedadIntelectual, lo primero que hayque decir es que la misma es

posible siempre que se trate de un programa ori-ginal cuyos derechos sean de titularidad de la per-sona a cuyo favor se inscriban. Por el carácter decla-rativo del Registro de la Propiedad Intelectual, elprincipal beneficio que se obtiene de la ins-cripción de derechos relativos a una obra en el mis-mo es la creación de una presunción de titula-ridad a favor de la persona o empresa a cuyo nom-bre está registrada.

En cuanto al procedimiento de inscripción, estepuede resultar un poco laborioso, porque junto alimpreso oficial de solicitud, ha de presentarse en elRegistro la siguiente documentación:

1. La totalidad del código fuente en papel debi-damente encuadernado y paginado incluyen-do el título y nombre y apellidos del autor otitular originario, salvo que por la extensióndel mismo el registro exija que se aporte enformato CD-ROM o disquete.

Javier Aragonés Miranda

dnm.legal

<< En primer lugar,

Javier Aragonés Mirandaes abogado de Suárez

de la Dehesa Abogados,despacho especializado en

Propiedad Intelectual e Industrialy Nuevas Tecnologías.

http://www.suarezdeladehesa.com

Por el carácter declarativo del Registro de laPropiedad Intelectual, el principal beneficio que seobtiene de la inscripción de derechos relativos auna obra en el mismo, es la creación de una pre-

sunción de titularidad a favor de la persona oempresa a cuyo nombre está registrada

Page 9: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

2. 1. Un ejecutable del programa, que seaportará también en CD-ROM o disquete.

3. Justificante del abono de la tasa correspon-diente.

4. Opcionalmente, aunque es recomendable, pue-de presentarse una memoria que contenga:

• Una breve descripción del programa deordenador.

• El lenguaje de programación.• El entorno operativo.• Un listado de ficheros.• El diagrama de flujo.• En su caso, número de depósito legal.

5. Y, en el caso de ser una empresa la titular delprograma, se ha de presentar también:

• Los datos identificativos de la misma,incluyendo el CIF.

• El título que acredite su personalidadjurídica (escritura de constitución, porejemplo) y

• Los documentos acreditativos de lacesión de los derechos de propiedad

intelectual realizada por los trabajado-res. Si son asalariados será suficientepresentar el contrato de trabajo y jus-tificante de pago de las cuotas a laSeguridad Social.

Como se aprecia, la inscripción de derechos deun programa de ordenador en el Registro de laPropiedad Intelectual requiere mucha documen-tación, lo que puede suponer un inconveniente parael titular, ya que ha de aportar copia compulsadade toda la documentación presentada, y eso puedeencarecer bastante el coste de la inscripción, sobretodo en el supuesto de que el titular sea una empre-sa, porque la compulsación se puede llevar a cabopor los funcionarios del Registro o por un Notario,y de ambos, es más económico hacerlo anteNotario.

Junto al coste y documentación necesaria, otroinconveniente que puede presentar la inscripciónen el Registro es la obligación de entregar la tota-lidad del código fuente, ya que ello suele ser unatraba muy grande para muchas empresas que, lógi-camente, prefieren mantener el mismo en secreto,pues constituye su activo más preciado.

Depósito del programa ante NotarioEs por este segundo inconveniente que, como

opción complementaria o sustitutoria a la inscripciónen el Registro, puede realizarse el depósito notarialdel programa de ordenador, pues requiere menos for-malismos y documentación, y con el mismo se obtie-nen prácticamente los mismos efectos que propor-ciona el Registro, que no son otros que fehacienciaen cuanto a la titularidad y al tiempo.

El procedimiento para depositar el programa anteNotario podrá variar ligeramente según la Notaríaque se elija pero, en general, todos tiene en comúnque se requiere al Notario para que custodie en unsobre sellado y lacrado un CD-ROM que contengael código del programa, lo que ellos se encargan dehacer durante el tiempo que se acuerde por una can-tidad de dinero que no resulta excesivamente alta,pues suele tener un coste aproximado de unos 150 o200 euros por CD depositado.

ConclusiónAsí pues, como conclusión y de manera gene-

ral, si el titular del programa es una persona físicapuede ser preferible y más económico proceder ala inscripción en el Registro de la PropiedadIntelectual; mientras que si el titular es una empre-sa, puede resultar más conveniente proceder aldepósito ante Notario. Pero la elección final varia-rá dependiendo del caso y de las preferencias deltitular del programa que se quiere proteger.

dotN

etM

anía

<<

9

dnm.legal<<

Como opción complementaria o sustitutoria a la inscripción en el Registro, puede

realizarse el depósito notarial del programa de ordenador, pues requiere menos

formalismos y documentación y con el mismo se obtienen prácticamente los

mismos efectos que proporciona el Registro

Page 10: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Entrevista a Brian Goldfarb

Con motivo del ASP.NET 2.0 Tour que impartieron por toda Europa Eric Rudder yBrian Goldfarb, tuvimos ocasión, durante su estancia en Madrid, de entrevistar a ésteúltimo, en calidad de Product Manager de la próxima versión de ASP.NET, y aprove-chamos para preguntarle por los pormenores de esta nueva versión.

exactamente en la promoción de ASP.NET?Básicamente, el de recoger las necesidades de los

desarrolladores, organizarlas y trasladarlas al equipode desarrollo, de forma que dispongamos de ese feed-back tan importante para nosotros.

¿Hasta qué punto es necesario para ti conocer elproducto?

Hasta sus más íntimos detalles, si quieres hacer-lo bien. No se trata de un producto de consumo masi-vo, ni de una herramienta de producción, sino deuna herramienta de desarrollo. Y los desarrollado-res tienen un perfil muy técnico y esperan respues-tas detalladas y concretas. A un desarrollador no pue-

des hablarle de “valores de negocio” ni de “oportu-nidades estratégicas” porque es algo que no le impor-ta. Lo que quiere saber es qué hace el producto, cómolo hace, y qué tiene de nuevo respecto a la versiónanterior.

Antes de hablar acerca de las características de lanueva interfaz de usuario y los nuevos controles deservidor, me interesan especialmente los cambios enla arquitectura. ¿Podrías resumirlos y explicarlos bre-vemente?

En el nivel más básico del sistema podemos encon-trar todo lo que llamamos Servicios de Aplicación. Cosasque ayudan a reducir el código necesario para un desa-

Marino Posadas

dnm.directo.entrevistas

Marino Posadas esasesor técnico y

redactor dedotNetManía, MVP de

C# y formador deAlhambra-Eidos

<< ¿Cuál es tu papel

Brian Goldfarb

Page 11: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

rrollo, como la gestión de credenciales,control de roles de aplicación, persona-lización, localización, etc. Esos serviciosbásicos constituyen la base de todas lasmejoras. Podríamos considerar cuatropilares principales:

El primero, sería la productividad decara al desarrollador. Desglosado en dosconceptos. Uno es simplificación de losconceptos de codificación necesarios; yel segundo, mejorar la calidad de laherramienta de desarrollo Web.

El segundo pilar es la extensibilidad.Si lo que el desarrollador necesita es lacapacidad de crear aplicaciones de mul-ticapa, debemos suministrarle esa posi-bilidad de la forma más natural posible,y poco adelantamos con permitir que searrastre una tabla sobre una página ycree una serie de elementos para pro-gramar esa tabla, porque nadie hace lascosas de esa manera. Necesitamos ele-mentos diferentes que suministren esasposibilidades, que en este caso son sumi-nistradas mediante lo que llamamos elpatrón de proveedores. Tenemos que sercapaces de modificar y descargar esque-mas, y ser capaces de adaptar esos esque-mas a la forma en que todo esto fun-ciona realmente.

El tercer pilar es la capacidad de man-tenimiento y gestión. Uno de los proble-mas a resolver era facilitar la adminis-tración e implantación de las aplicacio-nes. Dando soporte mejorado de laimplantación, añadiendo posibilidadesque faciliten la labor de los administra-dores, el seguimiento de los errores, etc.

Y el cuarto pilar es el rendimiento. Ylas consideraciones de escalabilidad delas aplicaciones, que tienen mucho quever con esto. Conseguir que sea fácil la

creación de granjas de servidores quesuministren altas prestaciones. Porejemplo, hemos hecho un gran esfuer-zo respecto a la implantación deASP.NET 2.0 en máquinas de 64 bits.

Otra gran novedad que se presenta,es la posibilidad de construir sitios Websin la presencia de IIS en la máquinadonde se desarrolla. ¿Eso se va a exten-der desde la fase de desarrollo a la deimplantación?

Visual Studio 2005 incluye un ser-vidor Web dentro del paquete de soft-ware. Esto te permite no tener que con-figurar el IIS dentro de la máquina dedesarrollo, o que existan varios desa-rrolladores depurando sobre la mismamáquina, y no tener que dar a los delequipo de desarrollo permisos especia-les, por ejemplo. No obstante, desde elpunto de vista de la implantación, sí quese necesita una instancia de IIS: un ser-vidor Web real. Aún así, se trata de ungran cambio, porque evita pasar por losproblemas de configuración de IIS.

Resulta notable la presencia de unprograma FTP dentro del entorno de

desarrollo, al menos dentro de la beta ala que hemos tenido acceso. ¿Va a seguiresto siendo así en la versión final?

Como parte de la idea de conseguirque Visual Studio 2005 fuera una herra-mientas más amigable, necesitábamosalgo así en el producto. Por eso damossoporte a cuatro formas de creación desitios Web: como un sistema local, comouna aplicación tradicional gestionadabajo IIS, mediante al soporte de FTP y

también, mediante la posibilidad de cre-ar sitios Web directamente sobre unaURL remota, vía HTTP.

Otra cuestión relativa a la arquitec-tura tiene que ver con la presencia denuevos directorios predeterminados aso-ciados con el sitio Web: data, code,resources, localresources, webreferen-ces, browsers y themes.

El nuevo modelo, incluyendo todaslas mejoras que queríamos incluir,requería de la presencia de estos direc-torios. Cuando planteamos esta situa-ción, tuvimos en cuenta la posibilidadde que otras aplicaciones utilizasen yaestos nombres de directorios, para evi-

Visual Studio 2005 incluye un servidor Web dentro. Esto tepermite no tener que configurar el IIS dentro de la máquina

de desarrollo, o que existan varios desarrolladores depurando sobre la misma máquina, y no tener que dar

a los del equipo de desarrollo permisos especiales

dotN

etM

anía

<<

11

dnm.directo.entrevistas<<

De Izquierda a derecha: Marino Posadas, Brian Goldfarb y David Carmona

Page 12: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

tar las posibles colisiones. Así que deci-dimos finalmente llamar así a los direc-torios, pero haciéndolos preceder delprefijo app_. De esa forma, tendremos,al final, app_data, app_code, etc.

Dinos algo acerca del nuevo mode-lo de compilación.

Es muy interesante y ofrece un mon-tón de beneficios al desarrollador. En elnuevo modelo, podemos aprovechar unanueva característica denominada tiposparciales. Esto nos permite separar laclase que estamos construyendo en múl-tiples ficheros. Es una situación muysimilar a la que planteará XAML parala construcción de aplicaciones paraLonghorn. En ASP.NET 2.0 tendre-mos la opción de precompilar incluso elcódigo de marcado (la parte HTML,por decirlo así). En la beta 2, ya ten-dremos la oportunidad de compilar enun ensamblado todo el código de mar-cado, o mantener el mismo modelo exis-tente hoy, con un conjunto de ficheros

de código de marcado y un grupo deDLL asociadas funcionalmente con esecódigo.

Esa es otra cuestión importante.Parece que ahora vamos a tener un con-junto de DLL diferentes en lugar de unasola con todo el código fuente.

Efectivamente, esta es una cues-tión que nos lleva de nuevo al mode-lo de compilación. En esta forma,podemos manejar mejor los conteni-dos del proyecto, añadiendo un factorde granularidad que no estaba pre-sente antes. Permite que diferentesdesarrolladores puedan trabajar deforma independiente sin propagaciónmutua de los errores producidos, man-teniendo cada uno su versión del códi-go generado y evitando colisiones.Esto nos permite realizar cambios yver los resultados con un simplerefresco de la página en el navegador,reflejando mucho mejor la forma detrabajar del programador Web.

¿Qué hay de nuevo desde el puntode vista del acceso a datos?

En ASP.NET 1.1, el trabajo condatos conllevaba una buena cantidad decódigo fuente de soporte. Así que hemosasumido un nuevo modelo de enlace adatos basado en dos objetos que intro-duce esta versión. Por ejemplo, el nue-vo control DataSource. Este control per-mite vincular elementos diferentes deuna página al mismo control DataSourcey mantener una vista de datos actuali-zada sin necesitar ningún código fuen-te de soporte adicional. Eso significatambién la posibilidad de edición, orde-naciones, paginaciones, etc., gestiona-da automáticamente por ese compo-nente. Cada DataSource se convierte enun elemento específico que vincula unorigen de datos: AccessDataSource,SQLDataSource, XMLDataSource, etc.El segundo punto crítico en cuanto aesto tiene que ver con lo que llamamosObject DataBinding. Estos objetos, lla-mados ObjectSources, permiten vincularun elemento de la interfaz de usuario ode la capa intermedia a cualquier ori-gen, pudiendo ser éste un servicio Web,un objeto de acceso a datos u otro obje-to de la capa de negocio, sin la necesi-dad de escribir código alguno. Esto per-mite diseñar sistemas de 3 capas realescon objetos de negocio fuertementetipados, que pueden vincularse directa-mente a los objetos de negocio.

Antes de pasar a comentar caracte-rísticas de la interfaz de usuario, comén-tanos qué novedades tenéis acerca de laseguridad.

Hemos hecho todo lo que estaba ennuestras manos para mejorar este aspec-to. Una de las novedades más interesan-tes es la forma en que funciona la perte-nencia a grupos (membership) en esta ver-sión. La manera en que se almacenan ytransportan las credenciales, de formaencriptada, supone que ahora no hay for-ma de que un hacker pueda hacer inge-niería inversa de las contraseñas, o de losnúmeros de una tarjeta de crédito. Esoha supuesto miles de líneas de código adi-cional para construir un sistema de altaseguridad suministrado por defecto. Dela misma forma, ahora, por defecto, todotiene lugar en un contexto de ejecuciónde confianza media y no de confianza total(FullTrust) como sucedía antes.

dotN

etM

anía

<<

12

dnm.directo.entrevistas<<

La manera en que se almacenan y transportan las credenciales, de forma encriptada, supone que ahora no hayforma de que un hacker pueda hacer ingeniería inversa de las

contraseñas, o de los números de una tarjeta de crédito

Page 13: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Ya que hablamos de la herramienta, hay una pre-gunta que todos nos hacíamos desde hace muchotiempo. Por fin, parece que el editor de códigoHTML preserva la posición de las líneas editadaspor el desarrollador sin cambiarlas aleatoriamente.La cuestión es: ¿Era eso tan difícil de hacer?

Sin duda era una de las quejas que figurabanentre las 3 primeras solicitudes de cambio por par-te de todos los desarrolladores. Eso ya está arre-glado, como consecuencia de un trabajo intensivo,para permitir esta característica. No se trata de arre-glar un bug sino de añadir algo nuevo. Para darteuna idea de la dificultad, 3 desarrolladores han esta-do a tiempo completo trabajando esta capacidaddurante un año y medio. Utiliza un sistema de tri-ple búfer mucho más difícil de implementar de loque parece a primera vista, sin que produzca coli-siones con el resto del producto.

Se ha hablado mucho de los casi 60 nuevos con-troles de servidor que van a estar disponibles paraesta versión.

Dentro de lo que llamamos los nuevos Serviciosde Aplicación (Application Services), existe un paque-te impresionante de nuevos controles. Por ejemplo,Login, permite el control de acceso, recuperaciónde contraseñas, registro de usuarios, etc. Después,tenemos que considerar los nuevos controles paradatos. El GridView, que reemplaza al antiguoDataGrid, y que incluye la posibilidad de hacer todaslas manipulaciones asociadas a un mantenimientode forma automática y directa: “Añadir”, “Borrar”,“Modificar”, “Reordenar”, “Paginación”, etc. Elcontrol para las vistas de detalle (DetailsView), etc.Un conjunto muy completo para trabajar con la pre-sentación y manipulación de datos. Además tene-mos otro conjunto nuevo de controles para gestio-nar la navegación por páginas que se puede vincu-lar con la estructura de un sitio Web, con facilida-des nuevas para la construcción de TreeViews, Menús,etc. Y por último, todas las nuevas capacidades depersonalización tanto de la apariencia, como delcomportamiento funcional.

¿Y que hay de las nuevas Master Pages?

Son una forma de facilitar la construcción desitios basados en elementos fijos en la página prin-cipal (o en otras secciones de la Web), que inclu-yen variaciones en la zona central dependiendo dela selección del usuario. Y además, se obtiene sopor-te en tiempo de diseño gracias a Visual Studio, conuna total personalización del aspecto para adecuar-se a cualquier tipo de presentación. Y en todomomento, en la ventana de pre-visualización pode-mos ver cómo va a ser el resultado. Suministra unsistema fácil, robusto y que además, incluye muchasmejoras en el rendimiento.

¿Qué es exactamente Visual Web Developer 2005Express Edition?

Es parte del nuevo conjunto de productos queforma parte de la familia Visual Studio. Su propó-sito es ese gran número de estudiantes, aficionadosy entusiastas que quieren conocer la tecnología sinentrar en las dificultades que conlleva una herra-mienta profesional. Aportan una forma de evaluarla tecnología como punto de entrada para valorarlas posibilidades. Por eso, existen otras versionessimilares para los otros lenguajes, como C++, C#,VB.NET y J#.

¿Va a existir alguna versión mejorada deWebMatrix?

No. No va haber una nueva versión deWebMatrix. Y Visual Web Developer 2005 ExpressEdition será el sustituto de este producto, con unprecio muy agresivo.

Y una última cuestión acerca del rendimiento.La forma en que se cree a partir de ahora un nue-vo sitio Web (máquina local, IIS, FTP o HTTP),¿va a tener algún tipo de impacto en el tiempo deejecución?

El nuevo modelo de compilación implica una míni-ma penalización la primera vez que se solicita una pági-na, siempre que ésta no esté precompilada. Pero estan sencillo de evitar como realizar un paso de pre-compilación. De hecho, eso es lo que se va a reco-mendar oficialmente, que se aprovechen esas nuevascaracterísticas, que mejorarán muchísimo el rendi-miento respecto a la situación actual.

dotN

etM

anía

<<

13

dnm.directo.entrevistas<<

El nuevo modelo de compilación implica una mínima penalización la primera vez que se solicita una página, siempre que ésta no esté precompilada.

Pero es tan sencillo de evitar como realizar un paso de pre-compilación.De hecho, eso es lo que se va a recomendar oficialmente

Page 14: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Seguridad en los servicios Web

Mucho se ha hablado de la seguridad de las páginas ASP.NET. Pero más importan-te aún es el hecho de asegurar nuestros servicios de negocio.Veremos como pro-teger nuestros servicios con modelos de autenticación / autorización y cómoescribir nuestros clientes para diseñar entornos distribuidos seguros.

<< Uno es el de la seguridad de los ser-vicios Web integrada con Windows y su implicaciónen un entorno cliente/servidor;.y dos, el de poderextender a nuestro gusto, el mensaje de intercambiode datos SOAP para enriquecer lo que ya tenemos, oadaptarlo a nuestras necesidades, por ejemplo, la dela seguridad.

En este artículo, pretendo enseñaros el cómo escri-bir aplicaciones cliente/servidor basadas en serviciosWeb seguros, empleando por un lado la autenticaciónde la que tanto se ha hablado en número anteriores y,por el otro, una herramienta muy potente del están-dar WSDL/SOAP: la posibilidad de extender las cabe-ceras SOAP para extender el protocolo en base a nues-tras necesidades, por ejemplo, montar un sistema deseguridad “extendido” para pasar algo más que sim-ples credenciales.

Seguridad integrada con WindowsÉste es el punto más sencillo. De artículos ante-

riores hemos sacado en claro que la seguridad inte-grada de IIS es extremadamente sencilla de configu-rar. Se basa en asegurar un directorio virtual emple-ando los mecanismos de autenticación, o bien emple-ar el descriptor XML, web.config, para sobrescribirel comportamiento del propio IIS cuando nos referi-mos a un contexto Web de aplicación determinado–con la ventaja de no tener que andar cacharreandocon sus opciones–.

Si realizamos un sencillo servicio que ofrezca unproceso de negocio simple como, por ejemplo, con-vertir de pesetas a euros, el reto será el de garantizar

que sólo aquellos clientes autenticados correctamen-te, puedan acceder a las funciones del servicio. Paraello, realizaremos 3 sencillas operaciones:

a) Crear el proyecto de un servicio Web –como yaseguro que a estas alturas hemos hecho cientos deveces– al que llamaremos ServiciosMonetarios.

b) Crear un nuevo servicio Web en este proyectoal que denominaremos WSConversor. Su misión,ofrecer diversos mecanismos de conversión dedivisas (ver fuente 1).

c) Asegurar el servicio empleando el descriptorweb.config de nuestro proyecto. Configurandola autenticación integrada de Windows, paraevitar que nadie no autenticado, pueda consu-mir nuestros servicios (ver fuente 2).

Pepe Hevia

dnm.asp.net

Pepe Heviacolabora habitualmente con

dotNetManía. Es arquitecto desoftware senior en Alhambra-

Eidos.Tiene las certificaciones deMCAD,MCSD.NET y MCT en

.NET Framework.Ha escritovarios libros sobre la plataforma

.NET (lalibreriadigital.com)

Dos asuntos a tratar:

Imports System.Web.Services

<System.Web.Services.WebService(Namespace := _"http://tempuri.org/ServiciosMonetarios/WSConversor")>_Public Class WSConversor

Inherits System.Web.Services.WebService<WebMethod()> Public Function ConvertirEuros(_

ByVal pesetas As Long) As DoubleReturn pesetas / 166.386

End Function

<WebMethod()> Public Function ConvertirPesetas(_ByVal euros As Double) As Long

Return Convert.ToInt64(Math.Round(euros * 166.386))End Function

End Class

Fuente 1

Page 15: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Si todo está bien configurado, vere-mos que el intento de probar el serviciodesde el propio WebServices Explorer–que cariñosamente nos genera el pro-pio IIS–, nos anima amablemente aautenticarnos con cuentas Windows, obien a decirnos de una forma parca ysencilla que nos dediquemos a otrascosas, porque se nos ha denegado elacceso.

Es importante que tengamos encuenta, que la única autenticación queno podemos usar de las ofrecidas porASP.NET, es la que está basada enWebForms. Esto es lógico, pues estamoshablando de un modelo de servicios, enlos que seguro no cabrá la posibilidad deabrir un WebForm, o mejor aún, como nosabemos qué tecnología o framework vaa acceder al servicio, no podemos presu-mir de obligar al consumidor a usar

ASP.NET en un navegador cuando a lomejor, están empleando WinForms.Queda claro.

Ahora viene la parte curiosa. La quenos lleva a consumir el servicio desdeun cliente que no tiene por qué serWeb. Vamos a utilizar un clienteWinForm que nos ofrezca un interfazsencillo y discreto a la par que funcio-nal. Para ello crearemos un nuevo pro-

yecto y, tras una esmerada ventanacomo la que se ve en la figura 2, pasa-remos a importar una referencia al ser-vicio Web remoto. Tras autenticarnosy recoger el WSDL y haberse genera-do el correspondiente proxy SOAP, yasólo nos queda implementar la funcio-nalidad de los eventos clic de los boto-nes “A Euros” y “A Pesetas”, quedan-do tal y como se e en la figura 2 (vertambién fuente 3).

Como podréis observar, la autenti-cación es extremadamente sencilla cuan-do empleamos los objetos ICredentialde .NET. Acoplando las credenciales anuestro consumidor, conseguiremossuperar las barreras de seguridad yobtener nuestro preciado resultado.Como veis he optado por emplear laclase System.net.CredentialCache quenos proporciona la información de lacuenta activa del usuario. Pero si algu-no necesita especificarlo de un modomás explícito, podéis usar la claseSystem.net.NetworkCredentials.

Para probar qué pasa si no tenéispermisos de acceso, siempre podéisdenegar el acceso a todo quisqui des-de el web.config o bien, especificar

figura 1do

tNet

Man

ía<<

15

dnm.asp.net<<

Figura 2

<?xml version=”1.0” encoding=”utf-8” ?>

<configuration>

<system.web>

<authentication mode=”Windows” />

<authorization>

<deny users=”?” /> <!— Permitir a todos los usuarios —>

</authorization>

</system.web>

</configuration>

Fuente 2

Figura 3

Page 16: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

unas credenciales a piñón falsas. Alfinal, saltará una pedazo de Exceptionque dejará muy claras las cosas.

Pero hasta aquí lo sencillo. Y segu-ro que lo conocido. Pero esto tiene unpequeño inconveniente: que nos limi-tamos a la seguridad de credencialesde Windows y nada más. Si queremosrecoger más información acerca delusuario (grupo, máquina, rol, teléfo-no de la hermana, etc.) estaremos limi-tados a pasar dicha información comoatributos del servicio (parámetros,para llevarnos bien). Y eso, no es unasolución elegante. O bien comernosel tarro para integrarnos con un ActiveDirectory, emplear los objetos deDirectoryServices de .NET y recogertoda la información de usuario de sucuenta AD. Pero esto, que es muyinteresante –y que veremos en futu-ros artículos– ahora se nos sale de loslímites de los objetivos y, en muchoscasos, de las necesidades reales de unproyecto.

Pero ahora viene una solución alter-nativa.

Cabeceras SOAP personali-zadas

Como hemos podido ver, es extrema-damente sencillo y transparente asegurarun servicio Web empleando la seguridadASP.NET –y, por extensión, la de IIS–.Pero ¿qué ocurre si es requisito del pro-yecto el montar un sistema de seguridadde aplicación casero que no dependa denadie más que de nosotros? El problemaque se nos plantea es que sea el propio ser-vicio Web el que valide la seguridad en sumismo código. Y para ello debemos esta-blecer que algunos de sus parámetros

especifiquen las credenciales. Pero eso noes del todo cómodo y complica las espe-cificaciones de los servicios, ya que nosvemos “copiando/pegando” las definicio-nes en todas las llamadas. Pero hay unaalternativa muy interesante…

Porqué no hacer que sea el propioprotocolo de comunicaciones de losservicios web (SOAP) el que propagueunas credenciales que hemos diseñadonosotros. Y que luego cada serviciorecoja del protocolo dichas credencia-les, como si fueran una parte integrantemás de la clase del servicio. Es decir,que se nos permite extender el esque-ma del mensaje SOAP para que agre-guemos nuevas clases, que serán recu-peradas por los mismos mecanismosque generan dicho SOAP: la serializa-ción automática del propio servicioweb. Muy práctico.

La idea: diseñar un sistema de segu-ridad. Necesidad: diseñar la clase querepresentará el modelo de informaciónde las credenciales de seguridad.Objetivo: integrar ese modelo de infor-mación en el mensaje SOAP e integrarlocon la lógica de negocio.

La extensibilidad de SOAP en .NETes especialmente transparente. El mode-lo SOAP corresponde a los interfaces queexpone el servicio. Es decir, los métodosque establece como públicos y bajo ladirectiva WebMethod. El serializador, pues,genera el esquema WSDL y de éste elmensaje SOAP en el momento de laacción. Pues bien, extender las cabece-ras es un proceso similar. Agregamos unmodelo de información a la clase del ser-vicio Web (en cristiano, un nuevo tipode clase), y la exponemos como exten-sión al mismo en los métodos que lorequieran (en cristiano, definimos unavariable miembro que actuará de objeto

dotN

etM

anía

<<

16

dnm.asp.net<<

Public Class FrmConversorInherits System.Windows.Forms.Form

(...)

Private Sub btnAEuros_Click( ByVal sender As System.Object,_ByVal e As System.EventArgs) _

Handles btnAEuros.ClickDim conversor As New localhost.WSConversor

'si queremos recoger la autenticacion actual del sistemaconversor.Credentials = System.Net.CredentialCache.DefaultCredentials

'si queremos especificarla de modo explicito emplear'la clase New NetworkCredentials("usuario","password"[,"dominio"])lbResultado.Text = conversor.ConvertirEuros(Int64.Parse(txtCantidad.Text)) & " €"

End Sub

Private Sub BtnPesetas_Click( ByVal sender As System.Object,_ByVal e As System.EventArgs) _

Handles BtnPesetas.ClickDim conversor As New localhost.WSConversor

'si queremos recoger la autenticacion actual del sistemaconversor.Credentials = System.Net.CredentialCache.DefaultCredentials

'si queremos especificarla de modo explicito emplear'la clase New NetworkCredentials("usuario","password"[,"dominio"])lbResultado.Text = conversor.ConvertirPesetas(Double.Parse(txtCantidad.Text)) &" Pts"

End SubEnd Class

Fuente 3

ASP.NET nos ofrece muchos mecanismos de seguridad y control de privilegios que pueden ser

reutilizados en los servicios web. La mayoría pasan porajustar correctamente el archivo web.config y

preparar los clientes para contemplar esta posibilidad

Page 17: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

cuando se requiera). Para ello empleare-mos la directiva SoapHeader en cada ser-vicio Web. De esta manera, la nuevacabecera será serializada por el mismoproceso, evitándonos todo ese trabajoque implica. Agregando un nuevo servi-cio Web a nuestro proyecto, que he lla-mado WSConversorExtendido –bajo unnuevo proyecto de servicio Web, deno-minado ServiciosMonetariosEx–, mirarcómo queda el código, que es muy claro(fuente 4).

Como podéis observar, es extremada-mente fácil de implementar. En este sen-cillo ejemplo, me limitaré a comprobarun nombre de grupo para autenticar alusuario. Ni qué decir tiene que no es másque la punta del iceberg, ya que tenéis laposibilidad de utilizar estos datos a vues-tro antojo (bases de datos, servicios deseguridad, integración con AD, etc.).

En nuestro ejemplo, en este nuevocaso, nos aseguraremos de permitir elacceso anónimo al servicio Web desde elmotor ASP.NET o del IIS, ya que la res-ponsabilidad de autenticación recae en elpropio servicio. Aunque si alguien quierereforzarlo, no tiene más que dejar la segu-ridad como lo especificamos en el ejem-plo anterior. Pero sería redundante, ¿no?.

Antes de continuar, aprovecho parahacer el inciso. Sería estupendo que acce-dierais al esquema WSDL del nuevo ser-vicio. Para evitar que el editor me matemostrando el WSDL, no lo pondremosaquí. Pero si os fijáis encontrareis cómola serialización integra nuestra clase “cabe-cera SOAP” en todos los mensajes. Muybonito y elegante. De hecho, es impre-sionante ver cómo nuestra única misiónen el desarrollo ha sido establecer el for-mato de los datos (clase CredencialesSOAP)y qué servicio va a disponer de ella, emple-ando una sencilla directiva para procedera usar el objeto; ya que se nos garantiza suinstancia a través del propio SOAP delservicio (ver figura 4).

El último paso es ver cómo queda-ría la implementación del cliente.Aprovechando el mismo ejemplo ante-rior, en este caso la política no sería la deautenticarse con los objetos ICredentialde .NET, sino aprovechar los mecanis-mos que la clase Proxy de nuestro nuevo

dotN

etM

anía

<<

17

dnm.asp.net<<

Imports System.Web.ServicesImports System.Web.Services.Protocols

'Modelo de informacion que extiende las cabeceras SOAPPublic Class CredencialesSOAP

Inherits SoapHeader

Public Login As StringPublic Password As StringPublic Grupo As String

End Class

<System.Web.Services.WebService(Namespace:=_"http://tempuri.org/ServiciosMonetariosEx/WSConversorExtendido")>

Public Class WSConversorExtendidoInherits System.Web.Services.WebService

'Variable miembro serializa extension SOAPPublic Credenciales As CredencialesSOAP

<WebMethod(), SoapHeader("Credenciales")> _Public Function ConvertirEuros(ByVal pesetas As Long) As Double

If (Credenciales.Grupo = "AccesoEuros") ThenReturn pesetas / 166.386

ElseThrow New Exception("Error: Acceso denegado a Paso a Euros")

End IfEnd Function

<WebMethod(), SoapHeader("Credenciales")> _Public Function ConvertirPesetas(ByVal euros As Double) As Long

If (Credenciales.Grupo = "AccesoEuros") ThenReturn Convert.ToInt64(Math.Round(euros * 166.386))

ElseThrow New Exception("Error: Acceso denegado a Paso a Pesetas")

End IfEnd Function

End Class

Fuente 4

figura 4

La flexibilidad del modelo SOAP es tal que podremos adecuarlo a nuestro gusto definiendo cabeceras

personalizadas, a modo de sencillas clases persistentes que se serializarán de modo automático

Page 18: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

servicio nos proporciona a partir del nue-vo esquema WSDL. El modelo del nue-vo formulario quedará ahora, tras agre-gar un campo nuevo en el que pondre-mos el nombre del “grupo de seguridad”,como en las figuras 5.

El código –tras terminar las “refe-rencias Web” oportunas– de los even-tos clic puede verlo en el fuente 6.

Y funcionando. Mirar qué pasa silo hacemos bien o si nos equivocamosen el nombre del grupo oportuno (se

ha especificado un grupo distinto paracada operación de conversión –verfigura 6 y 7–).

ConclusionesHemos podido ver en este artículo

lo sencillo y transparente que es diseñarservicios Web seguros. Bien sea a tra-vés de los servicios que nos ofrecen lospropios sistemas de Microsoft, o bien através de invenciones nuestras; lo queestá claro es que se ha notado la preo-cupación del desarrollo de aplicacionesseguras. Y se demuestra que .NET denuevo está al pie del cañón, ofreciendomultitud de potentes e interesantesalternativas.

Deciros que las cabeceras SOAPno se limitan sólo a la seguridad de losservicios Web, sino a otros diseñosmás generales. Aprovechad esta poten-cia para poder especificar reglas deenrutado, extensión de ficheros aña-didos al mensaje SOAP, informaciónextra del servicio, y un largo etcétera.Ya sabéis en qué mecanismos se basanlos nuevos WSE de Microsoft.

Ya no tenéis excusa para no asegu-rar vuestros servicios. El código fuen-te lo tenéis disponible en la Web de larevista (http://www.dotnetmania.com) oen mi página Web personal (http:www.heviatec.net). Para la pruebade la demo de Cabeceras SOAP, emple-ar para cada botón el grupo“AccesoEuros” o “AccesoPesetas”.Cualquier otra combinación os darála excepción de error de seguridad.Muy chulo, hasta la próxima.

dotN

etM

anía

<<

18

dnm.asp.net<<

Public form1ExtendidoInherits Form

(…)Private Sub btnAEuros_Click( ByVal sender As System.Object, _

ByVal e As System.EventArgs) _Handles btnAEuros.Click

Dim conversor As New localhost.WSConversorExtendidoDim creds As New localhost.CredencialesSOAPcreds.Login = "noseusa"creds.Password = "noseusa"creds.Grupo = txtGrupoSeguridad.Textconversor.CredencialesSOAPValue = credsTry

lbResultado.Text = conversor.ConvertirEuros(Int64.Parse(txtCantidad.Text)) & " €"Catch ex As Exception

MessageBox.Show(ex.Message)End Try

End Sub

Private Sub BtnPesetas_Click( ByVal sender As System.Object,ByVal e As System.EventArgs) _

Handles BtnPesetas.ClickDim conversor As New localhost.WSConversorExtendidoDim creds As New localhost.CredencialesSOAPcreds.Login = "noseusa"creds.Password = "noseusa"creds.Grupo = txtGrupoSeguridad.Textconversor.CredencialesSOAPValue = credsTry

lbResultado.Text=conversor.ConvertirPesetas(Double.Parse(txtCantidad.Text))&" Pts"Catch ex As Exception

MessageBox.Show(ex.Message)End Try

End Sub

Fuente 6

Figura 5

Figura 7

Figura 6

Page 19: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

19

Manipulación de imágenes conADO.NET

Cualquier desarrollador que se haya acercado a la tecnología .NET,en su vertiente deacceso a datos, dominará la arquitectura de ADO.NET cuando se trata de crear unproceso de mantenimiento de datos típico, utilizando los tipos de datos habituales.Pero, ¿qué ocurre cuando entran las imágenes como parte del mantenimiento?, ¿cómoagregamos estos elementos a una gestión de datos? En el este artículo describimos losrecursos que nos ofrece .NET,y las técnicas a nuestra disposición para integrar las imá-genes como parte de los procesos de manipulación de datos.

<<

Cuando nos enfrentamos al desarrollo de un man-tenimiento de datos típico en VB.NET contra un pro-veedor de datos ADO.NET, pongamos como casoSQL Server, todos sabemos, al realizar por ejemplouna inserción en una tabla, el modo de pasar los datostradicionales a las columnas de la nueva fila, enten-diendo como datos tradicionales los correspondien-tes a cadenas, números y fechas.

Sin embargo, la cuestión ya no resulta tan obviacuando entran en juego tipos de datos como las imá-genes, que salen del marco de trabajo de los tipos habi-tuales, por lo que la pregunta a formular sería lasiguiente: ¿cómo integrar una imagen en nuestra ges-tión de datos?

La solución más directa y sencilla pasaría por tenernuestras imágenes en archivos ubicados en una ovarias rutas del servidor, y una tabla en la base dedatos con un campo de tipo carácter, que contuvie-ra la ruta del archivo.

Esta forma de resolver el problema es amplia-mente utilizada y resulta una excelente solución. Noobstante, en este artículo, nos hemos propuesto com-plicarnos un poco la vida, y nuestra pretensión no esguardar una cadena con la ruta del archivo que con-tiene la imagen, sino el contenido de la propia ima-gen en la base de datos, lo que nos llevaría al siguien-te interrogante: ¿cómo grabar una imagen en unabase de datos?

El tipo Image de SQL Server

La pregunta que acabamos de plantear nos llevaa adentrarnos en la información que existe acerca delos tipos de datos en la documentación de SQL Server(sistema gestor de bases de datos que utilizaremos alo largo del artículo), en donde encontramos un ele-mento específicamente diseñado para nuestros pro-pósitos: el tipo Image, que consiste en un tipo de datoscompuesto por información binaria de longitud varia-ble, desde 0 hasta 231-1 (2.147.483.647) bytes.

Llegados al punto actual ya sabemos dónde hemosde depositar el contenido de una imagen en una basede datos SQL Server, pero ahora surge una nuevaincógnita: ¿cómo conseguirlo?

¿Qué es una imagen?Ciñéndonos a la problemática planteada sobre la

manipulación de imágenes dentro de la plataforma.NET Framework, podemos definir una imagencomo una secuencia de datos binarios o un array debytes. Detengámonos especialmente en la definiciónque acabamos de dar: “secuencia de datos binarios”,y su correspondencia con los elementos que la pla-taforma .NET pone a nuestra disposición para sumanejo. Dentro de la jerarquía de tipos de .NET, laclase que nos permite el trabajo con secuencias o flu-jos de datos es Stream, como clase abstracta, y todaslas clases concretas que derivan de ella (FileStream,MemoryStream, etc.). Por lo tanto, si lo que necesita-

Luis Miguel Blanco

dnm.ado.net

Luis Miguel Blancoes redactor de dotNetManía. Es

consultor en Alhambra-Eidos.Haescrito varios libros y decenas de

artículos sobre la plataforma.NET (lalibreriadigital.com)

Manipulando una imagen dentro de un mantenimiento de datos

Page 20: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

20

dnm.ado.net<<

mos es extraer de un archivo gráfico lasecuencia de bytes que contiene, abri-remos el archivo con un objetoFileStream y volcaremos su contenidoen un array de tipo Byte; este array seráen última instancia lo que utilizaremospara grabar la imagen en la base dedatos.

El modo de gestión de losdatos

ADO.NET es una tecnología quepermite el tratamiento de la informa-ción bajo una filosofía conectada o des-conectada de la fuente de datos con laque trabajemos, en función de las cla-ses que empleemos para dichas tareasde mantenimiento.

En este artículo abordaremosambos modos de trabajo, de maneraque el lector pueda tener una idea decuál de los dos esquemas convienemejor a sus necesidades, siendo inclu-so posible desarrollar un sistema quemezcle ambos.

Como ejemplos ilustrativos detodas las operaciones de manteni-miento de datos a realizar con imáge-nes y objetos de ADO.NET, hemosdesarrollado un proyecto que contie-ne todos los casos que iremos expo-niendo a lo largo de este artículo.Dicho proyecto puede encontrarlo enlos materiales de apoyo disponiblespara este artículo en la direcciónwww.dotnetmania.com.

El mencionado proyecto consisteen una aplicación Windows con inter-faz MDI, que contendrá dos formula-rios hijos, uno para los ejemplos conoperaciones en modo conectado, y elotro para los ejemplos con operacio-nes desconectadas. En el código deambos deberemos importar los siguien-tes espacios de nombre: System.Da-ta.SqlClient y System.IO, que nos per-mitirán utilizar los objetos deADO.NET para el proveedor de SQLServer y los diferentes tipos de streamrespectivamente.

El objetivo de la aplicación consis-te en almacenar y gestionar las fotosque tomamos con una cámara digital,y que tenemos repartidas en un nume-roso conjunto de archivos. Para lo quecrearemos una base de datos SQL

Server que llamaremos InfoViajes, yque contendrá una tabla con el nom-bre Fotos y la estructura mostrada enla siguiente tabla.

Una vez que hemos entrado ensituación, comenzaremos con el for-mulario frmModoConectado, que usare-mos para grabar un archivo gráfico enla base de datos, y posteriormente recu-perar una de esas imágenes almacena-das. La siguiente figura muestra unaporción de este formulario.

Insertar imágenes en una basede datos utilizando un objetoCommand

Tras introducir un número comoidentificador de foto en la caja de textodel formulario, pulsaremos su botón“Grabar imagen en BD”, que ejecutaráel código mostrado en el fuente 1.

El proceso que llevamos a cabo alejecutar este código es el siguiente:

tras pasar las oportunas validacionesque comprueban si hemos tecleado uncódigo para la imagen a grabar, abri-mos un control OpenFileDialog quenos facilita la tarea de seleccionar elarchivo gráfico. Una vez elegido éste,lo abriremos haciendo uso de unasecuencia representada mediante unobjeto FileStream, y dimensionaremosun array de bytes con un tamaño iguala la longitud del stream. Seguidamenteleeremos el contenido del stream y lovolcaremos en el array, con lo que yatendremos la información binaria dela imagen en un formato que nos per-mita tratarlo para su inserción en labase de datos.

A continuación, construiremos laconexión, el comando, y la cadena conla sentencia SQL a enviar a la base dedatos. También definiremos tantos

objetos Parameter

como campos a gra-bar; en el caso con-creto de la imagen,observemos que elparámetro lo crea-mos especificandocomo tipo de datoSqlDbType.Image ,correspondiente a laenumeración quenos devuelve lostipos disponiblespara SQL Server; elvalor que pasamos al

parámetro será el array de bytes quecontiene la información binaria de laimagen.

Por último, abrimos la conexión,ejecutamos el comando y cerramos laconexión. Si todo ha funcionadocorrectamente, tendremos la imagengrabada en un registro de la tabla. Paracomprobarlo podemos ejecutar unaconsulta hacia dicha tabla desde elAnalizador de consultas de SQL Server,obteniendo un resultado como el quevemos en la figura 2.

Tabla 1

Campo Tipo

IDFoto int

Nombre varchar(50)

Foto image

figura 1

figura 2

Page 21: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

21

dnm.ado.net<<

Private Sub btnGrabar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnGrabar.ClickDim nIDFoto As IntegerDim oFileStream As FileStreamDim xDlgResult As DialogResultDim aBytImagen() As ByteDim cnConexion As SqlConnectionDim cmdComando As SqlCommandDim parIDFoto As SqlParameterDim parNombre As SqlParameterDim parFoto As SqlParameterDim sSQL As StringDim oFileInfo As FileInfo

‘ validacionesIf Me.txtIDFoto.Text = String.Empty Then

MessageBox.Show(“Introducir identificador de foto”)Return

End If

TrynIDFoto = Integer.Parse(Me.txtIDFoto.Text)

Catch oException As ExceptionMe.txtIDFoto.Text = String.EmptyMessageBox.Show(“El identificador debe ser numérico”)Return

End Try

‘ cuadro de diálogo para seleccionar archivoMe.dlgAbrirArchivo.InitialDirectory = Application.StartupPath & “\ArchivosFotos”xDlgResult = Me.dlgAbrirArchivo.ShowDialog()

If xDlgResult = DialogResult.OK Then‘ abrir el archivo con un objeto streamoFileStream = New FileStream(Me.dlgAbrirArchivo.FileName, FileMode.Open)‘ crear un array byte que tenga el tamaño del archivoaBytImagen = New Byte(oFileStream.Length - 1) {}‘ leer con el stream el contenido del archivo‘ y volcarlo al arrayoFileStream.Read(aBytImagen, 0, oFileStream.Length - 1)oFileStream.Close()

oFileInfo = New FileInfo(Me.dlgAbrirArchivo.FileName)

sSQL = “INSERT INTO Fotos VALUES (@IDFoto, @Nombre, @Foto)”cnConexion = New SqlConnection(“data source=localhost;initial catalog=InfoViajes;uid=sa;pwd=’’;”)cmdComando = New SqlCommandcmdComando.Connection = cnConexioncmdComando.CommandType = CommandType.TextcmdComando.CommandText = sSQL

parIDFoto = New SqlParameter(“@IDFoto”, SqlDbType.Int)parIDFoto.Value = Convert.ToInt32(Me.txtIDFoto.Text)cmdComando.Parameters.Add(parIDFoto)

parNombre = New SqlParameter(“@Nombre”, SqlDbType.VarChar, 50)parNombre.Value = oFileInfo.NamecmdComando.Parameters.Add(parNombre)

‘ para pasar la imagen a la base de datos‘ definimos un parámetro de tipo Image‘ y le pasamos el array byte que contiene‘ la información binaria de la imagenparFoto = New SqlParameter(“@Foto”, SqlDbType.Image)parFoto.Value = aBytImagencmdComando.Parameters.Add(parFoto)

cnConexion.Open()cmdComando.ExecuteNonQuery()cnConexion.Close()

MessageBox.Show(“Imagen grabada en la base de datos”)End If

End Sub

Fuente 1

Page 22: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Obviamente no veremos en el campo Foto la ima-gen tal y como estamos acostumbrados, sino comouna sucesión de datos binarios, pero que son sufi-cientemente indicativos de que el contenido del archi-vo ha sido grabado.

¿Y si utilizamos el proveedor de OLEDB?Aunque este artículo está orientado hacia uso

del proveedor de datos para SQL Server, si el lec-tor se encuentra ante la necesidad de gestionar imá-genes residentes en un origen de datos para el quedeba de usar el proveedor de OLEDB, la mecáni-ca a seguir sería la misma que acabamos de expli-car, utilizando como es natural, los objetos deADO.NET específicos para este proveedor dedatos: OleDbConnection, OleDbCommand, OleDbPara-meter, etc. Veamos en el fuente 2 una adaptacióndel ejemplo anterior pero usando el proveedor deOLEDB.

Recuperar imágenes desde una base dedatos mediante los objetos Command yDataReader

Una vez que hemos grabado varias imágenes enla base de datos, vamos a efectuar la operación inver-sa, por lo que tras introducir un número identifica-

dotN

etM

anía

<<

22

dnm.ado.net<<

'....'apertura archivo con FileStream y volcado a array byte'....sSQL = _"INSERT INTO Fotos VALUES (@IDFoto, @Nombre, @Foto)"

cnConexion = New OleDbConnection(_"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=” &_”C:\Pruebas\InfoViajes.mdb;Password=;")

cmdComando = New OleDbCommandcmdComando.Connection = cnConexioncmdComando.CommandType = CommandType.TextcmdComando.CommandText = sSQL

parIDFoto = New OleDbParameter("@IDFoto", _OleDbType.Integer)

parIDFoto.Value = 5cmdComando.Parameters.Add(parIDFoto)

parNombre = New OleDbParameter("@Nombre", _OleDbType.VarChar, 50)

parNombre.Value = "karnak1.jpg"cmdComando.Parameters.Add(parNombre)

parFoto = New OleDbParameter("@Foto", _OleDbType.LongVarBinary)

parFoto.Value = aBytImagencmdComando.Parameters.Add(parFoto)

cnConexion.Open()cmdComando.ExecuteNonQuery()cnConexion.Close()

Fuente 2

Private Sub btnRecuperar_Click(ByVal sender As System.Object, _ByVal e As System.EventArgs) Handles btnRecuperar.Click

Dim nIDFoto As IntegerDim xDlgResult As DialogResultDim sSQL As StringDim cnConexion As SqlConnectionDim cmdComando As SqlCommandDim drFotos As SqlDataReaderDim sNombreFoto As StringDim aBytImagen() As ByteDim oFileStream As FileStreamDim oMemoryStream As MemoryStreamDim bmpImagen As Bitmap

‘ validacionesIf Me.txtIDFoto.Text = String.Empty Then

MessageBox.Show(“Introducir identificador de foto”)Return

End If

TrynIDFoto = Integer.Parse(Me.txtIDFoto.Text)

Catch oException As ExceptionMe.txtIDFoto.Text = String.EmptyMessageBox.Show(“El identificador debe ser numérico”)Return

End Try

‘ crear sentencia, conexión y comando para obtener la ‘ imagen de la base de datossSQL = “SELECT Nombre, Foto FROM Fotos WHERE IDFoto = “ & _

Me.txtIDFoto.TextcnConexion = New SqlConnection(_

“data source=localhost;initial catalog=InfoViajes;uid=sa;pwd=’’;”)cmdComando = New SqlCommandcmdComando.Connection = cnConexioncmdComando.CommandType = CommandType.TextcmdComando.CommandText = sSQL

cnConexion.Open()drFotos = cmdComando.ExecuteReader(CommandBehavior.SingleRow)If drFotos.Read() Then

sNombreFoto = drFotos(“Nombre”)‘ recuperar datos binarios de la fotoaBytImagen = drFotos(“Foto”)

End If

drFotos.Close()cnConexion.Close()If IsNothing(sNombreFoto) Then

MessageBox.Show(“No hay foto con ese identificador”)Return

End If

‘ abrir cuadro de diálogo para grabar la foto en un archivoMe.dlgGrabarArchivo.InitialDirectory = Application.StartupPath & _

“\FotosRecuperadasBD\”Me.dlgGrabarArchivo.FileName = sNombreFotoxDlgResult = Me.dlgGrabarArchivo.ShowDialog()If xDlgResult = DialogResult.OK Then

‘ crear un objeto stream de tipo archivo y escribir en él‘ el array byte que contiene los datos binarios de la imagenoFileStream = New FileStream(Me.dlgGrabarArchivo.FileName, _

FileMode.CreateNew, FileAccess.Write)oFileStream.Write(aBytImagen, 0, aBytImagen.Length)oFileStream.Close()

End If

‘ crear un objeto stream en memoria conteniendo los datos ‘ de la imagen, crear un bitmap con el stream y‘ visualizar la imagen en un control PictureBoxoMemoryStream = New MemoryStream(aBytImagen)bmpImagen = New Bitmap(oMemoryStream)Me.picFoto.Image = bmpImagen

End Sub

Fuente 3

Page 23: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dor de foto en la caja de texto del formulario, pulsa-remos su botón “Recuperar imagen de BD”, que eje-cutará el código fuente 3.

En esta ocasión, el proceso ejecutado consiste encrear una conexión y comando, cuya sentencia SQLcontenga el identificador de fila a recuperar, que habre-mos introducido en el formulario. Observe el lectorque al crear el comando, lo configuramos utilizandola enumeración CommandBehavior para optimizar su eje-cución, de modo que devuelva un DataReader com-puesto por una única fila.

Una vez obtenido el DataReader, su campo Fotocontendrá una serie de bytes que representan los datosbinarios de la imagen, y que volcaremos en un array,también de tipo byte.

A partir de aquí podemos tratar la imagen comonecesitemos; en este ejemplo realizamos dos opera-ciones: en primer lugar pasamos el array a un obje-to FileStream, creando de esta manera un archivográfico, ayudándonos de un cuadro de diálogoSaveFileDialog; en segundo lugar creamos un obje-to MemoryStream con el array, y a partir del stream,creamos un objeto Bitmap, que asignamos al controlPictureBox del formulario para visualizar la imagen;si no necesitamos transferir la imagen a un archivo,es mucho más efectivo tratarla en memoria con elstream disponible a tal efecto. La siguiente figuramuestra este formulario en ejecución.

Llegados a este punto, podemos dar por conclui-da la fase de gestión de imágenes en ADO.NET des-de un enfoque conectado a la fuente de datos; es horapues de abordar una técnica diferente: el modo des-conectado.

Manipulando imágenes mediante unDataSet

DataSet representa el objeto central sobre el cualse sustenta la arquitectura de gestión de datos desco-nectados en ADO.NET. La forma de tratar las imá-genes es igual que con los objetos Command y DataReader,salvando claro está, las diferencias entre estos tipos de

objeto en función de su natural operativa (conectadao desconectada).

El ejemplo con DataSet que acompañamos a con-tinuación, además de las operaciones de edición deimágenes, contiene la capacidad de navegación por lasfilas de la tabla, constituyendo un factor adicional quele diferencia del anterior ejemplo basado en coman-dos; el resultado conseguido consiste en un visualiza-dor de imágenes, que aunque sencillo, cumple correc-tamente su misión.

El formulario de ejemplo encargado de tratar conel DataSet es frmDesconectado, que podemos ver en lafigura 4.

En este artículo asumimos que el lector conoce lamecánica básica para crear y llenar un DataSet condatos, por lo que obviaremos aquellas líneas de códi-go pertenecientes a este formulario encargadas de estatarea y de la navegación de registros, centrándonosexclusivamente en los procesos que competen al tra-tamiento de imágenes con este objeto. Debemos acla-rar también, que para facilitar la programación de lasoperaciones en el formulario, algunos elementos talescomo el DataSet, las variables de control de la posi-

dotN

etM

anía

<<

23

dnm.ado.net<<

figura 3

figura 4

Para poder grabar una imagen a un campo de la base de datos,

debemos pasar primeramente dicha imagen a un array de tipo byte ][

Al igual que para el resto de tipos de datos,podemos abordar el mantenimiento de

imágenes con ADO.NET tanto desde unafilosofía conectada como desconectada

del origen físico de los datos. ][

Page 24: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

ción de fila, filas totales, etc., han sido declarados conámbito a nivel de la clase.

Tras poblar el DataSet con el contenido de la tablaFotos en el evento Load del formulario, llamaremos almétodo CargarDatos, que toma la fila en la que el DataSetse encuentra posicionado, y la muestra en los controlesdel modo que vemos en el código fuente 4.

Como acabamos de comprobar, la operación rea-lizada para obtener la imagen es la misma que paraun DataReader: pasamos el contenido del campo dela tabla a un array de tipo byte, y utilizamos éste paracrear un stream en memoria; finalmente, creamos unbitmap con el stream, y asignamos la imagen a un con-trol PictureBox. A partir de aquí, al pulsar los boto-nes de navegación, se actualizará el número de filade la tabla del DataSet a mostrar, volviendo a llamara este mismo método para visualizar la imagen, comovemos en la siguiente figura:

En lo que respecta a la grabación de un archivo grá-fico empleando este DataSet, pulsaremos el botón“Nuevo” para habilitar los controles correspondientes

del formulario. Después de teclear el número identifi-cador y la ruta del archivo, pulsaremos el botón“Grabar”, que ejecutará el siguiente código fuente:

La manera de grabar el archivo gráfico sobre la basede datos es, en esencia, la misma que en el ejemplo conobjetos conectados, ya que abrimos el archivo con unFileStream, y volcamos éste a un array de bytes; a con-tinuación creamos un nuevo objeto DataRow y asigna-mos los valores para sus campos, añadiendo este obje-to a la colección de filas de la tabla del DataSet.Finalmente actualizaremos la base de datos física con elDataSet y rellenaremos este último de nuevo, para queel orden de filas sea el correcto durante la navegaciónde registros por el formulario.

Y llegamos al finalEn efecto estimado lector, por mucho que nos

pese toda narración tiene su fin, y nuestro artículono iba a ser menos, esperamos que el tema tratadoen esta ocasión le sea de utilidad si se encuentra antela tesitura de crear un mantenimiento de datos enel que intervengan imágenes.

dotN

etM

anía

<<

24

dnm.ado.net<<

figura 5

Private Sub btnGrabar_Click(ByVal sender As System.Object, ByVal e AsSystem.EventArgs) Handles btnGrabar.Click

Dim oFileStream As FileStreamDim aBytImagen() As ByteDim drFila As DataRow

‘ abrir el archivo con un stream y volcar en un arrayoFileStream = New FileStream(Me.txtArchivo.Text, FileMode.Open)aBytImagen = New Byte(oFileStream.Length - 1) {}oFileStream.Read(aBytImagen, 0, oFileStream.Length - 1)oFileStream.Close()

‘ crear un objeto DataRow, asignar valores a sus campos‘ y añadirlo al datasetdrFila = dsInfoViajes.Tables(“Fotos”).NewRow()drFila(“IDFoto”) = Integer.Parse(Me.txtIDFoto.Text)drFila(“Nombre”) = Path.GetFileName(Me.txtArchivo.Text)drFila(“Foto”) = aBytImagendsInfoViajes.Tables(“Fotos”).Rows.Add(drFila)

‘ actualizar el dataset en la base de datos‘ y volverlo a llenar para que el orden de las ‘ filas sea el adecuadocnConexion.Open()daAdaptador.Update(dsInfoViajes, “Fotos”)dsInfoViajes.Clear()daAdaptador.Fill(dsInfoViajes, “Fotos”)cnConexion.Close()

‘ actualizar las variables de control del número de filasnFilasTotales = Me.dsInfoViajes.Tables(“Fotos”).Rows.Count - 1nFilaActual = nFilasTotales

Me.ControlesNavegar()Me.CargarDatos()

End Sub

Fuente 5

Private Sub CargarDatos()Dim drFila As DataRowDim aBytImagen() As ByteDim bmpImagen As BitmapDim oMemoryStream As MemoryStream

‘ obtener el objeto DataRow de la fila actual,‘ y recuperar los valores de sus camposdrFila = Me.dsInfoViajes.Tables(_

“Fotos”).Rows(nFilaActual)Me.txtIDFoto.Text = CType(drFila(“IDFoto”), String)Me.txtNombre.Text = CType(drFila(“Nombre”), String)‘ el campo de imagen consiste en información ‘ binaria (bytes), volcarlo a un array de tipo byteaBytImagen = CType(drFila(“Foto”), Byte())

‘ crear un objeto stream en memoria a partir ‘ del array byteoMemoryStream = New MemoryStream(aBytImagen)‘ crear un objeto bitmap a partir del streambmpImagen = New Bitmap(oMemoryStream)‘ pasar el objeto bitmap al control PictureBox ‘ del formularioMe.picFoto.Image = bmpImagenoMemoryStream.Close()

End Sub

Fuente 4

Page 25: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

25

Sistemas distribuidos en .NET con Remoting (y III)

Último artículo sobre Sistemas distribuidos en .NET con Remoting. Una vez vistocómo configurar las opciones de los objetos, los canales que usaremos y la ubicaciónde éstos mediante RemotingConfiguration, veremos cómo configurar .NET Remotingmediante archivos.Finalmente veremos cómo utilizar un servicio o IIS como host enlugar de una aplicación de consola como hemos venido haciendo hasta ahora.

Hasta ahora hemos estado configurando las opcio-nes de comportamiento de nuestros objetos, los cana-les que vamos a usar y la ubicación de los objetosremotos mediante la llamada en el código a funcio-nes de la clase RemotingConfiguration.

Este enfoque nos obliga a cambiar el código y recom-pilar siempre que cambiemos alguno de estos paráme-tros, lo que resta flexibilidad a la solución.

.NET Remoting permite la configuración median-te archivos, lo que nos permite una total flexibilidad ala hora de desplegar nuestra aplicación.

Los archivos de configuración de .NET Remotingtienen formato XML.

Podemos usar un archivo de configuración parael servidor (host) y otro archivo de configuración parael cliente.

Como todos los archivos de configuración de.NET, los archivos de configuración de .NETRemoting comienzan con la etiqueta <configura-tion>. A continuación se muestran los elementosbásicos que pueden aparecer en un archivo de con-figuración:

<configuration><system.runtime.remoting>

<application><lifetime /><chanels /><service /><client />

<application /><system.runtime.remoting/>

<configuration />

<lifetime>:Configurando el tiempo de vida

Usaremos la etiqueta <lifetime> para configurarlas propiedades por defecto de tiempo de vida denuestro objeto. Para modificar estas propiedades usa-remos los atributos de la etiqueta <lifetime> que des-cribimos a continuación:

Todos los atributos de la etiqueta <lifetime>son opcionales. Para expresar las unidades de tiem-po usaremos, “D” para días, “H” para horas, “M”para minutos, “S” para segundos y “MS” para mili-segundos.

Rodrigo Corral

dnm.plataforma.net

Rodrigo Corralcolabora habitualmente con

dotNetManía. Es Microsoft MVPy analista de Sisteplant, empresa

líder en el sector de lasaplicaciones de gestión industrial

<< Configurar .NET Remoting mediante archivos

Tabla 1

ATRIBUTO DESCRIPCIÓN

LeaseTimeIndica el tiempo de vida pordefecto de nuestro objeto. Elvalor por defecto es 5 minutos.

sponsorshipTimeout

Es el tiempo que tiene un spon-sor para responder antes de quesea descartado. El valor pordefecto es 2 minutos.

RenewOnCallTime

Es el tiempo que se añade cadavez que un método del objeto esllamado. El valor por defecto es2 minutos.

leaseManagerPoolTime

Es el intervalo de tiempo quetranscurrirá entre comproba-ciones del tiempo de vida delobjeto. El valor por defecto es10 segundos.

Page 26: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Ejemplo de la configuración deobjetos con un tiempo de vida exage-rado:

<lifetimeleaseTime = “100D”sponsorshipTimeout = “1D”renewOnCallTime = “1D”

/>

<channels>:Configurando los canalesde comunicación

La etiqueta <channels> contrendráinformación sobre uno o más canales;sólo sirve como contenedor de etique-tas <channel> y no tiene atributos aso-ciados a ella.

La etiqueta <channel> nos permiteespecificar las características del canal,como el puerto de escucha y el tipo decanal. En el cliente no es necesario espe-cificar los canales si usamos los están-dares (HTTP o TCP), porque estoscanales son registrados por defecto porel framework. En el servidor debemosespecificar al menos un puerto en el queescuchará el canal.

En la tabla 2 aparece una descrip-ción de los atributos que pueden acom-pañar a la etiquete <channel>.

Dentro de cada etiqueta <channel>podemos especificar el formateador quedeseamos utilizar. A continuación semuestra un ejemplo de un canal HTTPusando el formateador binario:

<channels><channel ref=”http” port=1234>

<serverProviders><formatter ref=”binary” />

<serverProviders/><channel/>

<channels/>

En la parte cliente será necesarioespecificar:

<channels><channel ref=”http” port=1234>

<clientProviders><formatter ref=”binary” />

<clientProviders/><channel/>

<channels/>

<service>: Configurando el com-portamiento de los objetos

El contenido de la etiqueta <service>permite registrar los objetos que nuestro

host va a exponer, así como especificar elcomportamiento de estos objetos. Laestructura de esta entrada es:

<service><wellknown/><activated/>

<service/>

Usaremos la etiqueta <wellknown> enel archivo de configuración de nuestroservidor cuando queramos configurarnuestro objeto como SAO. La etiqueta<wellknown> es equivalente a la llamada

RemotingConfiguration.RegisterWellKno

wnServiceType().En la tabla 3 describimos los atri-

butos que se pueden aplicar a la etique-ta <wellknown>.

A continuación se muestra un ejem-plo de cómo configurar un objeto:

<service><wellknown

mode=”Singleton”type=“namespace.classname,assembly”objectUri=”NuestraUri” />

<service/>

dotN

etM

anía

<<

26

dnm.plataforma.net<<

Tabla 2

ATRIBUTO DESCRIPCIÓN

RefReferencia a un canal predefinido (“tcp” o “http”)o a un canal de usuario definido en un archivo deconfiguración.

DisplayNameNombre con el que se mostrará el canal en laherramienta de configuración de .NETFramework.

TypeEste atributo es obligatorio. Contiene el tipo exac-to (namespace, nombre de clase, asemmbly) quecorresponde a la implementación del canal.

Port

Es el puerto que se usará para escuchar en la par-te servidora. Si queremos permitir que nuestrosclientes puedan recibir callbacks debemos especi-ficar como puerto el 0 en la parte cliente.

NameNombre del canal; por defecto es “http”, cuandoregistramos varios canales este nombre tiene queser único o “”.

PriorityEs un valor numérico entero. Cuanto mayor sea,mayores posibilidades hay de que sea éste, el canalusado para la comunicación.

clientConnectionLimitNúmero de conexiones simultáneas que se pue-den abrir con un determinado servidor. Pordefecto es 2.

ProxyName Nombre del servidor proxy.

ProxyPort Puertos del servidor proxy.

UseIPAddressEspecifica que se usará la dirección IP en lugardel nombre del host. Puede ser “true” o “false”.El valor por defecto es “true”.

BindToDirección IP por la que escuchará el servidor; seusa en equipo con más de una red.

MachineNameNombre del equipo host. Si se especifica se igno-ra el valor de useIPAdrress.

rejectRemoteRequestsSi se establece a “true”, el canal sólo responderáa peticiones desde la máquina local. Sólo se apli-ca a canales TCP.

Page 27: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Usaremos la etiqueta <activated> cuando quera-mos configurar nuestro objeto como CAO. Como enel caso de los objetos CAO, la URI del objeto estádeterminada por el nombre de aplicación. El únicoatributo que tenemos que especificar es el tipo delobjeto remoto que queremos publicar.

A continuación se muestra un ejemplo de cómoconfigurar un objeto CAO:

<service><activated

type=“namespace.classname,assembly” /><service/>

<client>:Configurando el cliente

La etiqueta <client> es el equivalente a la etique-ta <service> en el lado cliente.

La estructura de esta entrada es:

<client><wellknown/><activated/>

<client/>

Cuando usamos objetos CAO, debemos especi-ficar en la etiqueta <client> la ubicación (URL) delservidor, que será común para todas las entradas<activated>.

A continuación describimos los atributos de la eti-queta <client> (tabla 5):

La etiqueta <wellknown> se usa para registrar losobjetos SAO en el cliente y así poder usar el operadornew para instanciar objetos remotos. Los atributos dela etiqueta <wellknown> son equivalentes a los pará-metros de la función Activator.GetObject().

A continuación describimos los atributos que sepueden aplicar a la etiqueta <wellknown> (tabla 6):

A continuación se muestra un ejemplo de cómoconfigurar un objeto SAO para que podamos utilizarel operador new:

<client><wellknown

url=”tcp://hosname:1234/object.tcp”type=“namespace.classname,assembly” />

<client/>

La etiqueta <activated> es el equivalente en elcliente a la etiqueta <activated> en la parte servido-ra. Se utiliza para registrar objetos CAO. Como la rutaal servidor ya se ha especificado en el atributo url dela etiqueta <client>, el único atributo a especificar esel tipo del objeto remoto. Los datos de esta etiquetanos van a permitir usar el operador new para instan-ciar objetos CAO (tabla 7).

dotN

etM

anía

<<

27

dnm.plataforma.net<<

Tabla 3

ATRIBUTO DESCRIPCIÓN

typeInformación sobre la clase que queremospublicar como remota en la forma “names-pace.classname,assembly”

modeIndica el modo de funcionamiento del obje-to. Puede ser “ingleton” o “SingleCall”

objectUri

Especifica el ubicación del objeto. Cuandoel objeto se aloja en IIS el uri debe teminaren .soap o .rem para que sea correctamenteprocesado.

displayName

Atributo opcional que especifica el nombrecon el que aparecerá el objeto en las herra-mientas de configuración del .NETFramework

Tabla 4

ATRIBUTO DESCRIPCIÓN

typeInformación sobre la clase que queremospublicar como remota en la forma “names-pace.classname,assembly”

Tabla 5

ATRIBUTO DESCRIPCIÓN

urlLa url del servidor, es obligatoria si usamosobjetos CAO

displayName

Atributo opcional que especifica el nombrecon el que aparecerá el objeto en las herra-mientas de configuración del .NETFramework

Tabla 6

ATRIBUTO DESCRIPCIÓN

url La URL completa al objeto remoto

typeInformación sobre la clase que queremos uti-lizar como remota en la forma "namespa-ce.classname,assembly"

displayName

Atributo opcional que especifica el nombrecon el que aparecerá el objeto en las herra-mientas de configuración del .NETFramework

Tabla 7

ATRIBUTO DESCRIPCIÓN

typeInformación sobre la clase que queremos uti-lizar como remota en la forma “namespa-ce.classname,assembly”

Page 28: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

A continuación se muestra un ejem-plo de cómo configurar un objeto CAOpara poder usar el operador new:

<client><activatedtype=“namespace.classname,assembly” />

<client/>

Cargar la configuración desde elarchivo

Una vez escritos los archivos de con-figuración, tanto del cliente como del ser-vidor, será necesario cargarlos. Esto seconsigue con una simple llamada a la fun-ción RemotingConfiguration.Configure()que toma como parámetro la ruta delarchivo de configuración (fuente 1).

Ejemplo: RemotingConfigSample1

Utilizar un servicio como hostde nuestros objetos remotos

Hasta ahora hemos utilizado aplica-ciones de consola como host de nues-tros servicios; esto no es ningún pro-blema, e incluso es el enfoque adecua-do para depurar la aplicación, pero tie-ne algunas limitaciones:

• Hemos de arrancar “a mano” laaplicación que expone nuestrosobjetos.

• La aplicación aparece en el escri-torio.

• Cualquiera puede cerrar la apli-cación.

• Cualquiera puede arrancar la apli-cación.

• Para que la aplicación funcioneun usuario debe iniciar unasesión.

• Los objetos remotos corren en elcontexto de seguridad del usuarioque ha iniciado sesión.

Todos estos problemas se pueden evi-tar utilizando un servicio como host.Ahora que sabemos utilizar archivos de

configuración, alojar nuestros objetos enun servicio será algo tan simple como pue-de verse en el fuente 2.

El archivo de configuración con-tiene las definiciones de los objetosque vamos a exponer desde el servicio(fuente 3).

Un mismo servicio nos servirásiempre que queramos exponer obje-

tos remotos con sólo cambiar el archi-vo de configuración.

Ejemplo: ServiceHostSample1

Utilizar IIS como host denuestros objetos remotos

Desplegar nuestros objetos con IIScomo host es realmente sencillo. Lospasos a seguir son:

1) Crear un nuevo directorio virtualen IIS.

2) Copiar el assembly del objeto en elsubdirectorio BIN del directoriovirtual.

3) Poner la configuración de losobjetos en el archivo web.configen el directorio virtual raíz denuestra aplicación.

Si elegimos usar IIS como hostdebemos conocer algunas cosas:

• En el archivo web.config no sepuede usar la opción <debug>.

• Sólo podemos utilizar el canalHTTP.

• El protocolo siempre seráSOAP.

Una de las ventajas es que podemos usar laautenticación IIS y el protocolo SSL.

dotN

etM

anía

<<

28

dnm.plataforma.net<<

private void frmMain_Load(object sender, System.EventArgs e){

RemotingConfiguration.Configure(“RCSClient.exe.config”);

m_RCSObj = new RCSObject();m_RCSObj2 = new RCSObject2();//Aseguramos que sea un objeto remoto

System.Diagnostics.Debug.Assert(RemotingServices.IsTransparentProxy(m_RCSObj));}

Fuente 1

/// <summary>/// Cuando iniciamos el servicio, cargamos la configuración de los objetos remotos./// </summary>protected override void OnStart(string[] args){

RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);

}

<configuration><system.runtime.remoting><application>

<lifetime leaseTime=”1M” sponsorshipTimeout=”1M” renewOnCallTime=”1M” /><channels>

<channel ref=”http” port=”1234” /><channel ref=”tcp” port=”1235” />

</channels><service>

<wellknown mode=”Singleton” type=”RCSObjects.RCSObject, RCSObjects”objectUri=”RCSObject.rem” />

</service></application></system.runtime.remoting>

</configuration>

Fuente 2

Fuente 3

1 Los ejemplos pueden descargarse del material de apoyo de este artículo en http://www.dotnetmania.com/Articulos/014

Page 29: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

29

Interoperabilidad no administrada y migración (y III)

En esta última parte describiremos cómo llamar a funciones externas con un ejemploa una API de Windows.También describiremos la utilización de TypeLibConverter, en elproceso de exportación e importación de la biblioteca de tipos, clave para llevar acabola interoperabilidad COM.

Hasta ahora hemos visto un tipo de interope-rabilidad concreto: entre componentes COM y.NET, lo que es conocido como COM Interop. Acontinuación veremos la interoperabilidad conmétodos de librerías de vínculos dinámicos DLL.En versiones de Visual Basic 6.0 hacíamos uso deeste tipo de programación, por ejemplo, al llamara ciertas APIs de Windows, incluso Visual Basicvenía con un importador de APIs las cuales declarábamos y utilizábamos en nuestros proyec-tos. Con .NET, muchas funciones que sólo encon-trábamos en las APIs de Windows están disponi-bles sin necesidad de hacer llamadas externas, comopor ejemplo la manipulación de procesos enSystem.Threading.

Para las funciones que no se encuentran en BCL,.NET ofrece un servicio llamado invocación de pla-taforma que encontraremos a menudo comoP/Invoke. Dicho servicio se basa en los metadatospara el cálculo de referencias estándar y llamar adichas funciones.

P/Invoke localiza el archivo DLL que nosotros lehemos indicado desde código. Como veremos másadelante no es necesario indicarle la ubicación abso-

luta. Cuando localiza el fichero DLL lo carga enmemoria e inserta sus parámetros en la pila reali-zando los cálculos de referencia necesarios y es la fun-ción no administrada la que se ejecuta.

Crearemos un ejemplo y podremos ver cómoimplementar una llamada a una función externa des-de código .NET. Para el ejemplo utilizaremos unallamada a la función RasEnumConnections del archi-vo RASAPI32.DLL. Dicha función devolverá todas lasconexiones RAS (Remote Access Service) abiertas.Existen cantidad de funciones en KERNEL32.DLL,USER32.DLL o GDI32.DLL más fáciles de implementar,pero con ésta veremos un ejemplo algo más amplio,como el paso por referencia o paso de estructurasy, aunque a priori no es tan simple, será un ejemplomás provechoso.

En primer lugar, deberemos obtener la definiciónde dicha función. En el MSDN Library podemosencontrarla pero con el inconveniente que muestrala definición como prototipo C++. La definición quenos muestra es la siguiente:

En la misma página nos muestra la definiciónde los parámetros, así que podemos saber la utili-dad y observaciones de cada uno. La estructuraRASCONN la obtenemos del citado MSDN Library (verfuente 2).

José Miguel Torres

dnm.plataforma.net

<< Interoperabilidad con funciones no administradas

José Miguel Torrescolabora habitualmente con

dotNetManía. Es técnicosuperior en desarrollo de

aplicaciones informáticas ytrabaja como arquitecto de

software en el departamento detecnologías de la

información de MRW

DWORD RasEnumConnections(LPRASCONN lprasconn,LPDWORD lpcb,LPDWORD lpcConnections

);

Fuente 1

Figura 1. Estructura de directorios y entrada del Registro para implementación privada.

Page 30: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

30

dnm.plataforma.net<<

La obtención e identificación de la función de estecaso es muy simple y sólo debemos echar mano delMSDN Library que ofrece Microsoft. Si utilizáramosuna DLL propia con funciones específicas, deberíamosaplicar la misma metodología según su definición.

En el siguiente paso creamos un proyecto –ennuestro caso un proyecto de consola con Visual C#–que llamaremos RasEnum. A continuación creamos unaclase que contenga la función que hemos visto paraque la utilización en nuestro proyecto, por ejemplo,que se adapte a la programación orientada a objetos,es decir, que para la llamada a la función externaRasEnumConnection la hagamos a través de un métodopúblico de la clase que hemos creado. Podemos cre-ar una clase para cada función así como agrupar demanera lógica varias funciones para evitar la sobre-carga. De todas formas, la utilización de una clase faci-litará la llamada a dicha función.

Para implantar la función, debemos declarar elespacio de nombres System.Runtime.InteropServices.El código referente a la implantación es el siguiente:

[DllImport("RASAPI32",SetLastError=true,

CharSet=CharSet.Auto)]

private static extern int RasEnumConnections(

[In, Out] RASCONN[] lprasconn,

ref int lpcb,

ref int lpcConnections);

En primer lugar indicamos mediante la clase sella-da DllImport que se trata de una función externa, porello le indicamos el fichero DLL, en este caso RASA-PI32.DLL, y a continuación se declaran una serie deatributos opcionales que pueden ser los de la tabla 1.

La accesibilidad no es obligatoria. El hecho de quela haya declarado como privada, es para que sólo sepueda acceder mediante un método público de la cla-se que vamos a crear. Por definición, todas son de acce-

so estático y se deben declarar con la palabra reserva-da extern, ya que se implementa externamente.

Hasta aquí está la parte de .NET que implemen-ta la función, pero nos hemos saltado un paso, ¿cómohemos pasado de la definición de C++ que hemos vis-to, al que se ha implementado en C#?

En la definición vemos tipos de datos tales comoDWORD como retorno LPDWORD, TCHAR, etcétera, en losparámetros de la función. Todos estos tipo son los lla-mados Windows Data Types y son los que se utilizanen Visual C++, y es por ello que deberemos saber cuál

typedef struct _RASCONN {DWORD dwSize;HRASCONN hrasconn;TCHAR szEntryName[RAS_MaxEntryName + 1];

#if (WINVER >= 0x400)TCHAR szDeviceType[ RAS_MaxDeviceType + 1 ];TCHAR szDeviceName[ RAS_MaxDeviceName + 1 ];

#endif#if (WINVER >= 0x401)

TCHAR szPhonebook [ MAX_PATH ];DWORD dwSubEntry;

#endif#if (WINVER >= 0x500)

GUID guidEntry;#endif#if (WINVER >= 0x501)

DWORD dwFlags;LUID luid;

#endif} RASCONN ;

Fuente 2

Tabla 1.Atributo de la clase sellada DllImport

Campo Descripción

BestFitMapping Desactiva las mejores asignaciones.

CallingConvention

Especifica las convenciones de lla-mada utilizadas al pasar argumentosde método. El valor predeterminadoes WinAPI, lo que corresponde a__stdcall en las plataformas de 32bits de Intel.

CharSet

Controla la mutilación de nombres yla forma en que se deben calcular lasreferencias a los argumentos decadena en la función. El valor prede-terminado es CharSet.Ansi.

EntryPointEspecifica el punto de entrada delarchivo DLL que se va a llamar.

ExactSpelling

Controla si un punto de entradadebe modificarse para que se corres-ponda con el juego de caracteres. Elvalor predeterminado cambia segúnel lenguaje de programación.

PreserveSig

Controla si el prototipo administra-do del método debería transformarseen un prototipo no administrado quedevuelva un resultado HRESULT yque pueda tener un argumento adi-cional [out, retval] para el valordevuelto.El valor predeterminado es true (elprototipo no debe transformarse).

SetLastError

Permite al llamador utilizar la fun-ción Marshal.GetLastWin32Errorde la función de API para determi-nar si se produjo un error durante laejecución del método. En VisualBasic el valor predeterminado estrue; en C# y C++, es false.

ThrowOnUnmappableChar

Controla el inicio de una excepciónen un carácter Unicode que no sepuede asignar y que se convierte aun carácter ANSI “?”.

Page 31: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

es su homólogo en C#. En el mismoMSDN Library existen definiciones quenos describen cada tipo y a partir de ahípodemos saber que:

• DWORD: 32 bit unsigned integer,(equivale a uint)

• LPDWORD : Puntero a DWORD (equi-vale a ref uint)

• TCHAR: 16 bit de caracteres UNI-CODE (equivale a string)

De donde también deducimos queLPRASCONN es un puntero a la estructu-ra RASCONN. De ahí que hayamos indi-cado el primer parámetro, el que hacereferencia a la estructura RASCONNcomo In-Out, y los dos siguientes pará-metros como ref uint, aunque tam-bién lo hubiéramos declarado comoref int.

Ahora hace falta implementar laestructura, pero antes debemos imple-mentar cinco constantes. Si nos fija-mos bien en la definición de la estruc-tura, vemos como nos indica que, porejemplo, el miembro szEntryName, quehace referencia al nombre de la cone-xión, tiene una capacidad máxima deRAS_MaxEntryName + 1. Estos valores lospodemos obtener, por ejemplo, delfichero de encabezado Ras.h de VisualC++. Los demás son:

Así que la estructura quedará:

Fíjense que utilizamos [MarshalAs...]para indicarle que se trata de una cadenade tipo string de longitud fija y la longi-tud la pasamos mediante las constantes.A parte, la estructura posee el atributoStructLayoutAttribute para organizar enmemoria la estructura. NormalmenteCLR se encarga de esta operación peroes muy frecuente en las llamadas a fun-ciones externas.

Ya tenemos implementada la fun-ción y ahora crearemos un métodopúblico y estático para que podamos lla-mar a dicha función (fuente 5).

Observemos que después de creare inicializar el array de RASCONN asig-namos al miembro dwSize el tamañode la estructura RASCONN medianteMarshal tal y como indica en la defi-nición de la estructura de la funciónRasEnumConnection del MSDN Library.Normalmente esto indica la versiónde la función que debe utilizar para lamanipulación de la estructura.Posteriormente lo multiplicaremospor el tamaño de la matriz, resultadoel cual pasaremos por parámetro enlpcb por referencia. Tal y como nos

indica en la referencia del MSDNLibrary sobre RasEnumConnections, siéste devuelve 0 todo ha ido bien; encaso contrario, ha habido un error.

Éste ha sido sólo un ejemplo de uti-lización de función externa. A partir deaquí puede probar en utilizar en lugarde los tipos uint que provienen deDWORD, utilizar int, verá que no tieneporqué haber ningún tipo de proble-ma. Utilice int también en lugar deIntPtr, también funcionará. Si, porejemplo, utilizáramos la función exter-na RasHangUp para cerrar una conexión,

dotN

etM

anía

<<

31

dnm.plataforma.net<<

[StructLayout(LayoutKind.Sequential,CharSet=CharSet.Auto)]private struct RASCONN{

public int dwSize;public IntPtr hrasconn;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=RAS_MaxEntryName+1)]public string szEntryName;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=RAS_MaxDeviceType+1)]public string szDeviceType;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=RAS_MaxDeviceName+1)]public string szDeviceName;[MarshalAs(UnmanagedType.ByValTStr,SizeConst=MAX_PATH)]public string szPhonebook;public int dwSubEntry;

}

Fuente 4

private const int MAX_PATH = 260;private const int RAS_MaxDeviceType = 16;private const int RAS_MaxPhoneNumber = 128;private const int RAS_MaxEntryName = 256;private const int RAS_MaxDeviceName = 128;

Fuente 3

public static void representar(){

//comentario no implementado aúnuint ret;uint conns = 0;RASCONN[] rarr = new RASCONN[256];rarr.Initialize();rarr[0].dwSize = (uint) Marshal.SizeOf(typeof(RASCONN));uint lr = rarr[0].dwSize * (uint)rarr.Length;

// comentario no implementado aúnret = RasEnumConnections(rarr, ref lr, ref conns);if (ret != 0) throw new System.ComponentModel.Win32Exception((int) ret);

// comentario no implementado aúnfor(int i=0;i<conns;i++){

// comentario no implementado aúnRASCONN r = rarr[i];

// comentario no implementado aúnif (r.hrasconn == IntPtr.Zero) continue;

// comentario no implementado aún Console.WriteLine(“CONEXIÓN RAS {0}:”, i+1);Console.WriteLine(“\nNombre : {0}”, r.szEntryName);Console.WriteLine(“\nDispositivo : {0}”, r.szDeviceName); Console.WriteLine(“\nTipo dispositivo : {0}”, r.szDeviceType);Console.WriteLine(“\nLibro de llamadas : {0}”, r.szPhonebook);Console.ReadLine();

}}

Fuente 5. Método de llamada a la función externa RasEnumConnections.

Page 32: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

ésta sólo recibe un parámetro hrasconn.Si declaramos en nuestra clase dichafunción con el parámetro de tipoIntPtr, entonces lo que tenemos codi-ficado hasta ahora servirá para finali-zar una conexión, sin embargo, tam-bién podemos utilizarla con el tipo int,cambiándoselo tanto a RasHangUp comoa RasEnumConnection. La diferencia esque IntPtr es un puntero e int es eltipo de datos. Si probáramos constring, por ejemplo, no funcionaría.La utilización de IntPtr o int provocala entrada del cálculo de referencias enun mayor o menor coste.

No existe un patrón determinado.A veces hace falta realizar el cálculo dereferencia interoperativo casi de mane-ra manual si se utilizan estructuras detipo no completas, por ejemplo; asícomo podemos utilizar funciones exter-nas de manera mucho más sencilla.Afortunadamente, hay muchos autoresy soportes Web que tratan este tema y,sin duda, Internet es una muy buenafuente de conocimiento al respecto.

La clase TypeLibConverterOtra alternativa a la hora de inte-

roperar con las bibliotecas de tipo esmediante la utilización de la claseTypeLibConverter. TypeLibConverteres, como dije al principio, una clasesellada del espacio de nombresSystem.Runtime.InteropServices quepermite la conversión de COM a.NET y viceversa, además de tener laposibilidad de obtener el ensambladode interoperabilidad primaria. Esdecir, que TypeLibConverter realiza lasdos operaciones que hemos visto has-ta ahora y es por ello que sea la opciónmás flexible y, aunque algo más com-pleja que las demás, conocer su fun-cionamiento merece la pena.

TypeLibConverter tiene tres méto-dos funcionales para la interoperabi-lidad con código no administrado. Porun lado el método ConvertTypeLibTo-Assembly es el encargado de conver-tir una biblioteca de tipos a un ensam-blado. ConvertAssemblyToTypeLib hacejusto lo contrario, de un ensambladoexporta a un objeto como bibliotecade tipos como hace TlbExp.exe y, porúltimo, GetPrimaryInteropAssembly

obtiene un ensamblado de interopera-bilidad primaria para poder interope-rar.

Si nos fijamos, estos tres métodoshacen justamente las operaciones deinteroperabilidad que hemos visto has-ta ahora de la implementación COMen .NET por medio del ensambladode interoperabilidad primaria ymediante la importación de la biblio-teca de tipos (TlbImp.exe) y la imple-mentación .NET en COM mediantela exportación de la biblioteca de tipos(TlbExp.exe). Pues bien, todas estasoperaciones pueden ser parametriza-das en tiempo de ejecución mediantela utilización de TypeLibConverter.

Para mostrar realmente cómo utili-zarlo, nos centraremos en los métodos

ConvertAssemblyToTypeLib y, especial-mente, ConvertTypeLibToAssembly.

El primero devuelve un objeto(object). Dicho objeto, no es más que unobjeto que implementa una interfaz detipo UCOMITypeLib. Así, pasado un ensam-

blado de tipo Assembly, devolverá un obje-to UCOMITypeLib que contendrá la defini-ción administrada de la biblioteca de tiposlista para ser utilizada desde COM.

En el segundo método, Convert-TypeLibToAssembly, lo que devolveráserá un objeto de tipo AssemblyBuilderque encontramos en el espacio denombres System.Reflection.Emit.Como parámetros, entre otros, pasa-remos un objeto de tipo UCOMITypeLib,el cual hace referencia a la definicióndel componente COM. Veamos estemétodo con más detalle.

A priori, la utilización parece senci-lla, y realmente lo sería si no fuese por-que tenemos que hacer una llamada auna API del sistema operativo. Veamosel código en la figura 2.

Como vemos, no sólo depende deuna llamada al método de conversión;entran otro tipo de llamadas.

En primer lugar la claseConversorNotificador que implemen-ta la interfaz ITypeLibImporterNoti-

dotN

etM

anía

<<

32

dnm.plataforma.net<<

Figura 2.Código de ejemplo de utilización del método ConvertTypeLibToAssembly de la clase TypeLibConverter.

Page 33: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

fySink (línea 9) proporcionará un mecanismo deretorno de llamada sobre el estado de la conversión.Los dos métodos que debe implementar sonReportEvent (línea 11) y ResolveRef (línea 16). Elprimero describe el tipo de llamada según la enu-meración ImporterEventKind y el segundo se ejecu-tará cuando haya necesidad de resolver una segun-da referencia a otra biblioteca de tipos durante elproceso de conversión.

La declaración del método LoadTypeLibEx (línea28,29) de la librería oleaut32.dll, permite cargar unadeterminada biblioteca de tipos que referenciaremosdesde el objeto tlb de tipo UCOMITypeLib (línea 33). Enla llamada al método LoadTypeLibEx pasamos tres pará-metros. En primer lugar la ubicación (path) del fiche-ro que contiene la biblioteca de tipos en cuestión; ensegundo lugar se le pasa el valor del enumeradorRegKind (línea 24) y que estableceremos REGKIND_NONE,puesto que no deseamos registrar; por último pasa-mos la variable tlb por referencia y no inicializada(out) que será dónde se almacenará la definición de labiblioteca de tipos especificada en el primer paráme-tro, en modo de objeto.

Cuando la variable tlb obtenga dicha referencia,utilizaremos, ahora sí, la clase TypeLibConverter paraque el método ConvertTyperLibToAssembly se encar-gue de devolver un objeto de tipo AssemblyBuilder(líneas 40-43). Destacar que al método de conver-sión debemos indicarle el nombre del futuro ensam-blado, la asignación de un nombre seguro y/o unaclave para el nuevo ensamblado que en el ejemplohemos omitido con valores null, la instancia de laclase de tipo ITypeLibImporterNotifySink que hemosdefinido arriba y el último parámetro en el que indi-caremos mediante true o false, el tipo de control delas interfaces de la biblioteca de tipos según la para-metrización de las clases de seguridad para el códi-go no administrado (System.Security.Permission.SecurityPermissionsFlag.UnmanagedCode).

Por último, el objeto AssemblyBuilder ab, median-te el método Save guardará en nuevo ensamblado enun fichero físico (línea 45).

Hemos visto una de las dos sobrecargas del méto-do ConvertTyperLibToAssembly , quizás la más utiliza-da, y solamente uno de los tres métodos que contie-

ne la clase TypeLibConverter. Los tres pasos básicosson la implantación y utilización de LoadTypeLibEx, lautilización del método de conversión y la utilizaciónde un objeto tipo AssemblyBuilder.

Para acabar, quisiera hacer una observación enel método LoadTypeLibEx. El tercer parámetro es deltipo UCOMITypeLib, ya que se trata de un componenteCOM. Si no supiéramos el tipo exacto podemos uti-lizar un cálculo de referencias (marshalling) utili-zándolo como tercer parámetro de la siguientemanera: [MarshalAs (UnmanagedType.Interface)]out Object typeLib;. Pueden ver el resultado enfuente 6. De esta forma parte del cáculo de refe-rencias quedaria en manos del CLR.

Hemos podido ver, de un rápido pincelazo, nosólo las tres posibles maneras de interoperabilidadcon código no administrado, sino también unapequeña extensión en cuanto a cálculo de referen-cias se refiere.

Conclusión

Con esta serie de tres artículos hemos visto lainteroperabilidad desde varias perspectivas y condistintos métodos de uso y aplicación. Sin embar-go, podríamos considerarlo sólo la punta del ice-berg y para llegar a dominar y entender el tema enprofundidad necesitaríamos de más páginas y ejem-plos. Aún y así, espero que hayamos podido consi-derar y entender las nociones básicas para poderplantear dichas técnicas en nuestras aplicacionesaún a sabiendas de la complejidad que realmentetiene su aplicación en un contexto de migración,pero con la facilidad y transparencia que nos brin-da .NET Framework, con el cual estaremos, sinduda, más tranquilos.

dotN

etM

anía

<<

33

dnm.plataforma.net<<

Para las funciones que no se encuentran en BCL, .NET ofrece un servicio llamado invocación de plataforma que encontraremos a menudo

como P/Invoke.Dicho servicio se basa en los metadatos para el cálculo de referencias estándar y llamar a dichas funciones

[DllImport( "oleaut32.dll", CharSet=CharSet.Unicode, PreserveSig=false )]private static extern void LoadTypeLibEx(

String strTypeLibName, RegKind regKind, [ MarshalAs( UnmanagedType.Interface )] out Object typeLib );

}

Fuente 6

Page 34: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

IMPORTES VÁLIDOS HASTA NUEVA OFERTA

DATOS DE FACTURACIÓN

CIF/NIF . . . . . . . . . . . . . . . . . . . . .Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . .Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . .

DATOS DE ENVÍO (sólo si son distintos de los datos de facturación)

CIF/NIF . . . . . . . . . . . . . . . . . . . . .Empresa . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Nombre y apellidos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Dirección . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Población . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .Código Postal . . . . . . . . . . . . . . . . . . . Provincia . . . . . . . . . . . . . . . . . . . . . . . . .Teléfono . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Fax . . . . . . . . . . . . . . . . . . . . . . . . . . . email . . . . . . . . . . . . . . . . . . . . . . . . . . . .

FORMA DE PAGO

❑ Talón nominativo a nombre NETALIA, S.L.❑ Transferencia bancaria a nombre de NETALIA, S.L. a:

La Caixa - Número de cuenta 2100 4315 48 2200014696 (Indique su nombre en la transferencia)

❑ Domiciliación Bancaria (con renovación automática, previo aviso)Indique su número de cuenta:

❑ Tarjeta de crédito❑ VISA ❑ MASTERCARDNúmero de su tarjeta: Fecha de caducidad: / (imprescindible)

Firma y/o sello (imprescindible)

a de de 200

Suscripción a dotNetManía

Usted autoriza a la mecanizaciónde estos datos. El responsable ydestinatario de éstos es Netalia,S.L. Usted tiene derecho a acce-der a sus datos, modificarlos ycancelarlos cuando lo desee. Susdatos no serán cedidos en nin-guna de las formas posibles a ter-ceras partes y no se utilizaránmás que para el buen funciona-miento de su suscripción a larevista dotNetManía y parainformarle de las actividadescomerciales que realice la edito-rial Netalia, S.L. Si no desearecibir información comercial dedotNetManía marque la casillasiguiente ❑

❑ Nº9 ❑ Nº11 ❑ Nº12

Puede enviar los datos al email [email protected],al FAX (34) 91 499 13 64 o al teléfono (34) 91 666 74 77.

También puede enviarlo por correo postal a la siguiente dirección:

Netalia, S.LC/ Robledal, 13528529 - Rivas VaciamadridMadrid (España)

❑ Deseo suscribirme a dotNetManía por un año (11 ejemplares) y beneficiarme de la oferta del 10% de descuento por unimporte total de 60 € para España; o por 120€ para el resto del mundo (envío por avión) (IVA incluido).

❑ Deseo suscribirme a dotNetManía por un año (11 ejemplares) por un importe de 45 € por ser estudiante (IVA incluido).Aporto fotocopia del carné de estudiante o sello del centro académico (IMPRESCINDIBLE). OFERTA VÁLIDA SÓLOPARA ESTUDIANTES RESIDENTES EN ESPAÑA.

❑ Nº13❑ Nº7 ❑ Nº8

Si desea algún otro número indíquelo

❑ Nº10

Page 35: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que
Page 36: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

a Paco Marín escribir este artículo, notenía muy claro cómo enfocarlo; hacer unas libreríasdesde cero para generar PDF suponía eso que losdesarrolladores amamos tanto: reinventar la rueda;mostrar sólo cómo se generan estos documentos apartir de varias librerías gratuitas o de pago, iba dejara los lectores con la misma sensación que cuando vanal taller a dejar el coche y le dicen “ha sido la juntade la trócola… son cien mil”, vamos que uno ponecara de tonto, paga, espera que el coche ande y notener que volver muy a menudo por allí.

Como ambos extremos se quedaban cojos, he opta-do por dar una introducción al formato PDF, con unejemplo en C# del tipo “Hola mundo” que nos hagaperderle el miedo. De esta forma sabremos cómo con-tinuar si nos pica el gusanillo, aprenderemos concep-tos muy interesantes que han introducido los chicosde Adobe y por último realizaremos ejemplos más avan-zados utilizando una librería gratuita y otra de pago(en concreto iSharpText, y Tall Pdf kit).

¡Hola mundo!Para estudiar el formato PDF de forma práctica,

vamos a diseccionar el ejemplo más sencillo y cono-cido por todos nosotros: un documento con una pági-na que contenga el maravilloso texto “¡Hola mun-do!”(ver figura 1).

Cuando hablamos de formato PDF podemos divi-dirlo en dos áreas:

• Estructura del fichero: Cómo se organizan losobjetos en un fichero PDF para su acceso direc-to de forma eficiente.

• Estructura del documento: Cómo se distribuye lajerarquía de objetos para poder almacenar elcontenido y aspecto del documento.

La estructura de un fichero PDF

La estructura de un fichero PDF se divide en cua-tro partes (ver figura 2):

• Cabecera: Está compuesta por una línea. En ellaindicamos que el documento es un PDF y la ver-

PDFCaja transparente

Braulio Díez

Figura 1. Nuestro “Hola mundo”

<< Cuando le propuse

Braulio Díezcolabora habitualmente condotNetManía. Es MCSD en

programación distribuida con Visual C++.

Trabaja como SolutionsDeveloper de Avanade.

Para la mayoría de la gente, el formato PDF es un tipo de documento universalque se puede ver desde cualquier máquina sin perder detalle. ¿Cómo se crea unPDF? Herramientas especiales, conversores…, en definitiva: “cajas negras”. Eneste artículo vamos a convertir dicha caja opaca, en transparente, estudiando suformato y viendo las diversas formas de generarlo; para ello usaremos C#.

Page 37: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

sión del formato con el que se harealizado (por ejemplo: “%PDF-1.2”).

• Cuerpo (Body): Contiene los objetosque conforman los datos del docu-mento (cadenas de texto, streamscon imágenes, diccionarios de pági-nas, etc.).

• Tabla de referencias cruzadas (cross-reference table): Cada elemento del

documento (cadena de texto,imagen, etc.) se encuentra dentrode un objeto; en esta tabla de refe-rencias cruzadas tenemos una lis-ta con la dirección dentro delfichero en la que se encuentracada objeto (de esta forma, paraacceder a una parte del ficheroque nos interese, no es necesario

leer el archivo completo). Verfigura 3.

• Trailer: Nos indica dónde comien-za la tabla de referencias cruzadas(en qué offset del fichero) y tam-bién cuál es el objeto principal des-de el que se debe empezar a leer eldocumento. Ver figura 4.

A primera vista seguro que se nosviene a la cabeza pensar que la estruc-tura del fichero está casi al revés, ¿Nosería lo lógico tener la cabecera, la tablade referencias a los objetos y después elcuerpo del documento con todos losobjetos? La respuesta es no, tener latabla de referencias a los objetos al finalnos permite crear ficheros PDF de unasola pasada, de la siguiente forma:

1. Escribimos los objetos que com-ponen el documento de formasecuencial en el fichero, lo únicoque tenemos que almacenar enmemoria es el par número de objeto/ dirección del objeto (offset del fiche-ro donde se encuentra el objeto).

2. Escribimos en el fichero la listacompuesta por los pares número deobjeto/dirección del objeto almacena-dos en el paso 1 (esto sería la tablade referencias cruzadas).

3. Escribimos el trailer, indicando cuáles el objeto principal y en qué posi-ción (offset) del fichero se encuen-tra el comienzo de la tabla de refe-rencias cruzadas (paso 2).

Así pues, cuando leemos un ficheroPDF, empezamos por el final (cargan-do en memoria cuál es el objeto princi-pal y la tabla de referencias cruzadas), yal resto del documento vamos acce-diendo de forma dinámica (la ventaja esque podemos leer documentos de inclu-so varios gigas sin que nuestra máquinase quede “tostada”).

La estructura de un documento PDF

Ahora que conocemos cuál es el“esqueleto” de un PDF, vamos a ver cuáles su contenido.

Los elementos que forman un PDFpueden ser de distintos tipos:

dotN

etM

anía

<<

37

dnm.plataforma.net

%PDF-1.1CABECERA

(una sola línea)1 0 obj<< /Length 2 0 R >>streamBT/F0 10 Tf30 798 Td10 TL(Hola Mundo !)TjETendstreamendobj2 0 obj49endobj3 0 obj<</Type/Page/Parent 4 0 R/Contents 1 0 R>>endobj4 0 obj<</Type /Pages /Count 1/Kids[3 0 R]/Resources<</ProcSet[/PDF/Text]/Font<</F0 5 0 R>> >>/MediaBox [ 0 0 594 828 ]>>endobj5 0 obj<</Type/Font/Subtype/Type1/BaseFont/Courier/

Encoding/WinAnsiEncoding>>endobj6 0 obj<</Type/Catalog/Pages 4 0 R>>endobj

CUERPOCadenas de texto, imágenes, diccionario de páginas, etc.

Todo encapsulado en objetos

xref0 70000000000 65535 f0000000009 00000 n0000000110 00000 n0000000128 00000 n0000000186 00000 n0000000322 00000 n0000000408 00000 n

TABLA DE REFERENCIAS CRUZADAS

En qué offset del fichero se encuentracada objeto del cuerpo, para acceder a

ellos de forma directa

trailer<</Size 7/Root 6 0 R>>startxref453%%EOF

TRAILERAquí le indicamos cuál es el objeto prin-cipal, es decir. el objeto raíz, y dónde seencuentra la tabla de referencias cruza-

das y su tamaño

Figura 2. Estructura de un fichero PDF

Page 38: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

• Streams de Texto (cadenas de tex-to, definición de fuentes, etc.).

• Streams Binarios (que contengan,por ejemplo, imágenes).

• Diccionarios (nos sirven paraalmacenar, por ejemplo, listas depáginas).

Cada elemento que insertamos enun PDF está contenido en un objetocuyo nombre es numérico y único (asípodemos referenciar de forma única aun elemento).

Vale, ¿pero cómo pegamos todoesto para montar un documento consentido?

Para ello tenemos una jerarquía deobjetos. Vamos a ver los trazos princi-pales de la misma:

• En la cima tenemos el Catálogo/Diccionario del documento, quecontiene las referencias a losobjetos principales (en nuestrocaso sólo tendrá una referenciaal árbol de páginas).

• El árbol de páginas (se llama asíporque podemos crear estilos depáginas y que hereden otras susatributos).

• Las páginas.• El resto de Objetos/Elementos

(cadenas de texto, imágenes, fuen-tes, etc.).

dotN

etM

anía

<<

38

dnm.plataforma.net<<

Cada elemento que insertamos en un PDF está contenido en un objeto cuyo nombre es

numéricoy único (así podemos referenciar de forma única a un elemento)

xref0 70000000000 65535 f 0000000009 00000 n 0000000116 00000 n 0000000134 00000 n 0000000192 00000 n 0000000328 00000 n 0000000414 00000 n

Aquí comienza la tabla de referencias cruzadas. Le decimos que tenemos una subsección,que contiene 7 objetos, desde el 0 al 6 (0: referencia inicial del primer objeto, 7:númerode objetos que referenciamos).

La primera entrada debe ser siempre igual (0 65535 f). Es la primera entrada a una listade objetos borrados (la f significa “free entry”), la n viene de “in use”. Esto, y los cerosque tenemos a la derecha, se usan para el control de versiones/modificaciones de un docu-mento, que es un tópico avanzado; nosotros sólo nos preocuparemos de rellenar esos cam-pos a sus valores por defecto.

Offset del fichero en que se encuentra cada entrada obj (objetos). Podemos tener ficherosde hasta 10 Gigas.

Figura 3. Detalle de la tabla de referencias cruzadas

trailer<</Size 7/Root 6 0 R>>startxref459%%EOF

Offset en bytes desde el principio del fichero hasta la entrada xref (comienzo de la tablade referencias cruzadas).

Marca de final de fichero.

Figura 4. Detalle del trailer del fichero

Aquí le decimos el número de entradas que hemos metido en la tabla de referencias cruzadas(7 en nuestro caso) y qué objeto tiene el diccionario principal (en este caso el objeto 6).

Tres de los factores que han hecho del PDF el formato estándar parapublicar documentos son:

• El formato no es secreto; de hecho los chicos deAdobe nos permiten bajarnos una extensa guía en laque nos explican de forma exhaustiva todos los deta-lles del mismo.

• Es un formato tremendamente disciplinado que here-da del Postscript, en el que cada trozo de informaciónse divide en objetos.

• Adobe proporciona de forma gratuita un estupendovisor para casi cualquier plataforma.

PDF un estándar de facto

<<

Page 39: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Para ver cómo funciona todo esto,vamos a analizar nuestro “Hola mundo”(ver figura 5). Para seguir profundizando,puede bajar de la Web de Adobe la guíadel formato (al final de este artículo se pro-porciona el link a dicha guía).

Cómo generar un PDF con C#sin ayudarnos de librerías

Para terminar de perderle el miedo aeste formato, vamos a generar nuestro“Hola mundo” partiendo de cero. Elejemplo en cuestión consta del ficheroprincipal (una aplicación de consola) y unaclase que gestiona de forma automática la

dotN

etM

anía

<<

39

dnm.plataforma.net<<

%PDF - 1.11 0 obj<< /Length 2 0 R >>streamBT/F0 16 Tf30 798 Td10 TL(Hola Mundo !)TjETendstreamendobj2 0 obj49endobj3 0 obj<</Type/Page/Parent 4 0 R/Contents 1 0 R>>endobj4 0 obj<</Type /Pages /Count 1/Kids[3 0 R]/Resources<</ProcSet[/PDF/Text]/Font<</F0 5 0 R>> >>/MediaBox [ 0 0 594 828 ]>>endobj5 0 obj

<</Type/Font/Subtype/Type1/BaseFont/Courier/Encoding/WinAnsiEncoding>>endobj6 0 obj<</Type/Catalog/Pages 4 0 R>>endobjxref0 70000000000 65535 f 0000000009 00000 n 0000000110 00000 n 0000000128 00000 n 0000000186 00000 n 0000000322 00000 n 0000000408 00000 n trailer<</Size 7/Root 6 0 R>>startxref453%%EOF

Para definir nuestro stream le tenemos que decir la longitud que tendrá; en este caso le deci-mos que la longitud se la especificamos en el objeto 2 (obj 2 0), la R significa “Referencia”.Esto se suele hacer para generar de una pasada el PDF.

Aquí definimos un objeto. La referencia del objeto es el número 1, el 0 que se encuentra ala derecha significa que es la revisión 0 del objeto. Dentro de él vamos a añadir nuestro stre-am de texto “Hola mundo”.

Establecemos la fuente 0 (que definimos más adelante en los recursos), con tamaño 10, ledefinimos la posición en la que escribir el texto (30,798).

El objeto 2 0, almacena el número 49, que es la longitud del stream del objeto 1 0.

BT “Begin of Text” | ET “End of Text”.

Secuencia de caracteres, delimitadas por paréntesis. Si estuvieran delimitadas por <>, seríaun string con caracteres hexadecimales.

Existen múltiples alternativas para generar ficheros PDF de formaautomática.A destacar:

• Drivers de impresora que escriben a PDF traduciendo loscomandos de GDI a formato PDF.Es una solución rápi-da,el problema es que no se tiene mucho control sobreel documento generado.

• Herramientas XSL como FOP de Apache, que ofrecenun pseudolenguaje para generar los documentos PDF, apartir de éste se genera una plantilla XSL que convier-te datos a formato PDF (lo bueno de estas herramien-tas es que permiten aprovechar las plantillas para gene-rar otros múltiples formatos, Excel,MS Word, etc.).

Otras alternativas

<<

Figura 5. Estructura de un documento PDF

Arbol de páginas, aquí le indicamos cuántas páginas vamos a poner, y la lista de objetos quecontienen a esas páginas (en nuestro caso sólo una, la que definimos en el objeto 3 0).También le indicamos que las páginas usan un recurso fuente que hemos creado (el objeto5 0 del documento), y con Media Box le indicamos el tamaño de la página.

La fuente F0 la definimos en el objeto 5 0, y la incluiremos en el objeto 4 0, para su uso en lapágina que hemos creado.

Catálogo principal. Apuntamos al objeto que contiene el arbol de páginas (obj 4 0).

Aquí definimos la primera página, le decimos que herede los atributos del objeto 4 0, y leindicamos que el contenido de la misma lo puede encontrar en el objeto 1 0 (podríamostener un array de objetos).

Page 40: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

40

dnm.plataforma.net<<

static void Main(string[] args){

float pageWidth = 594.0f; // Ponemos estos datos aquí para que seafloat pageDepth = 828.0f; // más fácil cambiarlosfloat pageMargin = 30.0f;float fontSize = 16.0f;float leadSize = 10.0f;float yPos = 0f;string strPDFElement = “”;PDFSimpleWriter pdfSimpleWriter = new PDFSimpleWriter();

pdfSimpleWriter.startNewDocument();

// Escribimos nuestro stream que contiene “Hola mundo”// ( tenemos que especificarle posición, fuente, y texto)// ********************** 1 0 obj **********************// Le decimos que la longitud del stream se la indicamos en el objeto 2 0strPDFElement = “<< /Length 2 0 R >>\n”;strPDFElement +=”stream\n”;

int holaMundoStart = strPDFElement.Length;

strPDFElement += “BT\n/F0 “ + fontSize +” Tf\n”;yPos = pageDepth - pageMargin;strPDFElement += pageMargin + “ “ + yPos +” Td\n”;strPDFElement += leadSize+” TL\n”;

// Añadimos el texto strPDFElement += “(Hola Mundo !)Tj\n” ;strPDFElement += “ET\n”;int holaMundoEnd = strPDFElement.Length;strPDFElement += “endstream\n”;pdfSimpleWriter.WriteObject(strPDFElement); // </1 0 obj>

// ********************** 2 0 obj **********************// Ahora escribimos el objeto 2 0 que contiene la// longitud del stream que hemos escritoint HolaMundoLen = holaMundoEnd - holaMundoStart;

strPDFElement = HolaMundoLen.ToString() + “\n”;pdfSimpleWriter.WriteObject(strPDFElement); // </2 0 obj>// ********************** 3 0 obj **********************// Definimos la página primero, y le decimos que el// contenido está en el objeto 1 0 ( podríamos haber // definido un array de objetos)strPDFElement = “<</Type/Page/Parent 4 0 R/Contents 1 0 R>>\n”;pdfSimpleWriter.WriteObject(strPDFElement); // </3 0 obj>// ********************** 4 0 obj **********************// Aquí definimos el arbol de páginas, en nuestro caso// sólo tenemos una páginastrPDFElement = “<</Type /Pages /Count 1\n”;strPDFElement += “/Kids[\n3 0 R\n]\n”;strPDFElement += “/Resources<</ProcSet[/PDF/Text]/Font<</F0 5 0 R>> >>\n”;strPDFElement += “/MediaBox [ 0 0 “+ pageWidth + “ “ + pageDepth + “ ]\n>>\n”;pdfSimpleWriter.WriteObject(strPDFElement); // </4 0 obj>// ********************** 5 0 obj **********************// Añadimos la fuente que usaremos en la cadena de texto “Hola Mundo”strPDFElement = “<</Type/Font/Subtype/Type1/BaseFont/Courier/Encoding/WinAnsiEncoding>>\n”;pdfSimpleWriter.WriteObject(strPDFElement); // </5 0 obj>// ********************** 6 0 obj **********************// Definimos el catalogo principal ( le decimos en que objeto// está el arbol de páginas).strPDFElement = “<</Type/Catalog/Pages 4 0 R>>\n”;pdfSimpleWriter.WriteRootObject(strPDFElement); // </6 0 obj>

// EndDocument genera la tabla de referencias cruzadas y el trailerpdfSimpleWriter.endDocument();// Escribir el documento a fichero y testearpdfSimpleWriter.WriteToFile(@”Testeo.pdf”);

}

Fuente 1. Generación de PDF sin librerías. Main de la aplicación

Page 41: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

estructura del fichero (cabecera, tabla de referencias cru-zadas y trailer), así sólo tenemos que preocuparnos delcontenido del mismo (los objetos).

En el fuente 1 puede ver el main de la aplicación, laclase que gestiona la estructura del documento está dis-ponible en la web de dotNetManía (PDFSimpleWriter;debido a su extensión no la hemos incluidoen el artículo), ambos ficheros están profu-samente documentados para que sean fáci-les de seguir.

Se podría mejorar el ejemplo creandouna tabla hash que mapeara los identifica-dores de los objetos a nombres “amisto-sos” (por ejemplo cadenaholamundo), paraasí poder referenciarlos de forma fácil des-de otros objetos (por ejemplo, llamar a unstream desde una página). De esta forma sepodrían tener clases auxiliares que crearanlos objetos por nosotros (por ejemplo, unaclase que nos sirviera para generar streamsde texto, etc.).

iTextSharpiTextSharp es una librería open source gratuita con

muy buena fama. A continuación vamos a ver cómo ins-talarla y un pequeño ejemplo que genera un recibo deun banco.

Instalando la librería

Si algo se les suele echar en cara a este tipo de libre-rías es que suelen ser muy enrevesadas de instalar y queno tienen una buena documentación para empezar ausarlas. En este caso, la instalación es un “poquito” tra-bajosa; si seguimos los pasos rápidos la cosa no sale, nos

bajamos sólo la DLL, resulta que necesita otra DLLcon una librería open source que se llama ZipLib, nos labajamos también, creamos un proyecto de ejemplo, con-seguimos que compile la aplicación y cuando vamos aejecutarlo nos pega un cascazo. Buscamos en los foros,y resulta que la librería de ZipLib que nos habíamosbajado no era compatible con la que usan iTextSharp.Solución: nos bajamos el código fuente de iTextSharpy lo recompilamos (gracias a dios cargamos el .SLN, ledamos a “build” y todo sale a la primera).

Espero que ningún aficionado al open source se hayaenfadado por el tironcete de orejas; es sólo que a vecespor unos pequeños detalles, un excelente producto nose acaba usando porque es complicado de instalar.

Generando los PDF

Si en el punto anterior teníamos que dar un peque-ño tirón de orejas, en éste todo lo contrario. Nos pode-mos bajar un tutorial muy completo desde su mismositio web, que nos permite ponernos en productivo enmuy poco tiempo.

Para ver una idea de cómo se usa la librería, hehecho un ejemplo que genera un recibo de un banco.Como se ve en el código, el uso de ésta es bastanteintuitivo (en la figura 6 puede ver una captura del docu-mento, y en fuente 2 el código que lo genera).

TallPDFHemos visto cómo hacer el “Tarzán” y generar un

documento PDF desde cero, también cómo ayudarnosde una librería gratuita y ahorrarnos tiempo. Vamos apor la última opción, una librería de pago que tiene unaforma de generar documentos muy interesante: en unfichero XML definimos una plantilla (si queremos, pode-mos definirlo usando la propia librería), y este compo-nente convierte el XML en un fichero PDF.

Las principales ventajas de esta aproximación, esque permiten tanto generar ficheros desde código, comodirectamente en XML, y lo más importante, podemosconvertir estos XML a plantillas XSL, con lo que pode-

dotN

etM

anía

<<

41

dnm.plataforma.net<<

Figura 6. Nuestro recibo de banco generado con iTextSharp

PDF es un formato vivo,evoluciona con el tiempo.Algunosaspectos más avanzados son:

• Control de versiones: Permite guardar dife-rentes versiones de un documento.

• Encriptación de documentos:Así podemosañadir seguridad al mismo y que sólo pue-da ser leído por usuarios autorizados.

• Streams Comprimidos: No sólo se puedeañadir compresión a las imágenes que seinserten en un PDF sino también a cual-quier trozo de texto o flujo de datos.

• Representaciones gráficas: Este formatoincorpora un potente motor para gene-rar gráficas y representar fórmulasmatemáticas.

Aspectos avanzados del formato

<<

Page 42: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

42

dnm.plataforma.net<<

static void Main(string[] args){// Creamos una instancia iTextSharp.text.Document:Document document = new Document();// Le decimos donde queremos escribirPdfWriter.getInstance(document, new FileStream(@”C:\iTextSample.pdf”, FileMode.Create));// Abrimos el documentodocument.Open();

// Creamos una tabla en la que imprimiremos el reciboTable table = new Table(3, 4);table.setWidths(new int[]{25, 55, 35});table.BorderWidth = 1;table.Padding = 2;table.Spacing = 2;

// Insertamos la imagen con el logo del bancoImage logo = Image.getInstance(@”c:\ejemplo.jpg”);logo.Alignment = Image.TOP | Image.LEFT;logo.Border = 0;logo.scalePercent(60);

//Insertamos la celda con el logoCell cell1 = new Cell(logo);cell1.Colspan = 1;cell1.Rowspan = 1;table.addCell(cell1);

//Cabecera del reciboChunk chunk = new Chunk(“Comunicación operación a cuenta”, FontFactory.getFont(

FontFactory.HELVETICA_BOLD, 18, Font.NORMAL, new Color(0, 0, 0)));Paragraph p1 = new Paragraph(chunk);Cell cell2 = new Cell(chunk);

// El “Colspan” es como el de las tablas HTMLcell2.Colspan = 2;table.addCell(cell2);

// Creamos el detalle del reciboChunk chunkBody1 =

new Chunk(“Pago cuota del prestamo hipotecario correspodiente a el mes de Septiembre del 2004”, FontFactory.getFont(FontFactory.HELVETICA, 10, Font.NORMAL, new Color(0, 0, 0)));

Chunk chunkBody2 = new Chunk(“\n”, FontFactory.getFont(FontFactory.HELVETICA, 10, Font.NORMAL, new Color(0, 0, 0)));

Chunk chunkBody3 = new Chunk(“\n”, FontFactory.getFont(FontFactory.HELVETICA, 10, Font.NORMAL, new Color(0, 0, 0)));

Paragraph pBody = new Paragraph(chunkBody1);pBody.Add(chunkBody2);pBody.Add(chunkBody3);

// y el pie del mismoCell cell3 = new Cell(pBody);cell3.Colspan = 3;table.addCell(cell3);Chunk Footer1 = new Chunk(“Cuota mensual”, FontFactory.getFont(FontFactory.HELVETICA, 10,

Font.BOLD, new Color(0, 0, 0)));Paragraph pFooter1 = new Paragraph(Footer1);

Cell cell4 = new Cell(pFooter1);cell4.Colspan = 2;table.addCell(cell4);

Chunk Footer2 = new Chunk(“500 €”, FontFactory.getFont(FontFactory.HELVETICA, 12, Font.NORMAL, new Color(0, 0, 0)));

Paragraph pFooter2 = new Paragraph(chunkBody1);Cell cell5 = new Cell("500 €");cell5.Colspan = 1;table.addCell(cell5);// Añadimos la tabla al documentodocument.Add(table);

// Cerramos el ficherodocument.Close();

}

Fuente 2. Código que genera el recibo utilizando la librería open source iTextSharp

Page 43: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

mos generalizar y, por ejemplo, podríamos generar todoslos recibos de banco a partir de una sola plantilla.

Instalando la librería

Una librería de pago se supone que no debería tenerningún problema a la hora de instalarla ¿no? Bueno, locierto es que me dio un poco de guerra: el sistema parabajar la versión de prueba no me funcionó a la prime-ra, eso era un sábado a las 17:00, les escribí un correocreyendo que no recibiría respuesta hasta por lo menosel siguiente lunes, y cual fue mi sorpresa cuando a las19:49 recibí la contestación con las versiones de prue-ba para empezar a trabajar.

Generando los PDF

En los fuentes 3 y 4 podemos ver el XML y el códi-go C# que utilizaríamos para generar el mismo ejem-plo del recibo de banco del apartado anterior (figura 6).

Lo que se echa en falta a este componente es unareferencia a las etiquetas XML que se pueden usar paragenerar PDF. Hablé con Frank Rem (fundador de TallComponents) y me comentó que lo iban a tener en cuen-ta, aunque el XML que se genera son las clases del com-ponente serializadas (así pues, si en la ayuda vemos unapropiedad de un objeto que se llama MinHeight sabemosque podemos usar esa etiqueta en el fichero XML).

Para saber más…Espero que este artículo sirva como punto de par-

tida para que pueda adentrarse en el mundo del PDF,y haber convertido este formato en una caja menosmisteriosa y opaca para nosotros, los desarrollado-res. Si quiere seguir investigando este área, en la tablareferencias, tiene unos links interesantes.

dotN

etM

anía

<<

43

dnm.plataforma.net<<

<document xmlns=”http://www.tallcomponents.com/schemas/tallpdf/v1”><section><paragraph type=”table” preferredwidth=”400” forcewidth=”true”>

<row><cell fixed=”true” colspan=”1”><border>

<left /><top />

</border><paragraph type=”image” path=”c:\ejemplo.jpg” compression=”dct” width=”100” />

</cell><cell colspan=”3” fixed=”true”>

<border><left /><right /><top />

</border><paragraph type=”textparagraph”>

<fragment font=”HelveticaBold”>Comunicacion operacion a cuenta</fragment></paragraph>

</cell></row><row MinHeight=”100”>

<cell colspan=”4”><border>

<left /><right /><top />

</border><paragraph type=”textparagraph”>

<fragment>Pago cuota del prestamo hipotecario correspondiente al mes de Septiembre del 2004</fragment>

</paragraph></cell>

</row><row>

<cell colspan=”4”>

Fuente 3. XML con el layout del recibo del banco que queremos generar (sigue...)

Referencias

La guía oficial del formato PDF: http://partners.ado-be.com/asn/tech/pdf/specifications.jsp

La librería iTextSharp gratuita que analizamos en elartículo, la puede encontrar en: http://itextsharp.sour-ceforge.net

Sobre los componentes de pago, la página web deTall components es: http://www.tallcomponents.com

Un buen sitio para desarrolladores: http://www.pla-netpdf.com/developer/index.asp

Varios sitios de .net en los que se pueden encontrarartículos interesantes: http://www.codeproject.com ,http://www.c-sharpcorner.com

Para los "Javeros": http://xml.apache.org/fop/index.html

Page 44: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

44

dnm.plataforma.net<<

<border><left /><right /><bottom />

</border><paragraph type=”textparagraph”></paragraph>

</cell></row><row>

<cell colspan=”3” fixed=”true”><border>

<left /><right /><bottom />

</border><paragraph type=”textparagraph”>

<fragment>Cuota Mensual</fragment></paragraph>

</cell><cell colspan=”1”>

<border><left /><right /><bottom />

</border><paragraph type=”textparagraph”>

<fragment>500 Euros</fragment></paragraph>

</cell></row>

</paragraph></section>

</document>

Fuente 4. Código C# que transforma la plantilla XML en un recibo de banco en formato PDF

(...continuación) Fuente 3. XML con el layout del recibo del banco que queremos generar

static void Main(string[] args){FileStream fs = null;try{// Le decimos donde queremos generar el fichero PDFfs = new FileStream( @”c:\TallSample.pdf”, FileMode.Create );

// Leemos la plantilla XML con el recibo de bancoSystem.IO.StreamReader stream = new System.IO.StreamReader (@”C:\BancoEjemplo.xml”);

XmlTextReader reader = new XmlTextReader (stream); Document document = new Document();document.Read(reader);

// Le decimos que transforme la plantilla XML y la escriba // en el fichero PDF que le hemos indicado antesdocument.Write(fs);

// Cerramos los streams al fichero XML y al PDFreader.Close();stream.Close();}catch(System.Exception ex){System.Console.WriteLine(“***************************************”);System.Console.WriteLine(“ERROR: “ + ex.Message);System.Console.WriteLine(“***************************************”);System.Console.ReadLine();

}finally{fs.Close();

}}

Page 45: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que
Page 46: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

<< saber que una determinada utilidad o apli-cación nos resulta útil o es catalogada como indis-pensable? Sé que es una pregunta muy genérica, pero¿realmente se la ha hecho alguna vez de forma pro-funda? Y es que este mes he querido mostrar una uti-lidad muy especial de nombre MZ-Tools y desarro-llada por Carlos J. Quintero, MVP de Visual Developerdesde el año 2004.

MZ-Tools no es otra cosa que un add-in o com-plemento para Visual Basic, VBA y Visual Studio.NET. De hecho, existen dos versiones de este com-plemento, MZ-Tools 3.0 para Visual Basic 5, VisualBasic 6, VBA y MZ-Tools 4.0 para Visual Studio.NET 2002 y Visual Studio .NET 2003. En este artí-culo nos centraremos únicamente en el complemen-to para Visual Studio .NET, aunque ambas versionescomparten muchas de las funcionalidades que men-cionaré.

Historia de MZ-ToolsMZ-Tools tiene un nombre más que curioso, si

bien “Tools” es una palabra cuyo significado prácti-camente todo el mundo conoce, “MZ” sí que requie-re su explicación. Carlos nos describe claramente ensu página Web que en un primer momento, intentódenominar a su complemento con el nombre de Q-Tools, sin embargo, el dominio para este nombreestaba ocupado, por lo que pensando en otro domi-nio que estuviera disponible, finalmente cambió la“Q” por “MZ”. Lo que es realmente anecdótico entoda esta historia, es el significado de MZ, el cuál vie-ne de aquellos entrañables dibujos animados japone-ses de hace aproximadamente veinticinco años lla-mados Mazinger-Z, y que en España se han repues-to desde entonces en varias ocasiones.

Respecto a la aparición de la primera versión deMZ-Tools, la podemos encontrar en el mes deOctubre de 2000, cuando se hace oficial la versión 1.0de MZ-Tools. Se trataba de una versión para VisualBasic 6.0 distribuida con licencia freeware.

Apenas 6 meses después, aparecería MZ-Tools 2.0siendo una versión mucho más extendida y con máséxito que MZ-Tools 1.0. Igualmente en este caso, lalicencia de distribución de este complemento fue detipo freeware.

Carlos continuó entonces con la mejora de las fun-cionalidades de este complemento, y así, en el mes de

Octubre de 2001, apenas 1 año después de aparecerMZ-Tools 1.0, aparece la aún más renovada y pode-rosa versión MZ-Tools 3.0, un complemento con unadistribución aún mucho mayor que obtuvo un éxitoincontestable. Basta con darnos una pequeña vueltaen Internet y buscar un poco para encontrar todo tipode halagos sobre esta herramienta. Siendo además laúltima versión para Visual Basic 5.0, Visual Basic 6.0y VBA, hoy día es utilizada por una enorme cantidadde desarrolladores en todo el mundo.

¿Y que pasó a partir de ahí?. Carlos se introdujoen la tecnología .NET de Microsoft, y optó por hacerun MZ-Tools para .NET. Así que se puso manos a laobra y con no poco esfuerzo y trabajo, terminó lo quese ha llamado MZ-Tools 4.0, el complemento de MZ-Tools para Visual Studio .NET. Sin embargo, estanueva versión de este famoso complemento, obliga-ría a replantear algunas cosas respecto a versionesanteriores.

MZ-Tools 4.0, sus cambios respecto aanteriores versiones

MZ-Tools 4.0 supuso un importante reto, traba-jo y esfuerzo para Carlos, por lo que ese esfuerzo ydedicación, merecía ser recompensado. De esta mane-ra, MZ-Tools 4.0 se distribuiría a partir de ahora bajolicencia de pago. Es decir, MZ-Tools 4.0 ya no esta-ría bajo la licencia freeware. Algo que si lo pensamosfríamente, tiene su lógica.

Además, MZ-Tools 4.0 obligó a que algunas delas características y propiedades de MZ-Tools 3.0,fueran abandonadas por no considerarse ahoraindispensables. Sin embargo y por fortuna, el nue-vo entorno de desarrollo, ha hecho que se incor-poren a MZ-Tools algunas nuevas utilidades, porlo que MZ-Tools está más enriquecido en estosmomentos.

MZ-Tools 4.0, se distribuye por lo tanto, en dostipos de licencia, una licencia de tipo individual cono-cida como Personal Edition, y que tiene un precio de39,95€, y una licencia de servidor conocida comoEnterprise Edition, y que tiene un precio de 399,95€.Ambas versiones tienen el mismo número de fun-cionalidades, pero la primera tiene una licencia ade-cuada para desarrolladores individuales, mientrasque la segunda tiene una licencia tipo site adecuadapara empresas.

¿Cuándo y cómo

Jorge Serrano

dnm.mvp.online<<

MZ-Tools

Jorge Serranoes redactor de dotNetManía. EsIngeniero Informático y MVP deVB y de .NET. Es Webmaster de

PortalVB.com y autor dediferentes libros y artículos

técnicos. Jorge está entre losmejores profesores y

conferenciantes sobre latecnología .NET de nuestro país.

Page 47: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

La instalación de este complemento para los len-guajes VB.NET y C# de Visual Studio .NET, es real-mente simple. Basta con ejecutar la instalación yseguir las instrucciones que aparecen en pantalla, ypor último, activar el producto con su correspon-diente licencia. Cuando hemos completado estospasos y arrancamos el entorno de desarrollo VisualStudio .NET, nos encontraremos con MZ-Tools inte-grado en nuestro entorno de desarrollo. En el menú“MZ-Tools >> Acerca de”, podremos recoger la infor-mación de la versión de MZ-Tools instalada en nues-tro sistema, así como la licencia del producto, tal ycomo se muestra en la figura 1.

¿Para qué sirven los complementos enun entorno de desarrollo?

Los entornos de desarrollo como Visual Studio.NET, nos ofrecen a los desarrolladores un conjunto deherramientas que nos permiten hacer la vida más fácilal desarrollador. Sin embargo, existen muchos campossin cubrir, sigue habiendo muchas tareas arduas y com-plejas de llevar a cabo, muchas de ellas triviales y repe-titivas que de estar simplificadas o automatizadas, nosahorrarían mucho trabajo. Ahí es donde entra en jue-go el complemento MZ-Tools 4.0.

¿Qué ventajas nos ofrece MZ-Tools 4.0 alos desarrolladores?

La productividad en el desarrollo de aplicacioneses una de las bazas fuertes de este complemento. Susopciones son accesibles rápidamente desde el menúde Visual Studio .NET, desde la barra de botones

incorporada en el entorno, o haciendo clic con elbotón derecho del ratón sobre el código de la apli-cación por ejemplo.

Sus utilidades o funcionalidades son muy exten-sas y variadas, son cerca de 40 entre las cuales pode-mos destacar las siguientes:

Para escribir código más deprisa

• Plantillas de código: nos permite añadir plantillasde código rápidamente, así como gestores deexcepciones como el conocido Try Catch.

• Asistentes para nuevos procedimientos: nos permitecrear propiedades o convertir variables públicasde una clase determinada en propiedades.

• Asistentes para crear cajas de mensajes: permite ade-más de crear las cajas de mensajes, previsualizar-las para ver el resultado.

• Asistentes para cadenas de conexión: permite crearlas cadenas de conexión con bases de datos a tra-vés de ADO.NET, ODBC, OLEDB, etc.

• Asistentes para creación de bloques Select Case en elcaso de VB.NET y bloques switch en el caso deC#, a partir de valores o listas enumeradas enum.

Para encontrar código más deprisa

• Búsqueda avanzada: permite realizar una búsquedamostrando los resultados en un árbol, agrupandolos datos por proyecto, archivo, clase, etc. Permiteincluso eliminar los resultados de la lista que no nosinteresen o bien refrescarla. Se puede además alma-cenar tantas listas de resultados como nos interese,a través de fichas en un TabControl.

• Elementos de código favoritos: nos permite crear unalista con los procedimientos, clases, etc., que usa-mos con más frecuencia, para poder acceder aellos de forma más cómoda.

• Soluciones favoritas: de la misma forma, se puedecrear una lista con las soluciones que usamos conmás frecuencia.

dotN

etM

anía

<<

47

dnm.mvp.online<<

Figura 1.Ventana de versión de MZ-Tools 4.0 e información sobre su licencia

Figura 2. Ejecución en Visual Studio .NET 2003 de la utilidadde búsqueda de MZ-Tools 4.0

Page 48: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

• Funciones de desplazamiento: para poder ir al comien-zo y final de un procedimiento o de una clase deuna manera rápida.

Diseñador de formularios Windows mucho másrápido

• Modo de diseño inteligente: cuando este modo estáactivado, el complemento establece la posición yel tamaño más adecuado para un control cuandolo soltamos sobre un formulario. Para ello, exa-mina los controles vecinos y obtiene cuales son losmejores valores de tamaño y posición para quequeden alineados con los otros controles. Además,establece automáticamente la propiedad TabIndexdel control que hemos agregado al formulario.Esta funcionalidad es una de las más innovadorasde la versión 4.0 de este complemento.

• Asistente TabIndex: permite revisar o establecer deforma muy cómoda (pulsando un botón) la pro-piedad TabIndex adecuada a todos los controles deun formulario.

• Asistente para nombres de controles: permite estable-cer la propiedad Text y Name de los controles de unformulario de manera muy rápida mediante un Grid.La propiedad Name se puede generar automática-mente a partir de la propiedad Text del control. Porejemplo, si a un botón le asignamos el texto “Borrarpedido”, se asignaría automáticamente como nom-bre del control ButtonBorrarPedido.

• Propiedades por defecto de controles o formularios: per-mite definir qué valores por defecto tendrán las pro-piedades de un nuevo formulario cuando se agregaa un proyecto, o las propiedades de un control cuan-do se agrega a un formulario. Por ejemplo, podemosestablecer prefijos para los nombres de los contro-les de forma automática (Button “Btn”, etc.).

Documentación de código mucho más rápido

• Encabezados: hay funciones que permiten agregarencabezados predefinidos a archivos, clases o pro-

cedimientos. Estos encabezados pueden usar varia-bles predefinidas (nombre, autor, fecha, etc.) o varia-bles de usuario (por ejemplo, el propósito de unprocedimiento).

• Generación de documentación en formato XML: conesta funcionalidad se genera un archivo XML contoda la información (proyectos, archivos, clases,procedimientos, etc.) de nuestra solución. Es útilsi se quiere procesar dicha información mediantealgún parser XML para obtener algún tipo deinformación.

• Generación de documentación en formato HTML:como la funcionalidad anterior, pero en formatoHTML, más adecuado para consumo por partede programadores, analistas, etc.

Ayuda en la mejora del código fuente de las aplica-ciones a través de diferentes revisiones

• Revisión de código no permitido: permite detectar sialgún programador ha empleado construccionesde código que se consideran malas prácticas deprogramación, por ejemplo, más de un punto desalida en un procedimiento. Se puede parametri-zar el tipo de construcciones de código que noestán permitidas.

• Revisión de código obligatorio: permite detectar sialgún programador no ha empleado construccio-nes de código que son obligatorias, por ejemplo,que cada procedimiento lleve un encabezado quese ajuste a un estándar. Esta funcionalidad tam-bién se puede parametrizar.

• Revisión de la propiedad TabIndex: comprueba quetodos los controles de los formularios de un pro-yecto tienen el valor de la propiedad TabIndexcorrecto.

• Revisión de las teclas de acceso rápido: comprueba quetodos los controles que lo necesitan tienen una

dotN

etM

anía

<<

48

dnm.mvp.online<<

MZ-Tools no es otra cosa que un add-in o complemento para Visual Basic,VBA y Visual Studio

.NET.De hecho, existen dos versiones de estecomplemento,MZ-Tools 3.0 para Visual Basic 5,Visual Basic 6,VBA y MZ-Tools 4.0 para VisualStudio .NET 2002 y Visual Studio .NET 2003

Figura 3. Ejecución en Visual Studio .NET 2003 de la utilidadde generación de documentación XML de MZ-Tools 4.0

Page 49: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

49

dnm.mvp.online<<

tecla de acceso rápido (la letra subrayada de quepermite usar la tecla [Alt]) y que no hay teclas deacceso rápido repetidas.

• Revisión de código fuente no usado: informa de pro-cedimientos, variables, parámetros, etc., que noson usados en ninguna parte del código y que porlo tanto, podrían ser eliminados.

Otras funcionalidades

• Estadísticas: permite obtener estadísticas detalla-das del número de archivos, clases, procedimien-tos, etc. de nuestra solución.

• Autoguardar: permite guardar automáticamenteel código fuente que vamos escribiendo cada pocosminutos.

• Reordenar elementos de código: permite reordenarclases, procedimientos, etc., por nombre, visibi-lidad, etc.

• Colapsar proyectos de una solución en el Explorador desoluciones, muy útil si tenemos muchos archivos.

• Portapapeles privados: hasta 9, que permite alma-cenar trozos de código para uso frecuente.

• Herramienta extensible: expone el API que usa inter-namente para sus operaciones de revisión y permi-te crear nuevos tipos de revisiones. Por ejemplo, seproporciona el código fuente de una revisión decorrección ortográfica del texto de los controlesusando el corrector ortográfico de Microsoft Word.

ConclusiónComo podemos observar, este complemento no

sólo está compuesto por un conjunto de funcionali-dades útiles, sino que podríamos afirmar sin dudar-lo, que estas funcionalidades podrían ser catalogadassin problemas como indispensables.

El hecho de que nuestra productividad y renta-bilidad en las horas que pasamos delante de un orde-nador haciendo funciones de desarrollo pueda serincrementado, es algo que debería hacernos refle-

xionar, sobre todo, cuando nuestra función de desa-rrollo es frecuente o cuando desarrollamos aplica-ciones de cierta envergadura.

MZ-Tools es una de estas utilidades que nos haránla vida mucho más fácil y nos permitirá reducir enor-memente la curva de desarrollo ganando tiempo ycalidad en nuestros desarrollos.

Carlos es MVP de VisualDeveloper .NET desde Enero de2004. Respecto a su formación,es Ingeniero Superior deTelecomunicaciones por laUniversidad Politécnica deMadrid, pero desde el principiode su carrera profesional se dedi-có al mundo de la programación.

Lleva trabajando 10 años en el grupo Sogecable(http://www.sogecable.com) dónde desde hace varios añosejerce en el puesto de Jefe de Área de Tecnología en sudepartamento de desarrollo. Desde el inicio ha traba-jado con herramientas de Microsoft desde Visual Basic3.0 hasta Visual Studio .NET.

En el año 2000 comenzó a desarrollar MZ-Tools,objetivo de este artículo, actualizándolo y mejorándo-lo consecutivamente. MZ-Tools 3.0 es usado hoy díapor docenas de miles de desarrolladores en todo elmundo, y la versión MZ-Tools 4.0 comenzó su anda-dura en el año 2004.

Adicionalmente, contribuye asiduamente en losgrupos de discusión –especialmente en habla inglesa–sobre lenguajes y tecnologías de desarrollo como VisualBasic, Add-Ins para .NET, etc. Acerca de sus contri-buciones a las Comunidades, tiene mención especialel foro público de Yahoo (http://groups.yahoo.com/-group/vsnetaddin) dónde Carlos contribuye de formaespecial contestando infinidad de preguntas sobre com-plementos en .NET y organizando la sección de recur-sos de este foro como documentación, artículos, ejem-plos, base de conocimiento, bugs, etc.

Podrás contactar con él en la dirección de [email protected].

Si quieres saber más sobre el programa MVP pue-des consultar la página oficial de Microsoft en:http://mvp.support.microsoft.com

Sobre Carlos J.Quintero

Carlos J. Quintero

MZ-Tools es una de estas utilidades que nos haránla vida mucho más fácil y nos permitirá reducirenormemente la curva de desarrollo ganando

tiempo y calidad en nuestros desarrollos

Si desea aprender más acerca de MZ-Tools y adquiriruna licencia para su entorno, puede hacerlo en:

MZ-Tools: http://www.mztools.comMZ-Tools Legal Notice: http://www.mztools.com/legal_notice.htm

Page 50: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

50

dnm.comunidad.net<<

DOTNETSOLIDARIOEl lado humano de la tecnología

todo se mueve muy deprisa: conseguir unmejor rendimiento en nuestras aplicaciones es algofundamental, tener un microprocesador más veloz esimprescindible, y a veces conseguir un milisegundomas rápido de tiempo de ejecución es un gran logro.

Así no es de extrañar, que nunca nos hayamos para-do un momento a pensar en cuál debe ser el objetivo

final de todos estos avances tecnológicos.En este mundo que nos movemos, de las

tecnologías de la información, todo resultaa veces muy frío, y por más que busquemos

nos resulta muy complicado encontrar la con-ciencia social en nuestro sector.

Por este motivo surge una iniciativa que trata deencontrar ese lado humano a las tecnologías de la infor-mación, y que se llama DOTNETSOLIDARIO. Elobjetivo de DOTNETSOLIDARIO es dar a cono-cer los proyectos de las ONG y prestarles ayuda através de la tecnología .NET, proporcionándolesservicios gratuitos para que puedan desarrollar susproyectos.

Estos servicios gratuitosque ofrece DOTNETSOLI-DARIO a las ONG son lossiguientes:

• Hosting ASP .NET, aloja-miento gratuito en un ser-vidor Web que permite laejecución de paginas ASP yASP .NET, 50 megas deespacio en disco, y una cuenta FTP para poderactualizar la web siempre que se desee. Tambiéndispone de la posibilidad de alojar su base dedatos en Microsoft Access.

• Software .NET. Gracias a la colaboración deMicrosoft las ONG que vayan a realizar su Weben ASP.NET podrán obtener, sin cargo alguno,una licencia de Visual Studio .NET 2003Professional. Esta promoción esta limitada aONG que estén radicadas en España.

• Formación .NET, gracias a la colaboración deMSDN se impartirán seminarios relacionadoscon las tecnologías .NET, especialmente orien-tados al desarrollo Web con ASP.NET

• Desarrollo .NET, para las ONG que deseen cre-ar su Web pero no dispongan de medios se ofre-ce la posibilidad de buscar colaboradores, sin áni-mo de lucro, que les puedan ayudar a través deDOTNETSOLIDARIO.Todas estas ayudas para las ONG ya están disponi-

bles en el portal DOTNETSOLIDARIO, le reco-mendamos que lo visite si desea ver más información alrespecto. Pero si no quieren quedarse sólo en eso, DOT-NETSOLIDARIO tiene previsto ir ampliando estosservicios e ir añadiendo otras nuevas ideas para poten-ciar aún más el apoyo de la tecnología .NET en favorde las iniciativas solidarias. Actualmente, están prepa-rando una iniciativa para realizar una recogida de mate-rial informático para montar escuelas en el tercer mun-do, pero de momento no podemos contar más, esta ideaestá sólo en proyecto.

En la Web de DOTNETSOLIDARIO cabe des-tacar su foro donde se pueden abrir debates, dejarsugerencias y comentarios y opinar de todo lo quequeráis. También hay disponible un chat, en el cualse pueden intercambiar opiniones con otros usuariostanto de temas solidarios como de cosas relaciona-dos con la tecnología .NET.

<< En nuestro mundo

Aunque habitualmente en esta sección se suelen dar a conocer portales dedicadosexclusivamente a temas relacionados con .NET, en esta ocasión queremos presen-taros un portal que trata de fusionar iniciativas solidarias con temas relacionados

con la tecnología .NET, se trata de DOTNETSOLIDARIO.

El objetivo de DOTNETSOLIDARIO es dar a conocerlos proyectos de las ONG y prestarles ayuda a través

de la tecnología .NET, proporcionándoles servicios gra-tuitos para que puedan desarrollar sus proyectos. ][

1 Finalmente, el dominio de DOTNETSOLIDARIO es dotnetsolidario.com y no dotnetsolidario.info como fue en un principio

Page 51: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Y, por supuesto, en el portal DOTNETSOLIDA-RIO también tenéis información de todas las ONG quese han registrado en DOTNETSOLIDARIO, así comode los proyectos que están realizando estas ONG. Y siestás interesado en colaborar con alguna ONG en algu-no de los proyectos que están publicados puedes solici-tarlo a través de la Web de DOTNETSOLIDARIO.

Pero DOTNETSOLIDARIO no es sólo una Web interesante para las ONG, también dispone de unarecopilación de cientos de artículos relacionados con.NET, que va creciendo día a día y que sin duda es degran utilidad para cualquier desarrollador .NET.

Actualmente dispone de más de 500 artículos, perocada día son añadidos nuevos artículos y por supues-to todos en castellano.

Y muy interesante para los desarrolladores es elCLUB DOTNETSOLIDARIO, al que podrá apun-tarse todo el que lo desee para estar informado de lasúltimas novedades relacionadas con la tecnología .NETy los proyectos solidarios que se vayan publicando. ElCLUB DOTNETSOLIDARIO pretende ser unacomunidad de personas solidarias e interesadas en la tec-nología .NET. Por supuesto apuntarse no cuesta nada y

te permitirá estar informado de las actividades que vayarealizando la comunidad DOTNETSOLIDARIO.

Pero su intención es la de ser una comunidad diná-mica donde todos sus miembros aporten su granitode arena. Cada uno de la manera que quiera o quepueda, bien aportando ideas, sugerencias, artículos, ocualquier ayuda para poder llevar a cabo iniciativassolidarias, o simplemente para compartir sus conoci-mientos con los demás.

“El conocimiento es un bien que crece a medida quese comparte”. Ésta es la frase que podrá ver en todaslas páginas de la Web de DOTNETSOLIDARIOy que resume su filosofía.

Por último, recordaros que la Web DOTNETSO-LIDARIO podéis verla en http://www.dotnetsolidario.com1.Se trata de una iniciativa sin ánimo de lucro, que estáabierta a la colaboración con otras personas u organiza-ciones. La tecnología no puede olvidar nunca su ladohumano; si todos tenemos en mente esta idea, DOT-NETSOLIDARIO habrá logrado su objetivo.

dnm.comunidad.net

“El conocimiento es un bien que crece a medidaque se comparte”, esta es la frase que podrá veren todas las páginas de la web de DOTNETSO-

LIDARIO y que resume su filosofía. ][

Horizontales6. Importante recurso de programación que se basa

en usar una pila y que no existió en el primer len-guaje FORTRAN (E)

11. Nombre que se le da al concepto de que un obje-to agrupe métodos (código) y variables (memo-ria) (E)

12. Característica importante de los lenguajes con jerar-quías de tipo, gracias a la cual, un objeto de un tipo

derivado puede ser asignado a una variable o pará-metro declarado como de un tipo base (E)

14. Nombre que se le da a la información generalincluida en un ensamblado .NET y que describe aéste (E)

18. Nombre del “objeto” utilizado en una aplicaciónWeb ASP.NET para compartir información entretodas las páginas con independencia de la identi-dad del cliente (I)

22. Nombre que se le da a la capacidad de poder defi-nir más de un método con el mismo nombre (E)

23. Siglas del protocolo estándar utilizado para el inter-cambio de objetos en la Web (I)

Verticales1. Atributo que se le pone en .NET a la definición de

un tipo para indicar que los objetos de este tipopueden ser transferidos por la red (E)

2. Especificador de forma de traspaso de paráme-tros en C# que obliga al método llamado a asig-narle un valor al parámetro formal antes de retor-nar (I)

3. Iniciales del cómo se denominan los controles quese ejecutan en el lado del servidor y mediante loscuales una aplicación Web puede ofrecer interfacesde usuario que se muestran en el cliente según lascapacidades de éste (I)

4. Siglas del mecanismo de compilación que aplica elCLR .NET cuando carga un ensamblado (I)

5. Siglas del mecanismo de seguridad aplicado duran-te la ejecución de código en .NET (I)

7. Nombre del indicador existente en el lenguaje Ccon el que se puede especificar que dos variablesocupan la misma zona de memoria (I)

8. Iniciales de cómo se le llama en un lenguaje a lacaracterística de que no haya diferencia sintácticaen la forma en que se le consulta a un objeto unvalor independientemente si este valor es calcula-do o está representado directamente en memoriapor una variable de instancia.C# da soporte a estomediante las propiedades (E)

9. Nombre correspondiente en VB al this de C# (I)10. ¡Importante revista española dedicada a la tecno-

logía .NET! (E)13.Especificación de forma de traspaso de parámetros

que permite que cuando se le asigne al parámetroformal un valor, éste se asigne sobre el parámetroreal. (I)

15.Concepto en .NET que complementa al de la refle-xión para poder generar tipos dinámicamente (I)

16.Especificador en C# para indicar múltiples pará-metros en la definición de un método (I)

17.Nombre del recurso en Pascal equivalente alstruct de C (I)

19.Extensión utilizada por los ficheros de música deWindows Media Player (I)

20. Iniciales del modelo de componentes de Microsoft (I)21. Iniciales del mecanismo al que está asociado la apli-

cación del método Finalize en C# (I)

CRUCIGRAMA

(c) G

rupo

Web

oo

Nota La “E” indica que la respuesta es en español, la “I” indica que la respuesta es en inglés)Las soluciones en dotnetmanía.com

Page 52: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

es -ciertamente- un noble arte, pero, antes deque los artistas se introduzcan en el análisis exhaustivodel código, es preferible contar con un buen grupo deingenieros que revisen los pilares y fundamentos de laaplicación. Allí es donde tiene lugar la verdadera opti-mización. Para las aplicaciones ASP.NET, por ejemplo,eso significa reducir el tiempo de descarga entre nodosy mejorar la gestión de estado, quizá utilizando páginasde acceso asíncrono. Con toda seguridad, hay trucos apli-cables en todo esto, pero ése es el auténtico objetivo delartista. Y ahí es donde la optimización se convierte enarte noble. Si la aplicación está pobremente diseñada,no hay mucho que los artistas puedan hacer. Si está biendiseñada, las optimizaciones, en cambio, pueden mar-car la diferencia.

En este artículo, no me referiré específicamente alrendimiento de aplicaciones ASP.NET o Windows. Enuna sección de Preguntas y Respuestas, las generalizacio-nes no están permitidas. No puedes sencillamente pre-guntar ¿cómo puedo hacer que mi aplicación ASP.NETvuele? Las mejoras de rendimiento, aunque pueden cate-gorizarse dentro de un conjunto común de patrones, sonsólo aplicables rigurosamente para cada aplicación enconcreto y requiere de los artistas e ingenieros el cono-cimiento interno de todos los recursos implicados. Laspreguntas de este mes se refieren al rendimiento, peroson cuestiones específicas, que la mayoría de los lecto-res encontrarán de utilidad.

Yo estaba convencido de que la gestión de cade-nas desde una aplicación .NET no era uno de suspuntos fuertes. Ahora me doy cuenta de que son

más rápidas que ninguna de las plataformas anterio-res, pero no puedo concatenarlas eficientemente.¿Qué es lo que sucede exactamente?

Las cadenas son un tipo de dato muy común entodo tipo de aplicaciones, y no sólo en .NET. Piensasque la optimización del tratamiento de cadenas pue-de tener un gran impacto sobre el rendimiento gene-ral de la aplicación debido a que las cadenas son mane-jadas con frecuencia. Pero, ¿qué es una cadena en elcontexto de .NET?

En .NET, hay dos categorías de tipos básicos:por valor y por referencia. Los tipos por valor sonligeros, y corresponden con tipos usados frecuente-mente, tales como byte, char, single, double, long,bool, decimal e int64. Además, incorporan los tiposenum, struct, y, en general, cualquier tipo que here-

Consideraciones de rendimiento

Dino Esposito

dnm.todotnet.qa

<< La optimización

Dino Esposito es redactor de dotNetManía.

Formador, consultor y escritorafincado en Roma.Miembro

del equipo de Wintellect,Dino está especializado en

ASP.NET y ADO.NET. Puedeenviarle sus consultas a

[email protected]

Era estudiante de primer año en la universidad, cuando uno de los profesores dijo algo queno he sido capaz de olvidar en los 20 años siguientes. En una clase de Algorítmica, el profe-sor estaba explicándonos cómo computar el rendimiento de un algoritmo y cómo clasificar-lo en el tiempo y en el espacio.Un estudiante alzó su mano y preguntó: ¿nos debería impor-tar realmente el rendimiento?, ¿no basta con comprar una máquina más rápida? Su respues-ta, fue sorprendente para la mayoría de nosotros:“Las máquinas rápidas son las más benefi-ciadas de los algoritmos rápidos”. ¿Qué significa esto para el desarrollador de .NET?

A pesar de que la gestión decadenas en .NET es más eficien-te que en plataformas anterio-res, no puedo concatenarlas

eficientemente. ¿Qué es lo quesucede exactamente?

¿?

Page 53: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

de de la clase ValueType. Estos tipos se ubican en lapila correspondiente al proceso en ejecución, no enel montón (heap) administrado, y no están sujetos ala destrucción dinámica asociada al Recolector deBasura (Garbage Collector). Una variable que instan-cia un tipo por valor no se referencia mediante unadirección de memoria, sino que contiene en si mis-ma los campos de esa instancia. Cuando se copia, seefectúa una copia campo a campo. Los tipos por valorno pueden ser heredados.

Por otro lado, un tipo por referencia tiene sumemoria asociada ubicada en el montón administra-do, requiere una inicialización y la presencia delRecolector de Basura. Cualquier tipo al que nos refe-rimos como clase es un tipo por referencia. Cuandoasignamos un tipo por referencia a otra variable, sólose copia la dirección de memoria. Según esto, dos omás variables pueden “apuntar” al mismo objeto físi-co. Los cambios producidos en cualquiera de las varia-bles pueden afectar a las otras.

Los tipos por valor tienen dos representaciones–empaquetada y no empaquetada– (boxed y unboxed),mientras que los tipos por referencia sólo existenen forma empaquetada. Empaquetar quiere decirconvertir un tipo por valor en un tipo por referen-cia. El empaquetado no siempre es necesario. Sólose requiere cuando se pasa un tipo por valor a untipo por referencia. Esta técnica tiene un impactoen el rendimiento porque debe crearse un nuevoobjeto en el montón administrado, copiar los cam-pos de datos y, finalmente, se devuelve la direccióndel nuevo objeto así creado. Una aplicación hechaexclusivamente de tipos por referencia se ejecuta-ría más lentamente, y por consiguiente, lo mismole sucedería a un aplicación que utilizase constan-temente las técnicas de empaquetado y desempa-quetado.

Así pues, ¿crees que una cadena es un tipo por valoro por referencia? En .NET una cadena es un tipo porreferencia.

Una cadena es una secuencia inmutable de carac-teres ordenados. La clase String hereda deSystem.Object e implementa varias interfaces:IComparable, ICloneable, IConvertible e IEnumerable.Las cadenas son tipos primitivos para los compila-dores de C# y Visual Basic .NET, lo que las con-vierte en un tipo por referencia muy especial. Por

ejemplo, podemos crear una cadena sin llamar aloperador new. Por razones de rendimiento, el CLRgestiona el manejo de la cadena y la marca comosellada (no heredable), evitando así que el usuariocree sus propios tipos de cadenas. Además, las cade-nas son inmutables: una vez creadas no puedenmodificarse de ninguna forma. Podemos trabajarcon ellas, pero no cambiar su valor. Cuando usamosexpresiones complejas, que concatenan múltiplescadenas, se generan muchos objetos de vida corta,lo que no supone una merma en el rendimiento,debido a que son fáciles de reciclar por el Recolectorde Basura. Y, más importante aún, las cadenas sonmantenidas en un depósito global de memoria deforma que las variables de memoria que apuntan almismo texto, son, en definitiva, punteros a la mis-ma dirección. El CLR mantiene una tabla hash deobjetos String y utiliza el texto como clave. Cuandose solicita una cadena, el CLR busca la cadena enla tabla y la recupera de forma rápida y eficiente.Como decía mi profesor, las tablas hash son muyrápidas a la hora de recuperar cualquier dato con-tenido en la tabla. El secreto principal del rendi-miento para las cadenas es precisamente, su carác-ter inmutable y constante. ¿Qué sucede si concate-nas dos cadenas?

Si, simplemente, sumas dos cadenas, sucede algoinesperado. Como una cadena no puede ser modifi-cada por diseño, si se añade una cadena a otra, se creauna nueva con el tamaño apropiado para contener lasuma de ambas. Para evitar la penalización de estaforma de trabajo, deberíamos utilizar la claseStringBuilder.

Esta clase funciona de forma muy similar a cómofuncionaban las cadenas en las plataformas anterioresa .NET. Cuando añadimos una cadena a unStringBuilder, si la capacidad de éste no es suficien-te, se incrementa para permitir albergar a la nuevacadena. Los miembros de la clase permiten recompo-ner la cadena y añadirle formato. Por último, el méto-do ToString(), devuelve el texto almacenado comouna cadena clásica, inmutable.

Nunca deberíamos utilizar concatenación, sinomás bien, usar la clase StringBuilder para componerdos o más cadenas. También es correcto el uso deStringFormat ya que –internamente– utiliza un obje-to StringBuilder.

dotN

etM

anía

<<

53

dnm.todotnet.qa<<

Los tipos por valor sonligeros, y correspondencon tipos usados fre-

cuentemente“

”To

do

tNet.

qa@

do

tnetm

an

ia.c

om

.To

do

tNet.

qa@

do

tnetm

an

ia.c

omCualquier tipo al que

nos referimos como clase es un tipo por

referencia.“

Page 54: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

Una parte de mi vieja aplicación VB6 estaba dise-ñada para enlazar objetos dinámicos. En VB6 utili-zaba enlace tardío. Cuando he migrado la aplicacióna .NET utilicé bastante la introspección (Reflection).¿Supone esto un problema? El rendimiento no esmalo, pero me gustaría poder mejorarlo todavía más.

El enlace tardío en .NET puede obtenerse a travésde métodos de la clase Activator. Resumiendo, Activatores aproximadamente equivalente a CreateObject, en elsentido de que toma un ensamblado y un nombre ydevuelve un objeto. El método CreateInstance de la cla-se Activator es bastante rápido, pues recupera el cons-tructor de la clase y lo invoca. El problema viene des-pués. ¿Cómo trabajamos con los objetos creados de estaforma? Si conoces algo del objeto, –como por ejemplosu interfaz– podemos hacer un “casting” a dicho inter-faz y trabajar sin penalizaciones de rendimiento. Si no,tenemos que utilizar Reflection y eso tiene una penaliza-ción. Sin embargo, el costo de la introspección es fun-damentalmente, el de los pasos iniciales. Para llamar aun objeto de forma indirecta, necesitas obtener previa-mente un Proxy. Esto es lo que supone una mayor pena-lización y puede optimizarse situando el Proxy en unacaché. Para poner un ejemplo, un Proxy es la claseMethodInfo, que suministra el método Invoke para reali-zar la llamada. Si es posible, deberíamos evitar la crea-ción indiscriminada de objetos del tipo xxxInfo. La reu-tilización de estos objetos, mejora el rendimiento.

Si usas Reflection para importar componentes exter-nos (similar al modelo “plug-in”) apenas tienes proble-mas. Las aplicaciones que pueden potencialmente tenerproblemas de rendimiento son aquellas que investiganlas características de los objetos y, entonces, deciden quéhacer. En este caso, lo que realmente necesitas es unobjeto que se modifique dinámicamente para acomodaral objeto llamado. La ejecución de tu código lleva unacarga superior a lo habitual debido a la sobrecarga de laintrospección. ¿Podría ser de ayuda la generación diná-mica de código?

.NET utiliza la generación dinámica de código y lacompilación dinámica en varios de sus subsistemas –des-de ASP.NET a la seriación XML–. Esto mejora el ren-dimiento, pero sólo si se acompaña de las apropiadaspolíticas de uso de cachés, para minimizar la generación

de código. Para mí, donde cobra mayor sentido es en lossubsistemas fundamentales de tu aplicación. No resultaadecuado para temas puntuales. El costo de implemen-tar un mecanismo similar suele ser trivial. El API a ana-lizar es CodeDOM.

Una pregunta rápida. ¿Deberíamos utilizarDataReaders en lugar de DataSets para mejorar elrendimiento?

Se trata de objetos completamente distintos, de for-ma que la pregunta no refleja una comparación posible.Los Readers son un recurso excelente cuando se necesi-ta consumir datos. Los DataSets son muy buenos cuan-do es preciso almacenar los datos en memoria para suutilización posterior. Si necesitas –simplemente– con-sumir datos, los DataSets no son una buena opción; sinecesitas mover datos entre capas de la aplicación, losDataReaders son, simplemente, imposibles de utilizar.Los sistemas bien diseñados deben de tener esto en cuen-ta a la hora de seleccionar la ruta adecuada.

Consumir datos significa realizar cualquier tipo deoperación sobre un DataRow sin guardarlo en memorialocal. Si esto es lo que necesitas hacer –recorrer datoshasta el final del conjunto de resultados– los DataReadersson adecuados. El uso de un DataSet en este contexto noañade ninguna ventaja, más bien al contrario, diría yo.

Cuando rellenas un DataSet obtienes un Reader, reco-rres los datos y creas filas en una tabla local. Tras esto,para trabajar con los datos, tienes que irlos analizandopara realizar tu labor. Como puedes ver, tiene lugar unadoble navegación, lo que no es bueno.

Por otro lado, yo no suscribo la afirmación de queel uso de los Readers es preferible al uso de DataSets encualquier situación. Hay escenarios donde no es posibleutilizar un Reader en lugar de un DataSet. Si tienes quepasar datos de la capa de lógica intermedia a la capa dedatos, sólo puedes hacerlo utilizando un DataSet.

El único escenario donde el DataSet y los DataReaderspueden usarse indistintamente (con preferencia para losReaders por temas de rendimiento) es en el enlace dedatos ASP.NET. Algunos controles ASP.NET aceptanun DataReader como origen de datos. Esto puede con-llevar una optimización, siempre que no se pueda per-mitir el uso de cachés locales en el servidor Web. Perosi puedes permitírtelo, en mi opinión, la forma auténti-ca de optimización es el uso de cachés.

dotN

etM

anía

<<

54

dnm.todotnet.qa<<

¿Deberíamos utilizarDataReaders en lugar deDataSets para mejorar el

rendimiento?

¿ ?

To

do

tNet.

qa@

do

tnetm

an

ia.c

om

.To

do

tNet.

qa@

do

tnetm

an

ia.c

om

En una vieja aplicación VB6 enlazaba objetos dinámicos y

utilizaba enlace tardío. Cuandomigré la aplicación a .NET utilicé bastante reflection.

¿Supone esto un problema?

¿?

Traducción por Marino Posadas

Page 55: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

55

Con esta pequeña aplicación, podemos cambiarde versión ASP.NET con tan solo un clic de nues-tro ratón. Nos resultará muy útil cuando estemos

testeando nuestrasaplicaciones, pudien-do comprobar que seejecutan bien en dis-tintas versiones deASP.NET.

Tal y como pode-mos ver en la figura, alutilizar ASP .NETSwitcher vemos en laparte superior de laventana un listado detodas nuestras aplica-ciones ASP .NET y

en la parte inferior las distintas versiones de ASP .NETque tengamos instaladas en nuestra máquina.

Seleccionando la aplicación que deseemos ejecutar pode-mos ir cambiando de versión de ASP.NET tan soloseleccionándolo en ASP.NET Version Switcher.

En realidad lo que hace ASP.NET Switcher es reali-zar una llamada al comando ASPNET_REGIIIS que vieneincluido en el Framework .NET para cambiar de unaversión a otra, sencillo pero práctico.

Además es totalmente gratuita y ocupa muy poco,por lo cual se convierte en una herramienta muy prác-tica que siempre nos puede ahorrar tiempo en nues-tras pruebas.

Pedro Pozo

dnm.laboratorio.net

ASP.NET Version Switcher

Pedro Pozoes redactor de dotNetManía. Es

es consultor e-Bussines.Ingeniero Técnico Informático

de Sistemas y Webmaster del portal para desarrolladores

.NET Framework Clikear.com

Ficha técnicaNombre ASP .NET Version SwitcherVersión 1.1Fabricante DenisBauer.com

Webhttp://www.denisbauer.com/NETTools/ASPNETVersionSwitcher.aspx

Categoría UtilidadesPrecio GRATISValoración

Cada vez son más las páginas Web que presen-tan sus contenidos personalizados dependiendo delpaís o del lenguaje del usuario que las visita. Si estápensando en realizar una Web de ese tipo, el com-ponente Localization Manager le puede resultar muyútil.

Se trata de un componente totalmente gratuito,lo podrá descargar de Internet e instalar en sólo unosminutos, y además también incluye unos ejemplosdonde poder comprobar el funcionamiento de estecomponente y ver lo sencillo que es utilizarlo en suspáginas Web.

Por ejemplo, si desea comprobar cuál es el len-guaje que está utilizando el usuario que se conec-ta a su Web, tan solo deberá llamar al métodosiguiente:

ActiveUp.WebControls.LocalizationManager.ParseLanguageCode

Si desea obtener el país desde el cuál está acce-diendo el usuario que se conecta a su Web, tan solodeberá llamar al método siguiente:

ActiveUp.WebControls.LocalizationManager.ParseCountryCode

La lógica que utiliza el método ParseCountryCodeno es 100% fiable, esto es debido a que LocalizationManager utiliza un pequeño truco, y es comprobar lainformación que es enviada por el navegador al servi-dor en cada petición de página Web. Esto supone unpequeño inconveniente y es que si, por ejemplo, estu-viésemos en España y tuviésemos nuestro navegador eninglés, configurado con idioma por defecto en ingles,pues el componente Localization Manager nos devolve-ría nuestro país e idioma, el inglés, aunque realmenteestamos conectándonos en España.

A pesar de esto, Localization Manager se trata de uncomponente que puede ser muy práctico en cualquierdesarrollo multilenguaje, y es una alternativa más eco-nómica que otros componentes que se basan en la direc-ción IP del usuario como método para detectar el paísdesde el que se conecta.

Localization Manager

Ficha técnicaNombre Localization ManagerVersión 1.1Fabricante Active VP

Webhttp://www.activeup.com/products/components/localizationmanager

Categoría ComponentesPrecio GRATISValoración

<<

<<

Page 56: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

<< dnm.laboratorio.net

56

<<do

tNet

Man

ía

Si en la máquina donde desarrollas tienes ins-talado Personal Web Server podrás haber compro-bado que sólo puedes crear un sitio Web. Estosupone un inconveniente cuando tienes en desa-rrollo varias webs, ya que no puedes definir varioswebsites.

Si está en esta situación le será de gran utilidadISAPI URL Mapper. Se trata de un filtro ISAPI quenos permite crear más de un website, identificandoa los diferentes sites que definamos.

Para utilizar esta utilidad deberemos registrarcomo un filtro ISAPI la DLL URLMAPPER.DLL que vaincluida en el paquete. Posteriormente añadiremosel cgi URLMapperConfig al directorio en el que se

encuentra la Web que deseamos crear y que nos per-mitirá configurarlo.

De esta forma ya tendremos listo nuestro servidorWeb y podremos crear tantos websites virtuales comoqueramos.

ISAPI URL Mapper

Ficha técnicaNombre ISAPI URL MapperVersión 1.1Fabricante newObjects[]

Webhttp://www.newobjects.com/product.asp?Category=46&Story=94

Categoría UtilidadesPrecio 40$Valoración

Sharp PDF es una librería que nos permite cre-ar documentos en formato PDF dinámicamenteen nuestras aplicaciones. Se trata de un compo-nente de código abierto y totalmente gratuito,desarrollado por completo con C#.

De fácil manejo, nos servirá tanto para nuestrasaplicaciones Web como para las aplicaciones deescritorio. Y como dispone-mos del código fuente, siem-pre podremos introducir lasmodificaciones que conside-remos necesarias para adap-tarlo a las necesidades denuestro proyecto.

Su forma de trabajar esmuy sencilla, inicialmente secrea un objeto del tipo pdfDocument, que representaal documento PDF. A nuestro objeto pdfDocument ledeberemos ir añadiendo los objetos pdfPage, querepresentan las páginas del documento y que a su vezestán formadas por objetos del tipo pdfObjects.

Los pdfObjects se pueden dividir en dos tipos:• Objetos Reales. Son elementos escritos directamen-

te en el código PDF y que son creados llamandoa métodos de la clase pdfPage. Algunos ejemplosde estos elementos son text, paragraph, line, image.

• Objetos Abstractos. Son elementos que son cre-ados a partir de una colección de elementos

reales. Además estos elementos tienen suspropias clases que los definen como por ejem-plo pdfTable, pdfPageMaker, pdfPersistanPagey pdfBookmarkNode.

A continuación veamos un ejemplo de lo sen-cillo que es utilizar Sharp PDF en nuestros desa-rrollos, y en un alarde de originalidad he creadoun ejemplo en el que creamos un documento PDFque contiene el texto “Hola Mundo”.

Sin duda un componente muy recomendable,por las posibilidades que nos ofrece, por su senci-llez de manejo y a un precio inigualable.

Sharp PDF

Ficha técnicaNombre Sharp PDFVersión 2.0 Beta 2Web http://sharppdf.sourceforge.netCategoría ComponentePrecio GRATIS (licencia LGPL)Valoración

<<

<<

pdfDocument miDocumento = new pdfDocument("EJEMPLO","PEDRO");pdfPage miPagina = miDocumento.addPage();miPagina.addText("Hola Mundo",200,450,predefinedFont.csHelvetica,20);miDocumento.createPDF(@"c:\holamundo.pdf");

Page 57: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

dotN

etM

anía

<<

57

<<

La Cara Oculta de C#Ian Maartens

Editorial: IntSight EspañaISBN: 84-607-9860-7Páginas: 465Publicado: Enero, 2004

Estamos ante uno de los mejores libros que hemos visto en castellano sobre ADO.NET (elautor es de habla hispana, a pesar del nombre). Una obra pensada para el desarrollador porun desarrollador, que aborda los problemas diarios y las dificultades típicas que se presen-tan más allá de la presentación de datos en un control. Además, contiene no pocas dosis dehumor bien entendido. Según sus propias palabras:

“La primera parte presenta el lado menos conocido de Transact SQL y SQL Server: las téc-nicas más útiles desde el punto de vista de un programador; la segunda parte explica qué esADO.NET, cómo funcionan las capas conectadas y desconectadas, y cómo se pueden pre-sentar los datos extraídos de una base de datos en una aplicación basada en Windows Forms.Finalmente, la tercera parte cubre temas poco frecuentes: desde .NET Remoting, pasandopor los servicios Web, para terminar explicando el funcionamiento de los servicios corpo-rativos de COM+. El último capítulo ofrece técnicas y sugerencias de utilidad para crear ser-vidores de capa intermedia (cifrado, colas de mensajes, envío de correo electrónico...)”.Absolutamente recomendable.

Windows Forms Programming in C#Chris Sells

Editorial: Addison-WesleyISBN: 0321116208 Páginas: 736Publicado: Agosto, 2003

Muchos expertos de talla (como Jeff Prosise, Brian Randell o Fritz Onion) hanrecomendado esta obra como “imprescindible” para el desarrollador de aplicacio-nes Windows. Salvando las distancias, también la recomendamos aquí, no sólo porsu temática (más escasa de lo que parece), sino por la calidad del contenido y laexposición. Aborda absolutamente todo lo necesario para la correcta construcciónde aplicaciones Windows, sin concesiones a la galería, y sin eludir ninguno de losentresijos necesarios para su desarrollo, optimización e implantación.

Y un detalle más para animar a su lectura: Chris fue contratado el pasado año paratrabajar en uno de los equipos de desarrollo de Visual Studio 2005: ¿imaginan cuál?

dnm.biblioteca.net<<

dnm.biblioteca.net

Page 58: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que

La nueva XBox 2,dispondrá de una potencia de cálculo simi-lar a la de los superordenadores:un billón de operacionespor segundoJ. Allard, Microsoft Corporate Vice President y Chief XNA (laplataforma para la construcción de juegos de Microsoft), pre-sentó a primeros de marzo la que será nueva versión de lapopular consola. “La potencia de cálculo será similar a la de unsuperordenador, y permitirá la creación de toda una nueva genera-ción de juegos que aprovechará toda la potencia del hardware actual,para ofrecer una experiencia de usuario sin precedentes hasta aho-ra.", afirmaba Allard. Microsoft ha contado con la colabora-ción de dos grandes compañías en la creación de la platafor-ma: IBM por parte de los procesadores, y ATI Technologiespara el soporte gráfico.

El anuncio casi coincide en el tiempo con la presentación delnuevo XNA Studio, la plataforma de desarrollo específica-mente pensada para juegos, basada en Visual Studio 2005.A este respecto, Chris Satchell, Director de XNA enMicrosoft., afirmaba: “No sólo se hacen necesarias nuevas plata-

formas de hardware para poder ofre-cer a los jugadores más de lo que demandan,

sino que el verdadero reto consiste en integrar todo el proceso de desa-rrollo, para que se automaticen muchas rutinas que hasta ahoraobligaban a volver a programar a menudo las mismas. Gracias aXNA, los desarrolladores podrán plasmar sus visiones y crear jue-gos de mayor calidad en menos tiempo.

IBM duplica la capacidad del que era –hasta ahora– el orde-nador más potente del mundo. Blue-Gene/L: 72 trillonesde teraflops.Los investigadores de IBM en Lawrence Livermore,California, han comunicado la adición de 32.000 nuevos pro-cesadores al superordenador Blue-Gene/L, que ya contabacon otros 32.000, lo que le convertía en el más potente delplaneta. La iniciativa es parte de un proyecto todavía másambicioso, tendente a conseguir un ensamblado hardware decerca de 130.000 procesadores, para el próximo mes de junio,lo que debería conducir a un nivel de rendimiento cercano alos 300 trillones de teraflops.

dotN

etM

anía

<<

58

no

ticia

s.n

oti

cia

s

Sitio Web de Lluís Franco:http://www.uyssoft.com coninformación sobre VB.NET, C#, ADO.NET, que recopi-la artículos, recursos, utilidades y muchas más cosas sobre.NET.

The Visual Basic Team: ¿Quiere saber qué se está cociendoen al cocina del desarrollo de la próxima versión de VisualBasic .NET? Este es uno de los sitios para verlo. Controles,novedades del lenguaje, comportamiento en acceso a datosy casi de todo (en inglés: http://blogs.msdn.com/vbteam/cate-gory/4754.aspx).

dnm.desvan<<

Marino Posadas

Cómo subir y bajar ficheros mediante ASP.NET: File Uploadwith ASP.NET (http://www.codeproject.com/aspnet/fileu-pload.asp) lo explica con todo lujo de detalles. Eso sí, hayque darse de alta antes en CodeProject, sitio ya reco-mendado en esta revista.

Generar una aplicación de principio a fin (con C#), Excelentey completo documento cuyo título habla por sí mismo acer-ca de las buenas prácticas en la construcción de aplicacionespara .NET. Aunque está pensado para el lenguaje C#, es fácil-mente extrapolable a cual otro de los lenguajes de la plata-forma. Creado por Microsoft en su “Universidad .NET” deArgentina, y disponible en http://www.microsoft.com/spa-nish/msdn/comunidad/uni.net/CSharpnet/about.asp

Documentos en la Red

A Daniel, que ha querido venir al mundo también en 2005.Daniel, venga, que vienes a tiempo de probar la Beta 2 :-). ¡Suerte chaval!

Enlaces del mes

Page 59: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que
Page 60: Visual Basic.NET • C# • Delphi • ASP.NET • ADO.NET • .NET ... · Manipulación de imágenes con ADO.NET ... ediciones de SQL Server 2005 y Visual Studio 2005,con las que