Mostrando entradas con la etiqueta C#. Mostrar todas las entradas
Mostrando entradas con la etiqueta C#. Mostrar todas las entradas

martes, 7 de mayo de 2019

MVC 5 Desde Cero

Hola a todos. Luego de casi dos años de trabajo, terminé de escribir segundo libro: MVC 5 desde cero - Guía paso a paso usando C# y Visual Studio 2017 para Amazon Kindle e Impreso. ¡Espero lo compren y les guste!

Le puse "talento" y versión kindle tiene más de 1000 páginas. La Versión impresa tiene más de 600 páginas.

Cada capítulo tiene su código fuente en GitLab: http://gitlab.com/hernaldog/mvc5desdecero/

Compras por Amazon

Valor Kindle: a sólo 26 USD:

https://www.amazon.com/MVC-Desde-Cero-usando-Spanish-ebook-dp-B07QX9PB11/dp/B07QX9PB11/ref=mt_kindle?_encoding=UTF8&me=&qid=

Valor libro impreso a 35 USD (más gastos envío):

https://www.amazon.com/MVC-Desde-Cero-usando-Spanish/dp/1095327585/ref=tmm_pap_swatch_0?_encoding=UTF8&qid=&sr=

En Chile (impreso)

Por Mercado Libre valor $25.000:

https://articulo.mercadolibre.cl/MLC-487764851-libro-impreso-mvc-5-desde-cero-con-visual-studio-2017-_JM?quantity=1

Por Yapo valor $25.000:

https://www.yapo.cl/region_metropolitana/libros_revistas/libro_nuevo_impreso_mvc_5_desde_cero_63241045.htm



Tabla de contenidos
Contenido

1. Introducción
1.1 Introducción a ASP.NET MVC
1.2 Resumen de ASP.NET MVC 5
1.3 Instalando Visual Studio 2017
1.4 Creando una aplicación MVC 5
1.5 Estructura de una aplicación MVC en Visual Studio
1.6 Resumen
1.7 Ejercicios
1.8 Código fuente del capítulo

2. Controladores
2.1 El rol del controlador
2.2 Un ejemplo: la famosa tienda de música MVC
2.3 Un Controlador básico
2.4 Resumen
2.5 Ejercicios
2.6 Código fuente del capítulo

3. Vistas
3.1 ¿Por qué usar una vista?
3.2 Convención en las Vistas
3.3 Vistas fuertemente tipadas
3.4 View Model
3.5 Agregar un Vista
3.6 El motor de vista Razor
3.7 Resumen
3.8 Ejercicios
3.9 Código fuente del capítulo

4. Modelos
4.1 Modelando la Tienda de Música
4.2 Crear el administrador de almacenamiento
4.3 Resumen
4.4 Ejercicios
4.5 Código fuente del capítulo

5. Los HTML Helpers
5.1 El tag form
5.2 HTML Helpers
5.3 Otros helpers
5.4 Rendereando los Helpers
5.5 Resumen
5.6 Ejercicios
5.7 Código fuente del capítulo

6 Membresía, Autorización y Seguridad
6.1 Usando el atributo Authorize
6.2 El atributo Authorize para usarlo con roles
6.3 Cuando usar roles y cuando usuarios
6.4 Login externo con OAuth2 y OpenID
6.5 Puntos de seguridad en una Aplicación Web
6.6 CustomErrors en el web.config
6.7 Usando la opción Retail
6.8 Usar un logging dedicado
6.9 Resumen de las típicas amenazas y links
6.10 Resumen
6.11 Ejercicios
6.12 Código fuente del capítulo

7 Data Annotations y Validaciones
7.1 Data Annotations para una venta
7.2 Lógica de validación personalizada
7.3 Mostrar y Editar Annotations
7.4 Resumen
7.5 Ejercicios
7.6 Código fuente del capítulo

8 Ajax
8.1 jQuery
8.2 Ajax Helpers
8.3 Validación en el lado del Cliente
8.4 Detrás los helpers
8.5 Mejorando el rendimiento de Ajax
8.6 Resumen
8.7 Ejercicios
8.8 Código fuente del capítulo

9 Routing
9.1 ¿URL o URI?
9.2 Introducción al Routing
9.3 Como las rutas generan una URL
9.4 Como las rutas vinculan las URL a un action
9.5 Rutas-constraints personalizados
9.6 Usando Routing con Web Forms
9.7 Resumen
9.8 Ejercicios
9.9 Código fuente del capítulo

10 NuGet
10.1 Introducción a NuGet
10.2 Actualizando NuGet
10.3 Agregando una librería como package
10.4 Creando packages
10.5 Publicando packages
10.6 Resumen
10.7 Ejercicios
10.8 Código fuente del capítulo

11 Web API
11.1 Definición de una Web API
11.2 Comenzando un proyecto Web API
11.3 Escribiendo un controlador API
11.4 Configurando Web API
11.5 Agregando rutas a la Web API
11.6 Binding de Parámetros
11.7 Filtros en los request
11.8 Habilitando Dependency Injection (DI)
11.9 Help Pages y Swagger
11.10 Traceando la aplicación
11.11 Ejemplo de una Web API
11.12 Resumen
11.13 Ejercicios
11.14 Código fuente del capítulo

12 Single Page Applications (SPA) con AngularJS
12.1 Entendiendo y configurando AngularJS
12.2 Creando la Web API
12.3 Construyendo la aplicación y módulos
12.4 Resumen
12.5 Ejercicios
12.6 Código fuente del capítulo

13 Inyección de dependencias en MVC y Web APIs
13.1 Patrones de diseño de software
13.2 Resolutor de dependencias en MVC
13.3 Resolución de dependencias en Web API
13.4 Resumen
13.5 Ejercicios
13.6 Código fuente del capítulo

14 Test Unitario
14.1 Entendiendo las Pruebas Unitarias y el Test-Driven Development
14.2 Construyendo un proyecto de Pruebas Unitarias
14.3 Tips para Pruebas Unitarias de MVC y de Web API
14.4 Resumen
14.5 Ejercicios
14.6 Código fuente del capítulo

15 Anexo: Descarga de Fuentes GitLab
15.1 Previa: ¿GitHub vs GitLab vs Bitbucket?
15.2 Descarga de fuentes de GitLab con Visual Studio
15.3 Descarga manual desde Sitio GitLab.com

Respuestas a ejercicios

miércoles, 30 de agosto de 2017

The State of C# en Español (El estado de C#)

Traducción al español del excelente paper llamado The State of C# publicado por Progress (los dueños del producto Telerik), el 25 de agosto de 2017. Tiene algo de publicidad a su producto estrella, hay que admitirlo, pero tiene muchas cosas interesantes de C#, del mercado, de Visual Studio y de las últimas características en la versión 7.0. Escrito por originalmente por Kevin Griffin. Traducido por Hernaldo González.

Resumen

Imagina que eres un desarrollador en los años 90. Tienes una variedad de herramientas a tu disposición: C++, Java, Delphi, Visual Basic, FoxPro y otros. Sabemos que cada uno de esos lenguajes tiene cosas muy buenas, pero también sus propias fallas.

Al comienzo del año 2000, Microsoft públicamente anunció sus planes para su .NET Framework, el cual era una serie de librerías administradas. Este nuevo framework, sin embargo, necesitaba un nuevo lenguaje. Se le llamó en un inicio "Cool", C# había nacido.

C# fue originalmente diseñado para ser abierto, pero bajo estándares. Cada versión de C# es aprobada no sólo por Microsoft, sino por ECMA International y la International Organization for Standardization (ISO). ¿Qué quiere decir esto para el desarrollador? Cualquiera puede hacer un compilador de C# para sus sistemas operativos. El Mono Project, el cual es una implementación tipo código abierto del compilador C# y del .NET Framework, es el perfecto ejemplo del C# estándar en acción.

C# ha tenido 5 revisiones importantes desde su versión 1.0 en el año 2002. En este tiempo ha tenido varias mejoras importantes como: generics, métodos y tipos anónimos, propiedades automáticas, expression trees, dynamics, métodos asíncronos y compilación como servicio. No es una lista detallada, pero es para ver como C# fue creciendo a través de los años.

Ahora, si eres ingeniero informático, analista de sistemas y vas en el último año de la carrera o estás recién egresado y estás buscando el norte en la industria de la informática, la pregunta que deberías hacerte a ti mismo es: "¿Debería aprender C# para tenerlo dentro de mi portafolio de conocimientos"?

Carrera de un desarrollador C#

En la encuesta anual de StackOverflow del año 2016, situó a C# como el 5to lenguaje que deberías conocer. Además se les consultó a los usuarios que lenguaje les encantaba, cuales conocían y cuales quisieran usar. Si miras el lenguaje que más les encantaba, temían o querían trabajar (Most Loved, Dreaded, and Wanted) y cual consideraban muy tecnológico (Top Tech), C# estaba en ambos listados del top.

¿Qué hay de los otros lenguajes de la lista? Mientas muchos desarrollan en JavaScript, Android o Java, ninguno de ellos cae en la categoría que los desarrolladores les encanta trabajar con ellos. En cambio C# si.

¿Qué tal el sueldo promedio de un desarrollador C#? Un desarrollador en un trabajo horario de oficina full time, gana 95 mil dólares al año (N. Del T. que en pesos Chilenos serían 5 millones mensuales, wuau, cambio al 25 de agosto 2017). A menudo en este sueldo se incluye que también sabe JavaScript y otros cosas. La única forma de ganar más, digamos unos 105 mil dólares al año (5.6 millones mensuales Chilenos) requiere que el desarrollador sepa tecnologías basadas en la nube como Reac o Redis.

Si hablamos de un desarrollador front-end, el sueldo promedio baja a 75 mil dólares al año (3.9 millones mensuales Chilenos). Lo que si, la encuesta no indica si es un desarrollador Web o también incluye aplicaciones de escritorio.

Un desarrollador C# especializado en los datos y con conocimientos de Machine Learning (N. Del T. Librerías que simulan el pensamiento humano como aplicaciones predictivas o de reconocimiento de caras en imágenes), puede ganar hasta 85 mil dólares al año (4.5 millones mensuales Chilenos). Los mismos números aplican para un desarrollador Android cuyo lenguaje principal es C#. Incluso lo que gana un desarrollador iOS o un desarrollador Android, no se diferencia mucho de lo que gana un desarrollador C# que implemente para ambas plataformas usando Xamarin.

Herramientas

La herramienta más conocida por los desarrolladores de C# es el IDE Visual Studio. Es importante saber que que Visual Studio no está limitado solo a C#, de echo, cuando se estaba creando, Visual Studio se usaba para desarrollos de Visual Basic o C/C++.

Actualmente se puede usar para diversos lenguajes como Visual Basic, C/C++, F#, C#, Python, Ruby, HTML, JavaScript y otros.

Esta variedad de lenguajes soportados es posible gracias al sistema de plugins que tiene el editor. Permite que un desarrollador de Microsoft, o incluso de la misma comunidad, desarrolle complementos que funcionen correctamente con los subsistemas de Visual Studio.

Hay muchas características de Visual Studio que hace que los desarrolladores no se vayan. En primer lugar, está el editor de código de clase mundial. A medida que codificas, a menudo eres asistido directamente por Visual Studio a través de una función llamada Intellisense. Esta función analiza el código después de cada pulsación de tecla y, a menudo, puede proporcionar el autocompletado de variables y métodos. Esta previsión inteligente está diseñada específicamente para el lenguaje que estás desarrollando, lo que significa que Intellisense C# e Intellisense CSS son experiencias diferentes que resuelven el mismo tipo de problema. Las herramientas de depuración que tiene integradas te ayudan a reducir problemas específicos, y permiten por ejemplo, hacer un "paso a paso" de las líneas código.

¿Habrá una característica que le falte a Visual Studio que haga que mejore tu experiencia de desarrollo?
Hay un gran grupo de proveedores en la industria que desarrollan herramientas para aumentar y mejorar la experiencia de desarrollo usando Visual Studio. Por ejemplo, Telerik de la empresa Progress es el creador de JustCode, una extensión de Visual Studio que hace que la codificación sea más rápida y fácil añadiendo más inteligencia y accesos directos al editor de código de los que ya vienen por defecto en el IDE.

En versiones antiguas de Visual Studio debías incluso pagar por su uso, o podías usarlo sólo si estabas suscrito a MSDN. Desde Visual Studio 2015, Microsoft estrenó Visual Studio Community Edition, una versión gratuita de Visual Studio que a la vez permite usar cualquier plugin que desees instalar. A diferencia de los anteriores Visual Studio Express, cualquier aplicación creada por un desarrollador individual ahora puede ser usada de forma comercial.

Visual Studio es el Roll Royce de los entornos de desarrollo. El gran obstáculo que alegan algunos desarrolladores es que es una herramienta poderosa pero sólo para desarrollar aplicaciones que funcionan en Windows. El mercado actualmente está lleno de herramientas que permiten desarrollar para Linux u OSX.

En una conferencia del año 2016, Microsoft anunció el editor Visual Studio Code. Visual Studio (VS) Code puede ser usado para codificar para que funcione en un ambiente Windows, OSX o Linux.
Aunque sea una herramienta más liviana, VS Code soporta varias cosas que tiene Visual Studio. Tiene un editor con estilos de colores según el lenguaje, ¡soportando C#, C++, F#, Elixir, Docker, Python, Ruby and otros!

VS Code no ofrece un Intellisense completo que si encontrarías en Visual Studio. Sin embargo, VS Code proporciona una robusta funcionalidad de code completion para varios lenguajes.
Para los desarrolladores que trabajan con C#, Node.js y Python, hay soporte de depuración incorporado adicional.
Al combinar la ligera arquitectura que posee y el soporte multiplataforma, VS Code es una excelente herramienta para que un desarrollador comience con C#.

Por último, si ya eres fan de otro editor que no sea VS Code, asún estás con suerte. Los desarrolladores de Microsoft junto con muchos colaboradores externos, han construido un plugin increíble llamado Omnisharp. Con Omnisharp, puedes inyectar Intellisense de Visual Studio directamente en el editor de tu preferencia.
Actualmente, Omnisharp es compatible con Atom, Brackets, Emacs, Sublime Text y Vim. También es el motor que potencia las características de code completion de VS Code.

El objetivo subyacente a todas estas herramientas, independientemente de cuál de ellas elijas utilizar, es que si eres un desarrollador que trabaja con C# y .NET Framework, tu experiencia sea inigualable.

Plataformas

¿Qué hemos visto hasta ahora? C# es un lenguaje basado en estándares donde sus características han crecido exponencialmente en los últimos 15 años. Combina eso con un conjunto de herramientas de desarrollo de clase mundial y te estarás preparando para una gran carrera de desarrollo centrado únicamente en Windows, ¿correcto?

¡De ningún modo! Con toda esa inversión de tiempo y energía en C#, no hay límite para el número de plataformas que podrás desarrollar. A continuación, cubriremos algunos de los entornos más comunes que los desarrolladores de C# pueden implementar.

Escritorio

La creación de aplicaciones para Windows siempre ha sido un elemento básico para el desarrollador de C#. Al principio, nuestras aplicaciones se escribieron utilizando Windows Forms (WinForms). WinForms, combinado con las potentes herramientas de diseño dentro de Visual Studio, permite a un desarrollador rápidamente previsualizar la apariencia de una aplicación. La lógica de negocio para las interacciones de los controles se hizo simplemente mediante el uso de eventos.

WinForms también podía ampliarse aún más mediante el uso de suites de terceros, como Telerik WinForms. Estas suites de control ofrecen una amplia variedad de características que faltan en los controles de base proporcionados por defecto. Los controles tales como grids, gráficos y más, podrían fácilmente demorar meses de desarrollo a un equipo de desarrolladores si lo hicieran desde cero, e incluso así, estos controles no serían tan ricos en funciones como lo que se obtiene con la UI de Telerik para WinForms.

Un efecto secundario de tener un flujo de trabajo que se inicia con la etapa de diseño como es en WinForms, es que las aplicaciones comenzaron a crearse con ese mismo look & feel. El término "gris acorazado" fue muy conocido en toda la industria porque reflejaba cómo se veían todas las aplicaciones de WinForms. Desviarse de la norma era difícil, incluso con la ayuda de herramientas de terceros.

Con el lanzamiento de C# 3.0, Microsoft anunció el Windows Presentation Foundation, o WPF. Esto hizo repensar el proceso de construcción de aplicaciones centradas en Windows. En lugar de un enfoque centrado en el diseño, los desarrolladores podrían construir las interfaces de usuario con un nuevo lenguaje llamado XAML.

Las aplicaciones construidas con WPF seguían usando C# tras la cortina. Sin embargo, los desarrolladores ahora tenían la capacidad de construir interfaces más robustas tan fácilmente como si fuera HTML.

Aquellos que querían una experiencia de diseño similar a WinForms podría utilizar Blend, una herramienta de diseño similar a Photoshop, pero especializada en la generación de XAML. Al igual que con WinForms, un desarrollador que no quería reinventar la rueda podía utilizar una de las asombrosas suites de control de terceros disponibles, como la UI de WPF.

La liberación de Windows 10 abrió un nuevo mundo de oportunidades para los desarrolladores de Windows. Windows ya no es sólo un sistema operativo de escritorio. Se puede ejecutar en escritorios virtuales, pero también sobre dispositivos Windows Mobile, Xbox One y Hololens.

Con la llegada de Universal Windows Platform (UWP) se creó un entorno en el que un desarrollador podía crear una única aplicación que podía ejecutarse de forma nativa en Windows 10, pero también con unos pocos ajustes, realizar implementaciones para Windows 10 Mobile y Xbox One. Debajo de la alfombra, hay un potente subsistema accesible a través de C#, C++, Visual Basic y JavaScript. Las tecnologías de WPF y XAML se combinan fácilmente.

Web



Ahora, volvamos nuestra atención al módulo Web, más conocimo como ASP.NET. En los últimos años, ha habido tres revoluciones por el lado de ASP.NET.

En los primeros días de .NET y WinForms, Internet estaba todavía en su infancia. El concepto de constriur una aplicación comercial basada en la web era relativamente nuevo, y las herramientas no estaban diseñadas para manejar aplicaciones en esta escala.

¿Cómo una compañía enfocada en desarrolladores como Microsoft toma millones de programadores con conocimiento de WinForms y patrones de diseño similares y los convierte en desarrolladores web? La respuesta está en el nacimiento y la liberación inicial de ASP.NET WebForms.

Cualquier desarrollador que tuviera experiencia con WinForms podría traducir rápidamente esas habilidades a la web. Después de todo, era similar a WinForms, una aplicación WebForms se iniciaba con un diseño y el control se hacia mediante el uso de eventos (event handlers).

Su núcleo fue, una vez más, C#.

La web ha madurado mucho desde el inicio de WebForms. En 2007, ASP. NET se convirtió en la versión inicial de ASP.NET MVC, una implementación del patrón Model View Controller construido en la capa superior de ASP.NET. Los desarrolladores que querían un entorno más puro para crear aplicaciones web podrían usar ASP.NET MVC, así podían crear aplicaciones que no tuvieran esa sobrecarga de ASP.NET WebForms.

Hubo una falla fundamental en la creación de aplicaciones ASP.NET: su estrategia de deploy se centró únicamente en el uso de Internet Information Services (IIS) sobre un servidor Windows. El hosting basado en Windows es a menudo más costoso de configurar y mantener frente a Linux o sistemas operativos similares. El ecosistema de ASP.NET era principalmente para la empresa, que podía pagar los costos de licencias, o para sitios de bajo tráfico que podrían funcionar eficientemente dentro de ambientes compartidos.

A finales de 2015, ASP.NET pasó por otro "renacimiento" con la introducción de ASP.NET Core (y .NET Core framework).

A diferencia de su predecesor, ASP.NET Core es opensource, una plataforma abierta que rearma el cómo funciona ASP.NET. Todavía estamos en los primeros días de esta plataforma, pero imagina ser capaz de construir una aplicación web completa en ASP.NET que se puede implementar rápida y fácilmente a Windows, Linux o incluso OSX sin ningún cambio de código.

Actualmente, los únicos idiomas soportados en ASP. NET Core son C# y F#, mientras que Visual Basic ya lo es desde el inicio.

Mobile



Sabemos que C# es bueno para aplicaciones web y de escritorio, pero todos sabemos que para móviles no es buena ¿cierto?

Como dijimos anteriormente, con Universal Windows Platform, puedes generar aplicaciones para Windows 10 Mobile con unos simples cambios en la configuración. Ahora si miramos el mercado estadounidense vemos las ventas del año 2016 para Windows Phone y estás apenas alcanzan el 3% del total. La mayoría de las ventas las tiene iOS y Android.

Una falla en la industria es que si quieres desarrollar aplicaciones iOS, necesitas aprender Objective-C o Swift. Si deseas desarrollar aplicaciones para Android, necesitas saber Java.

En febrero de 2016, Microsoft compró Xamarin, un framework para la construcción de aplicaciones iOS y Android sobre la capa superior de la Plataforma Mono.

El truco de Xamarin es que puedes construir para Android nativo, iOS nativo e incluso aplicaciones nativas de Windows usando la misma base hecha en C#. Ninguna otra plataforma puede presumir de dichas características. No siquiera las soluciones móviles multiplataforma como PhoneGap o WebView, donde la experiencia es un simple shell a la cual las aplicaciones son inyectadas. Xamarin ofrece a los desarrolladores acceso a la misma apariencia y la sensación que los usuarios de iOS y Android esperan ver.

Entonces, recapitulemos todas las plataformas que un desarrollador de C# podría encontrarse en el mercado. En primer lugar, para el tipo escritorio, puede trabajar en aplicaciones Windows Forms, Windows Presentation Foundation y la nueva Universal Windows Platform. La siguiente es la web, donde una aplicación podría ser construida con ASP.NET WebForms o ASP.NET MVC. Los desarrolladores más astutos ahora pueden incluso usar ASP.NET Core, lo que les permite trabajar no sólo en Windows, sino en Linux u OSX. Por último, el mercado móvil se alcanza mediante el uso de Xamarin para crear aplicaciones móviles multiplataforma que comparten una base de código común escrita en C#.

Quince años de innovación y de nuevas características

Hasta ahora, hemos hablado mucho del estado actual del ecosistema de C#. Hay fácilmente 15 años de plataformas y sistemas construidos sobre C#. Sin embargo, aún no ha alcanzado su límite. Más bien, toda esta innovación es posible porque C# continúa madurando y creciendo como un lenguaje.

¿Cuáles son algunas de las principales características que ha tenido en 15 años de innovación? Si ya eres un desarrollador de C#, las sabrás de memoria.

Algo tan simple como Generics, Partial Types y Nullable types no existían hasta la versión C# 2.0. En la versión C# 3.0 se introdujeron Extension Methods, Expression trees, Lambda expression y otras cosas. Estas características permitieron que existiera LINQ (Language Integrated Query), una característica que cambió bastante la forma en que los desarrolladores de C# trabajaban la data.

C# 4.0 cambió radicalmente la forma en que los desarrolladores usaban los tipos, introduciendo dynamic types a un lenguaje de tipo estático. Métodos asíncronos se agregaron en C# 5.0, lo que proporcionó a los desarrolladores una forma de construcción de aplicaciones más eficientes, permitiendo que las tareas largas de ejecución fueran asíncronas.

Por último, en C# 6.0, vimos el compilador Roslyn (Compilador como servicio), que proporciona un compilador C# a los desarrolladores para que se utilizara en tiempo de ejecución. También proporciona herramientas de análisis de código y potencia muchas de las características del desarrollador integradas en Visual Studio.

Esta lista no es la más completa, pero proporciona un amplio panorama de cómo C# ha madurado a lo largo de los años. Si eres nuevo en C#, tómate el tiempo para revisar en detalle esta lista de características.


¿Qué hay de nuevo en C# 7.0?

Ahora, cambiemos el enfoque y hablamos de lo que viene a nivel de código. Respondamos la pregunta: "¿Qué hay de nuevo en C# 7.0?"

Es importante tener en cuenta que los siguientes ejemplos y conceptos están todavía en revisión. Su contexto y sintaxis aún se está desarrollando, y no hay garantía de que estas características no se cambien o eliminen en el futuro.

Out Variables (Variables de salida)

La palabra out no es nueva en C#. Si declaras una variable dentro de un método que tenga un parámetro con un out, estás indicando al compilador que estás esperando que el método setee ese valor en tiempo de ejecución.
public void TestMethod()
{
  string fullName;
  GetPersonName(“Kevin”, “Griffin”, out fullName);
}
Comúnmente, el problema es que tienes que declarar la variable antes de hacer la llamada al método con out. En C# 7.0, está el concepto de variables out, lo que te ahorrará un par de pulsaciones de teclas ya que declarará la variable en línea.

El ejemplo anterior puede ser refactorizado en este:
public void TestMethod()
{
  GetPersonName(“Kevin”, “Griffin”, **out string fullName**);
}
En paralelo, si no sabes el tipo del parámetro, puedes cambiar el tipo del parámetro por var.

Pattern Matching (Coincidencia de patrones)

En C# 7.0 se da un fuerte énfasis en la característica de Pattern Matching. Básicamente consiste en que C# permite buscar algún patrón o ámbito para realizar cierta operación. Como verás más adelante también permite extraer un valor si coincide con el patrón definido.

El siguiente ejemplo muestra claramente como funciona Pattern Matching con la instrucción Switch:
switch(person)
{
  case CEO ceo:
    CallCeo(ceo);
    break;
  case Manager salesManager when (salesManager.Department == “Sales”):
    CallSalesManager(salesManager);
    break;
  case Manager other
    CallManager(other);
    break;
  default:
    WriteLine(“Standard employee”);
    break;
  case null:
    throw new ArgumentNullException(nameof(person));
}
Recorramos la instrucción Switch paso a paso. El objeto "Persona" se validará con la instrucción Switch y vamos a evaluar dicho objeto de forma distinta dependiendo del tipo y datos que contenga el mismo.

En el primer case, si Persona coincide con el objeto CEO, hará el match y retornará el handler respectivo. En una instrucción evaluaremos si es manager pero a la vez tiene un departamento "sales", entonces llamaremos a una función. Cuando se usa when se evalúa contra el objeto salesManager recién generado. En la siguiente condición queremos evaluar si el objeto es sólo un manager.

Aquí hay dos escenarios. El caso más común es usar el case default, donde tenemos un objeto que no coincide con ninguno de los patrones anteriores. Al final, también hay un caso null que asegurará que el objeto pasado tenga un valor, y lanzará una excepción ArgumentNull cuando esto suceda.

Is-Expressions (Expresiones IS)

Basándonos en la explicación anterior acerca de variables out, podemos usar variables de patrón para crear variables a demanda dentro de un bloque de código.
public void LoadPerson(object age)
{
  if (age is int ageInt || (age is string ageString &&
  int.TryParse(ageAsString, out ageInt)))
  {
    // ageInt contains a value.
  }
}
Mirando el código, tenemos un caso donde la "edad" de una persona puede entrar en nuestra aplicación como un string o integer. Si la edad es integer, inmediatamente caerá en esta condición. Pero, si edad es un string, tendremos que realizar una conversión utilizando el método int.TryParse.

Como sabemos, el mayor problema con TryParse es que se debe definir la variable antes de la llamada al método TryParse. En C# 7.0, esto ya no es necesario. Puede crear la variable a demanda si el método TryParse retorna True.

Tuples (Tuplas)

En C# 3.0 se agregó el tipo de referencia Tuple<>. ¿Qué es una Tupla? En pocas palabras, una Tuple es una colección de valores.

Imagina el ejemplo anterior donde cargamos la información de una persona. Hay varias formas en que podemos devolver los datos de un método:
public Person LoadPerson(){}

public Tuple LoadPerson(){}
El primer ejemplo devuelve un fully qualified type (N. del T. el objeto completo) y dependiendo del caso, esto es perfectamente aceptable.
Sin embargo, ¿qué pasa si el tipo Persona es descartable? Vas va a recuperar datos, utilizarlo y tirarlo. Crear el tipo Persona para un solo método es un poco engorroso.

El segundo ejemplo utiliza el tipo genérico Tuple<> para recuperar la misma información. ¿Cómo sería la llamada a LoadPerson?
public void Foo()
{
  var person = LoadPerson();
  var fullName = $"{person.Item1} {person.Item2}";
}
Para un sencillo Tuple de dos valores, estamos empezando a desviarnos del camino de la legibilidad. ¿Qué se supone refleja el elemento 1 o el artículo 2? ¿Es su nombre y apellido respectivamente? ¿Podría ser el nombre y la dirección? ¿Ciudad o país?
No hay mucho que intuir porque Item1 y Item2 son tan explicativos como "a" o "b".

Con C# 7.0 vamos a tener acceso a Tuplas reales de una manera más cercana a lenguajes funcionales como F#. La firma de método LoadPerson() se refactorizaría así:
public (string firstName, string lastName) LoadPerson(){};
Observa la nueva sintaxis del tipo de retorno. El tipo de retorno Tuple actúa de forma similar al patrón utilizado para declarar los parámetros de una función. Por último, si deseas crear una Tuple en línea, se puede hacer mediante el uso de la nueva palabra clave.
return new (string firstName, string lastName) {firstName = "Kevin", lastName = "Griffin"};
Separador de dígitos

Archiva de esta característica como "útil pero algo loco". ¿Cuántas veces has creado un literal numérico y tuvo que contar el número de dígitos para asegurarse de que introdujo el número correcto?

Por ejemplo:
long Gigabyte = 1048576;
El número se ve aparentemente inofensivo, pero si se te olvida poner un dígito estarías en problemas. Normalmente, si alguien escribiera este número a mano, sería representado como 1,048,576. Las comas ayudarían a dictar la posición de los dígitos.

Los nuevos "separadores de dígitos" de C #7.0 te permiten hacer lo mismo, excepto que, en lugar de usar una coma, puedes usar el underscore.
long Gigabyte = 1_048_576;
El compilador ignorará los underscore en tiempo de construcción.

Throw Exceptions

Escribir código defensivo a menudo significa generar un montón de excepciones. En C# 7.0, hay algunos nuevos ajustes en donde puedes lanzar una excepción.

Por ejemplo, considera este método existente:
Public string GetName (persona persona)
{
  if (person.Name == null)
    throw new Exception("Name not found");
  return person.Name;
}
Con los nuevos cambios que dijimos, ese método puede ser rápidamente refactorizado en:
public string GetName(Person person)
{
  return person.Name ?? throw new Exception("Name not found.");
}
Non-Nullable Reference Types (Tipos no nulos)

Una de las excepciones más comunes lanzadas en las aplicaciones .NET es la Null Reference. ¿Cuál es el problema? Los tipos de referencia en C# son nullables por defecto. Esta condición previa causa que los desarrolladores aseguren su código a prueba de balas para evitar que se esté tratando de acceder a una variable que potencialmente podría ser null en tiempo de ejecución.

Para tipos de valores, como int o DateTime, no es posible que el valor sea nulo a menos que las definas como un tipo Nullable.
  int? intCouldBeNull;
  DateTime? nullableDateTime;
¿Qué pasa si los diseñadores de C# simplemente cambian los valores predeterminados? Todos los tipos de referencia ya no serían null por defecto, entonces tendrías que setear explícitamente una variable que pueda ser null.
Ok...pero romperías 15 años de código C#.

Como alternativa, ¿qué pasaría si pudiéramos declarar explícitamente que un tipo de valor sea "no null?" En C# 7.0, el operador "!" se usará para indicar que una variable no puede ser null.
string! nonNullableString;

Person! nonNullablePerson;
Utilizando el operador "!", le estamos diciendo a C# que nonNullableString y nonNullablePerson, por lo tanto, NUNCA deben ser null. En el caso de que se pase un valor null, esto debería causar un error o una advertencia del compilador.

Fundación estable, carrera estable

Si eres nuevo en la industria o un profesional experimentado, tienes la gran oportunidad de decidirte por alinearte con diferentes tecnologías que vayan contigo. C# ha mostrado a través del tiempo para ser no sólo una plataforma estable, sino un lenguaje que ha madurado y crecido a lo largo de los años para adaptarse a las cambiantes necesidades de los desarrolladores.
La última versión, C# 7.0, se encuentra en revisión. Se jacta de un conjunto de nuevas características diseñadas para hacer el código más fácil de leer y escribir.

StackOverflow, el recurso más confiable para desarrolladores de Internet en la actualidad, nos dice que C# es una de las cinco plataformas tecnológicas más importantes del mundo. Además, si miramos la encuesta de las tecnologías que los desarrolladores les encanta usar, sólo C# está en ambas listas. Ni siquiera con Java, que también se le considera uno de los mejores lenguajes de la industria, se puede decir que les encanta a los desarrolladores. Finalmente como guinda de la torta, un desarrollador que se especializa en C# puede, en promedio, ganar entre 85 a 95 mil dólares al año.

C# es una triple amenaza: es amado, es demandado y se paga bien.
Tampoco un desarrollador C# se limita a una vida construyendo las famosas ventanas grises de Windows. Como hemos comentado anteriormente, C# te permite crear aplicaciones de Windows en la nueva Universal Windows Platform, o puede usarse para construir aplicaciones más antiguas con Windows Forms. Los desarrolladores web pueden ahora crear sitios completamente funcionales que se ejecutan en Windows Server, Linux u OSX. Xamarin es un framework para que los desarrolladores C# construyan código de forma compartida y que está orientado a la creación de aplicaciones móviles nativas.

Las aplicaciones de clase mundial necesitan entornos de desarrollo de clase mundial. Durante más de 15 años, Visual Studio ha sido el Cadillac de los IDE. Con características como Intellisense, un sorprendente depurador y un rico ecosistema de add-ons, Visual Studio continúa impulsando el concepto de lo que un IDE debería ser.

Los desarrolladores que no necesitan todo el poder de Visual Studio, o quieren una experiencia similar en OSX o Linux, pueden usar Visual Studio Code. Es de código abierto y multiplataforma. Te ofrece una increíble experiencia de codificación en un pequeño paquete. Si ya tienes un editor y no te convence cambiarte, entonces puedes usar el complemento Omnisharp que te permite usar la experiencia Intellisense de C# en casi cualquier otro editor.

¿Es una buena decisión usar C#? La evidencia anterior habla maravillas sobre la viabilidad a largo plazo del lenguaje, el gran ecosistema de herramientas de desarrollo y los diversos nichos donde pueden aplicarse tus conocimientos. No importa si estas orientado a desarrollo de escritorio, web, móvil, C# es una apuesta segura para los próximos años.

lunes, 30 de mayo de 2016

Tutorial de uso de la librería Winnovative HTML to PDF con C# y MVC

Hola, hace rato que no publicaba nada...Bueno hoy veremos como usar la librería Winnovative HTML to PDF Converter Library usando C# y MVC .Net. El tema nació en que buscamos una forma buena y elegante de imprimir un PDF a partir de un sitio web hecho en MVC .Net, pudiendo personalizar el PDF, tipo de hoja, orientación, que permita imprimir un sitio que haga request Ajax y tenga imágenes.

Personalmente conozco 3 herramientas que permiten generar PDF desde C# y me quedo con Winnovative por lo anterior dicho:


El tutorial fue probado con IE 11, Chrome 50.0.2661.102, FireFox 37.0.1.

Requisitos


  • Tener la librería Winnovative HTML to PDF Converter Library v12.16, descargarla de http://www.winnovative-software.com/download.aspx. En mi caso bajé Winnovative HTML to PDF Converter Library Optimized for 64-bit ya que tanto los PC de los desarrolladores como servidores son de 64 bit.
  • En mi caso usaré una versión comprada HTML to PDF Converter Redistributable License cuyo valor es de 1200 USD ya que permite instalarlo en N Servidores, incluyendo en PC de desarrolladores y en servidores de clientes. No es obligación tener la licencia para el ejemplo, lo que sí, saldrán tus PDF con la frase Winnovative PDF Tools Demo en la parte inferior:
  • Para el ejemplo usaré Visual Studio 2013 con C#, MVC 4 y Framework 4.0
NOTA: la librería no es compatible con el Framework .Net 3.5, si con las versiones 2.0, 4.0 y 4.5.

Paso a paso


Pasos generales

  • Crear un proyecto MVC 4 usando C# con Framework 4.0.
  • Vamos a instalar la librería Winnovative "a la antigua", es decir manualmente, ya que se puede instalar por NuGet. Descomprimir el archivo descargado WnvHtmlToPdf-v12.16-x64.zip, en la raíz del zip estarán estos tres archivos que son compatibles si usas al Framework 4.0: wnvhtmltopdf.dll, wnvinternal.dat y Help.chm.
  • Si usas el Framework 2.0 debes copiar los 3 archivos de la carpeta NET_2.0 (wnvhtmltopdf.dll, wnvhtmltopdf.xml y wnvinternal.dat) al directorio bin de tu proyecto web. El XML contiene sólo la documentación de los fuentes.
  • Si están con Framework 4.0. debes copiarlos a una nueva carpeta LIB. Preocúpate los archivos que no estén chequeados como "solo lectura".
  • El archivo wnvhtmltopdf.dll dentro de LIB debes referenciarlo desde tu proyecto MVC .NET.
  • Agregar en el HomeController el using:

    //HomeController.cs
    using Winnovative;
  • Si usas la Key, y la agregas en el código, no se verá el mensaje "Winnovative PDF Tools Demo":

    //HomeController.cs
    htmlToPdfConverter.LicenseKey = "keyComprada";

Imprimir a pdf una vista o página externa

  • Crear el vista principal con un botón dentro de un Form que llamará a la impresión, por ejemplo:

    <!-- Index.cshtml -->
    @using (Html.BeginForm("ImprimeVistaExterna", "Home", FormMethod.Post))
    {
    <input type="submit" id="impresion2" name="impresion2" value="imprimir otra vista completa" /gt;
    }
  • Creas el Action y la Vista Externa a ser llamada. Esta vista puede tener imágenes, o un llamado Ajax a otra Vista ¡y todo eso se verá impreso!. Esa es la gracia de la librería ya que mucha no hacen eso, esta ejecuta el request con todo lo que conlleva, llamados Ajax, JS, estilos, imágenes y todo el resultado del HTML final, es el que imprime. En mi caso incluso uso la librería Kendo MVC para mostrar un TreView y esta igual se imprime:

    <!-- VistaExterna.cshtml -->
    @{
    ViewBag.Title = "Impresion ejemplo";
    }

    <h1>Vista demo de impresión</h1>

    @(Html.Kendo().TreeView()
    .Name("LinksTreeView")
    .Items(items =>
    {
    items.Add()
    .Text("Home")
    .Action("Index", "Home");
    items.Add()
    .Text("About")
    .Action("About", "Home");
    items.Add()
    .Text("Contact")
    .Action("Contact", "Home");
    })
    )

    <img src="~/Images/pacman.png" />

    <div id="contenedor"></div>

    <script>
    $(document).ready(function () {
    $.ajax({
    url: "/Home/VistaExternaAjax",
    type: 'GET',
    datatype: 'html',
    success: function (data) {
    $("#contenedor").html(data);
    }
    });
    });
    </script>
  • Por último creamos la vista externa (la más externa) que es llamada desde al Ajax anterior:

    <!-- VistaExternaAjax.cshtml -->
    <h1>Otra Vista externa invocada por ajax</h1> <h2>holaaa</h2>
  • Si abrimos la Vista externa en el navegador se verá así:
  • Creas el Action ImprimeVistaExterna dentro del controlador Home:
    //HomeController.cs
    [HttpPost]
    public ActionResult ImprimeVistaExterna()
    {
    // Create a HTML to PDF converter object with default settings
    HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter();
    
    // Set HTML Viewer width in pixels which is the equivalent in converter of the browser window width
    htmlToPdfConverter.HtmlViewerWidth = 1024;
                
    htmlToPdfConverter.LicenseKey = "tuKey"; //propiedad opcional
    htmlToPdfConverter.HtmlViewerHeight = 768;
    
    // Set PDF page size which can be a predefined size like A4 or a custom size in points 
    // Leave it not set to have a default A4 PDF page
    htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.Letter;
    
    // Set PDF page orientation to Portrait or Landscape
    // Leave it not set to have a default Portrait orientation for PDF page
    htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
    
    // Set the maximum time in seconds to wait for HTML page to be loaded 
    // Leave it not set for a default 60 seconds maximum wait time
    htmlToPdfConverter.NavigationTimeout = 4;
    
    // Set an adddional delay in seconds to wait for JavaScript or AJAX calls after page load completed
    // Set this property to 0 if you don't need to wait for such asynchcronous operations to finish
    htmlToPdfConverter.ConversionDelay = 1;
    
    string url = "http://localhost:50422/Home/VistaExterna";
    
    // Convert the HTML page given by an URL to a PDF document in a memory buffer
    byte[] outPdfBuffer = htmlToPdfConverter.ConvertUrl(url);
    
    // Send the PDF file to browser
    FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
    fileResult.FileDownloadName = "ImpresionVistaExterna.pdf";
    
    return fileResult;
    }
    
  • Notar que en url defines la ruta que se imprimirá. Se le hará un request a dicha ruta. Puede ser cualquier URL, incluso una externa como www.google.com
  • Con htmlToPdfConverter.NavigationTimeout se define el tiempo máximo de espera a dicho request. Yo usaré 4 segundos.
  • Con fileResult.FileDownloadName le defines el nombre del archivo PDF de salida.
  • Con htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.Letter defines el tipo de papel, en este caso tipo Carta.
  • Con htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait defines la orientación del documento.
  • Al hacer clic en "Imprimir página Externa", se bajará el PDF resultante y su lo abres es el mismo contenido HTML que tiene la vista externa:


Imprimir a pdf una sección de la página actual

  • La sección debe ser una Vista Parcial, así que creas la vista Seccion.cshtml:

    <!-- Seccion.cshtml -->
    @{
    ViewBag.Title = "Seccion ejemplo";
    var nombre = ViewBag.Nombre;
    }

    <div class="panel">
    <div class="panel-body">

    @using (Html.BeginForm("ImpresionSeccionVistaActual", "Home", FormMethod.Post))
    {
    <h3>Sección: @nombre</h3>
    <br />
    <img src="~/Images/pacman.png" />
    }

    <center>
    <div class="rotate">Este texto está rotado 90 grados</div>
    </center> </div> </div>
  • El ejemplo contiene un texto rotado en 90 grados que se verá impreso de igual forma, por lo tanto debes agregar en la sección de estilos el siguiente código:

    <!-- _Layout.cshtml -->
    <style>
    .rotate {
    font-family: Arial, Helvetica, sans-serif;
    font-size: 13px;
    -webkit-transform: rotate(-90deg);
    -moz-transform: rotate(-90deg);
    -o-transform: rotate(-90deg);
    -ms-transform: rotate(-90deg);
    -sand-transform: rotate(90deg);
    }
    </style>
  • Creamos en la vista principal un botón Imprimir que llame al Action que haremos luego. Notar que agregamos dos bloques de texto antes y después para que se vea que solo se imprimirá la vista Seccion.cshtml:

    <!-- Index.cshtml -->
    <h2>Texto anterior</h2>
    @{
    Html.RenderAction("Seccion", "Home", new { nombre = nombre });
    }

    @using (Html.BeginForm("ImpresionSeccionVistaActual", "Home", FormMethod.Post))
    {
    @Html.Hidden("nombre", (object)nombre)
    <input type="submit" id="impresion2" name="impresion2" value="imprimir sólo sección" />
    }
    <h2>Texto posterior</h2>
  • En el HomeController crear el Action ImpresionSeccionVistaActual que procesa la sección:
    //HomeController.cs
    [HttpPost]
    public ActionResult ImpresionSeccionVistaActual(FormCollection collection)
    {
    object model = null;
    ViewDataDictionary viewData = new ViewDataDictionary(model);
    
    // transmit the posted data to view
    viewData.Add("nombre", collection["nombre"]);
    
    // The string writer where to render the HTML code of the view
    StringWriter stringWriter = new StringWriter();
    
    // Render the Index view in a HTML string
    ViewEngineResult viewResult = ViewEngines.Engines.FindView(ControllerContext, "Seccion", null);
    ViewContext viewContext = new ViewContext(
    ControllerContext,
    viewResult.View,
    viewData,
    new TempDataDictionary(),
    stringWriter
    );
    viewResult.View.Render(viewContext, stringWriter);
    
    // Get the view HTML string
    string htmlToConvert = stringWriter.ToString();
    
    // Get the base URL
    String currentPageUrl = this.ControllerContext.HttpContext.Request.Url.AbsoluteUri;
    String baseUrl = currentPageUrl.Substring(0, currentPageUrl.Length - "Home/Seccion".Length);
    
    // Create a HTML to PDF converter object with default settings
    HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter();
    
    // Set license key received after purchase to use the converter in licensed mode
    // Leave it not set to use the converter in demo mode
    htmlToPdfConverter.LicenseKey = key;
    
    // Set an adddional delay in seconds to wait for JavaScript or AJAX calls after page load completed
    // Set this property to 0 if you don't need to wait for such asynchcronous operations to finish
    htmlToPdfConverter.ConversionDelay = 2;
    
    // Convert the HTML string to a PDF document in a memory buffer
    byte[] outPdfBuffer = htmlToPdfConverter.ConvertHtml(htmlToConvert, baseUrl);
    
    // Send the PDF file to browser
    FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
    fileResult.FileDownloadName = "ImpresionSeccionVistaActual.pdf";
    
    return fileResult;
    }
    
  • Si haces clic en "Imprimir solo sección", se verá el PDF:
  • La imagen de la aplicación final ejecutándose en el navegador con dos botones, Imprimir Sección o Imprimir página externa, se ve así:

Mostrar PDF en una nueva pestaña del navegador al hacer clic en imprimir (y no en la barra de descargas)


Cambiar la clase Controller:
//HomeController.cs
// Convert the HTML page given by an URL to a PDF document in a memory buffer
byte[] outPdfBuffer = htmlToPdfConverter.ConvertUrl(url);            

// Send the PDF file to browser
//FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");            
//fileResult.FileDownloadName = "ImpresionVistaExterna.pdf";
//return fileResult;

MemoryStream stream = new MemoryStream(outPdfBuffer);
Response.AppendHeader("content-disposition", "inline; filename=file.pdf");
return new FileStreamResult(stream, "application/pdf");
Cambiar la vista para que abra en una nueva pestaña con target _black:

<!-- Index.cshtml -->
@using (Html.BeginForm("ImprimeVistaExterna", "Home", FormMethod.Post, new { target= "_blank" }))
{
<input type="submit" id="impresion2" name="impresion2" value="ver pdf generado directo en otra pestaña" />
}



Mostrar PDF en una nueva pestaña del navegador al hacer clic en imprimir y se abra automáticamente el cuadro de diálogos de las impresoras


Esto es útil si el usuario quiere hacer la menor cantidad posible de clic para imprimir un documento PDF. Se le debe asignar el key (si tienes) de nuevo al Document. Recordar igual lo del target _blank en la vista que tiene el botón.
//HomeController.cs
string url = "http://localhost:50422/Home/VistaExterna";

// Convert the HTML page given by an URL to a PDF document in a memory buffer
byte[] outPdfBuffer = htmlToPdfConverter.ConvertUrl(url);                       

//mergeResultPdfDocument.OpenAction.Action = New PdfActionJavaScript("print()")

// Send the PDF file to browser
//FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");            
//fileResult.FileDownloadName = "ImpresionVistaExterna.pdf";
//return fileResult;

MemoryStream stream = new MemoryStream(outPdfBuffer);

Document document = new Document(stream);
document.LicenseKey = key;
document.OpenAction.Action = new PdfActionJavaScript("print()");
byte[] b = document.Save();
Stream strm = new MemoryStream(b);
           
Response.AppendHeader("content-disposition", "inline; filename=file.pdf");
return new FileStreamResult(strm, "application/pdf");


Links útiles

jueves, 22 de enero de 2015

TreeList con Kendo UI for ASP.NET MVC

Este post va dirigido a los que hemos trabajado con Kendo UI para ASP.NET MVC y no hemos podido hacer un simple TreeList en menos de 1 hora.

Primero, tenía instalada la versión de Kendo 2014.2.1008 y escribía en mi vista:
@(Html.Kendo().TreeList

Y arrojaba error ya que no encontraba el .TreeList, luego viendo lo ejemplo de otras versiones me di cuenta que está incluido en la versión 2014.3.1316 por lo que recomiendo bajar esta. Además que actualmente es la última (por lo que averigüé el TreeList se agregó a Kendo en la versión 2014.3.1119).

La documentación es mucha, de hecho me perdí tanto leer, al menos en Telerik encontré:

http://docs.telerik.com/kendo-ui/api/javascript/ui/treelist
http://docs.telerik.com/kendo-ui/aspnet-mvc/helpers/treelist/overview
http://demos.telerik.com/kendo-ui/treelist/index

Luego tenemos los ejemplos que vienen en el ZIP del Kendo comercial (pagado):

- telerik.ui.for.aspnetmvc.2014.3.1316.commercial.zip, para MVC/ASPX, tiene muchos ejemplos, uno de TreeList que es muy complejo quizá para alguien que quiere hacer su primer TreeList.
- telerik.kendoui.professional.2014.3.1316.commercial.zip, para JQuery, con otros muchos ejemplos pero el código de los controladores se leen de un servicio en línea por ejemplo:
var service = "http://demos.telerik.com/kendo-ui/service";

Luego de ver mucho código, partí de cero y era más simple de lo que pensaba.

Primero tenemos una vista que llama a otra vista Header para la carga de los JS/CSS necesario, como JQuery/Kendo:
<! DOCTYPE html >
<html>
<head>
    @Html.Partial("~/HeaderCssJs.cshtml")
</head>

    

    <div class="demo-section k-header">
        @(Html.Kendo().TreeList<models .miviewmodel="">()
        .Name("treelist")
        .Columns(columns =>
        {
            columns.Add().Field(e => e.FirstName).Width(220).TemplateId("photo-template");
            columns.Add().Field(e => e.LastName).Width(160);
            columns.Add().Field(e => e.Address).Title("Address");            
        })
        .Filterable()
        .Sortable()
        .DataSource(dataSource => dataSource
            .Read(read => read.Action("Read", "Home"))
            .ServerOperation(false)
            .Model(m =>
            {
                m.Id(f => f.EmployeeId);
                m.ParentId(f => f.ReportsTo);
                m.Field(f => f.FirstName);
                m.Field(f => f.LastName);
                m.Field(f => f.ReportsTo);
            })
        )
        .Height(540)
        )
    </div>
<style>
        .employee-photo {
            display: inline-block;
            width: 40px;
            height: 40px;
            border-radius: 50%;
            background-size: 40px 44px;
            background-position: center center;
            vertical-align: middle;
            line-height: 41px;
            box-shadow: inset 0 0 1px #999, inset 0 0 10px rgba(0,0,0,.2);
        }

        .employee-name {
            display: inline-block;
            vertical-align: middle;
            line-height: 41px;
            padding-left: 10px;
        }
    </style>
</body>
En el Controlador tenemos 3 actions.

El que carga inicialmente la Vista:
public ActionResult Index()
{
    return View();
}
El Reader que se llama desde el Evento del TreeList:
public JsonResult Read([DataSourceRequest] DataSourceRequest request)
{
   var result = GetDetalle().ToTreeDataSourceResult(request);           
   return Json(result, JsonRequestBehavior.AllowGet);
}
El que carga el enumerador. Lo mejor es que no importa el orden que se hagan los Add, el Tree List de Kendo se encarga de ordenar los hijos:
private IEnumerable GetDetalle()
{
    List<MiViewModel> lista = new List< MiViewModel >();
    lista.Add(new MiViewModel () { EmployeeId = 9, FirstName = "xxxxx", LastName = "yyy", hasChildren = false, ReportsTo = 3, Address = "999", Color = "rojo" });
    lista.Add(new MiViewModel () { EmployeeId = 1, FirstName = "naldo", LastName = "Gonz", hasChildren = true, ReportsTo = null, Address = "123", Color = "rojo" });
    lista.Add(new MiViewModel () { EmployeeId = 2, FirstName = "pepe", LastName = "Super", hasChildren = false, ReportsTo = 1, Address = "456", Color = "rojo" });
    lista.Add(new MiViewModel () { EmployeeId = 3, FirstName = "juan", LastName = "Man", hasChildren = false, ReportsTo = null, Address = "789", Color = "verde" });
    return from a in lista
           select a;
}
En mi caso tengo una carpeta “img” con dos imágenes “rojo.jpg” y “verde.jpg”.

Por ultimo la clase MiViewModel:
using System.Web;

namespace Models
{
    public class MiViewModel
    {
        public MiViewModel() { }       
        public int? EmployeeId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Pos { get; set; }
        public string Color { get; set; }
        public string Address { get; set; }
        public bool hasChildren { get; set; }        
        public int? ReportsTo { get; set; }       
    }        
}

El resultado es:


Ahora veamos algunas cosillas que podemos agregar. Por ejemplo cambiar el texto que muestra el botón de arriba, en vez de "Add New Record", ponemos "Crear":
@(Html.Kendo().TreeList<Modelo>()
.Toolbar(toolbar => toolbar.Create().Text("Crear"))
Como hacer botones propios en el header del TreeList
En la definición del TreeList:
.Toolbar(toolbar =>
{
   toolbar.Custom().Name("botoncrear").Text("Crear");
   toolbar.Custom().Name("mycommand").Text("View X");
})
Luego en la sección scripts ponemos el handler del botón que lee una propiedad del modelo por ejemplo (en base a la celda seleccionada) y lo muestra en un alert:

Como dejar una fila seleccionable (al hacer clic en una celda toda la fila queda seleccionada):
@(Html.Kendo().TreeList<Modelo>()
  .Selectable(true)
Como obtener dicha fila seleccionada con jQuery:
var treeList = $("#contenedor").data("kendoTreeList");
var row = treeList.select();       
Como cambiarle el estilo a una fila seleccionada, por ejemplo seleccionarla y dejarla con estilo oblique (parecido a Italic):
var treeList = $("#contenedor").data("kendoTreeList");
var row = treeList.select();            
row.css('font-style', 'oblique');

Espero les sirva.

jueves, 14 de noviembre de 2013

Capítulo 1 de libro examen para certificación 70-536 en español

El Examen 70-536 de nombre TS: Microsoft .NET Framework - Application Development Foundation de Microsoft, liberado el 21 de Marzo del 2008, y que actualmente no está vigente, pero sin embargo, es uno de los mejores libros (a mi gusto) donde están los fundamentos de la programación en .Net, específicamente del Framework 2.0 y por ende una sólida base para los que trabajamos con las siguientes versiones del Framework como la versión 4.0 o 4.5.

Cuando estudié para esta certificación que finalmente no di (de flojo), lo hice con el libro oficial MCTS Self-Paced Training Kit (Exam 70-536): Microsoft® .NET Framework Application Development Foundation, Second edition que en Amazon está en 43,54 dolares unos 21 mil, más el envío a Chile dan un costo total aproximado calculo de unos 28 mil, pero que pillas en Google fácilmente con la palabra clave "70-536 pdf", bueno cuando estudié, realizaba la traducción/transcripción del libro ya que para mí me salía más fácil entender. Este es el primer capítulo, lecciones 1, 2, 3 y 4 traducido al español y que quiero compartir con ustedes ya que lo tenía botado en mi viejo baúl en dropbox:

Leyenda
F: Framework

CAPÍTULO 1 : Fundamentos del Framework

Lección 1: Tipos por Valor

  • String no es por Valor, sino por Referencia.
  • Al usarse una variable por valor en un procedimiento, se hace una copia de esta, por lo que si se hacen cambios adentro, no se ve afectado la variable al salir
  • Son valores chicos, usan 16 bytes o menos cada uno. Son altamente performantes
  • Tipos de datos numéricos y bool son tipos por valor
  • Son datos datos que están directos en memoria, en una zona llamada "Pila"
  • Hay 3 tipos:

1. Build-in: los da el Framework
A. Numéricos: optimizado para Int32, UInt32 y Double
    System.Sbyte -128 a 127
    System.Byte 0 a 255
    System.Int32 / Int C#, Integer en VB –2147483648 a 2147483647   -> Int32 es una estructura y no una clase (ya que esta ultima es un tipo de dato por referencia)
    System.UInt32 0 a 4294967295
    Int64 –9223372036854775808 a 9223372036854775807
    Single –3.402823E+38 a 3.402823E+38
    Double –1.79769313486232E+308 a 1.79769313486232E+308   (más preciso)
    Decimal: –79228162514264337593543950335 a 79228162514264337593543950335   (cientifico/estadistico)
            IntCtr permite que el largo lo defina el SO por ej. Windows 32 o 64 bits, puede ser mas largo o mas corto que el numero que que lo del int
      B. Otros
      System.Char letras unicode
      System.Boolean true/false
      System.IntPr         puntero a memoria
      System.DateTime      momentos en el tiempo

      - Se autodeclaran, tienen implícito un constructor, no requieren new. El constructor le asigna un nulo o 0, pero siempre se debe inicializar. Ejemplo: Bool test = false;
      - C# es case-sensitive, Visual Basic no.
      - Declarar un objeto nulo cuando no se quiere inicializar, se puede usar la sentencia Nullable:
         Nullable b = null;   
         //en C# permite igual   
         bool? b = null;   
         //o también
         int? i = null;
      
      - Para ver si un objeto nullable tiene valor, usar HasValue:
         if (b.HasValue)
      

      2. User-defined
      - Son Estructuras o structs, contienen otros tipos de datos, por ej:
         System.Drawing.Point p = new System.Drawing.Point(20, 30);   // Point es Value Type
      
      - Se pueden crear con la palabra "struct", estas SOLO tienen tipos por VALOR
          struct Cycle
          { 
           int _val, _min, _max;
       
           public Cycle(int min, int max)
           {
           _val = min;
           _min = min;
           _max = max;
           }
      
      - Se puede convertir a tipo por Referencia cambiando Struct por Class, se puede tener 2 variables apuntando a la misma dirección de memoria, quedando en una zona llamada HEAP de la memoria.
      - Al hacer esto se almacena fuera de los 12 bytes de la pila.
      - Usualmente las estructuras son mas eficientes que las clases. Deberías definir estructuras si el tipo anda mejor como tipo por valor que por referencia.
      - Se debe escoger una estructura SOLO si: Lógicamente es como tener un simple valor, tiene un tamaño menor a 16 bytes, no cambiara luego de su creación, no usa tipos por referencia SOLO por Valor.

      3. Enumeraciones
         public enum Genders : int { Male, Female };
         public Genders gender;
      

      Lección 2: Tipos por Referencia

      -La mayoría de los tipos del F son por referencia.
      -Se guarda la dirección de los datos en memoria, no los datos en si, un "puntero" en la pila, en una zona llamada HEAP.
      -El F maneja lo que esta en el HEAP con el Garbaje collector o GC, este escanea la memoria en busca de valores no referenciados.
      -El GC se gatilla cuando el F lo necesita o cuando se ejecuta GC.Collect.
      -Al tener una variable por referencia, si tengo otra que le asigno el valor, en verdad es la copia de la dirección no del valor. Ejemplo:
        struct Numbers
        {
         public int val;
         public Numbers(int _val)
         { val = _val; }
         public override string ToString()
         { return val.ToString(); }
        }  
        Numbers n1 = new Numbers(0);   // -> Numerse es una variable por referencia
        Numbers n2 = n1;
        n1.val += 1;
        n2.val += 2;
        Console.WriteLine("n1 = {0}, n2 = {1}", n1, n2);  // -> N1: 1  N2: 2
        
        Si lo cambiamos a Clase: 
        
        // C#
        Class Numbers
        {
        ... 
      
      La salida es ----> N3: 3 N2: 3 ya que ambos apuntan a la misma dirección no al valor en si. La modificar la referencia, se modifican todas las copias de la referencia.
      Weak refference: es una referencia débil o que puede ser eliminada por el Garbaje Collector a pesar de usar usada y no asignada a null que es cuando el garbaje collector debería eliminarla.
      - Hay 2500 tipo por referencia build-in en el F. No todos derivan del System.ValueType.
      - Tipos por referencia mas comunes: System.Object, System.String, Systen.Text.TextBuilder, System.Array, System.IO.Stream, System.Exception.
      - No todos los tipo de objetos que derivan de System.Object son tipo de objetos por referencia. Puede derivar objeto de tipo por Valor.
      - Strings y String Builders: proveen manipulación de datos.
      - Es mejor usar StringBuilder en vez de String cuando se quiere armar un gran string con pedazos de string mas chicos. No así cuando se quiere buscar o reemplazar.
      -String soporta 32,767 bytes.
         string s = "this is some text to search";  
         s = s.Replace("search", "replace");
      
      -Los string son inmutables en .Net, es decir, cualquier cambio en ellos genera un nuevo string y el viejo pasa a ser marcado como listo para eliminar por el GC. Ejemplo:
         // C#
         string s;
         s = "wombat"; // "wombat"
         s += " kangaroo"; // "wombat kangaroo"
         s += " wallaby"; // "wombat kangaroo wallaby"
         s += " koala"; // "wombat kangaroo wallaby koala" 
      - Solo el último vale y tiene una referencia, los otros se eliminaran por el GC.
      - No tener esos string intermedios ayuda al performance ya que evita que el GC trabaje.
      - Para evitar string intermedios, se puede usar:
      - Métodos Concat, Join o Format de la clase String.
      - Usar clase StringBuilder para trabajar con varios "mutables" strings.
         System.Text.StringBuilder sb = new System.Text.StringBuilder(30);
         sb.Append("wombat"); // Build string.
         sb.Append(" koala");
         string s = sb.ToString(); // Copy result to string.
      
      -La clase String permite sobreescribir operadores de System.Object:
         suma vb + o &  C# +
         igualdad vb =  C# ==
         no igualdad vb <>  c# !=
         asignación vb y c# =
      
      - Como crear y ordenar Arreglos:
         int[] ar = { 3, 1, 2 };   
         Array.Sort(ar);   
         //mostramos los resultados:  
         Console.WriteLine("{0}, {1}, {2}", ar[0], ar[1], ar[2]);
      

      Como crear y usar Streams
      - Los streams se usan para escribir datos en el disco o enviar paquetes por red.
      - El tipo base es System.IO.Stream de otros tipos.
      - Tipos stream para red se ubican en System.Network.Sockets
      - Stream encriptados estan en System.Security.Cryptography namespace.
      - Tipos stream comunes: FileStream, MemoryStream, StreamReader, StreamWriter.
      - StreamReader y StreamWriter te permite escribir y leer archivos del disco.
         use namespace System.IO
         // Escribe en un txt
         StreamWriter sw = new StreamWriter("text.txt");
         sw.WriteLine("Hello, World!");
         sw.Close();   
         // Lee un archivo y muestra
         StreamReader sr = new StreamReader("text.txt");
         Console.WriteLine(sr.ReadToEnd());
         sr.Close();
      

      Como lanzar y capturar Excepciones
      - Las excepciones son "eventos" inesperados que interrumpen la normal ejecución de un assembly.
      - Las excepciones no evitan que un software se caiga sino que sirve para uno se adelante y las capture y maneje
      - Ejemplo:
         use namespace System.IO
         try
         {
          StreamReader sr = new StreamReader(@"C:\boot.ini");
          Console.WriteLine(sr.ReadToEnd());
         }
         catch (Exception ex)
         {
          // If there are any problems reading the file, display an error message
          Console.WriteLine("Error reading file: " + ex.Message);
      
          //Este caso puede arrojar error: file not found error, insufficient privileges error
          //o un error al leer el archivo. Y la ejecucion "salta" al Catch.
         }
      
      - La clase base Exception es muy útil ya que contiene el mensaje de error y mas datos de la aplicación.
      - Uno puede hacer Excepciones propias derivando de System.ApplicationException.
      - Se pueden tener múltiples clases Exceptions para responder diferente a algún tipo de error, el F ejecutara el primer bloque Catch que coincida con el tipo de Exception definido.
      - Se deben ordenar las excepciones desde las mas especificas a la mas global, generalmente Exception.
         Try
          Dim sr As StreamReader = New StreamReader("text.txt")
          Console.WriteLine(sr.ReadToEnd)
          Catch ex As System.IO.FileNotFoundException
           Console.WriteLine("The file could not be found.")
          Catch ex As System.UnauthorizedAccessException
           Console.WriteLine("You do not have sufficient permissions.")
          Catch ex As Exception
           Console.WriteLine("Error reading file: " + ex.Message)
         End Try
      

      -El bloque try/catch soporta un bloque Finally que se ejecuta bien caiga o no en algún Catch. Se usa para cerrar Streams, o limpiar algún objeto.
         StreamReader sr = new StreamReader("text.txt");
         try
         {
          Console.WriteLine(sr.ReadToEnd());
         }
         catch (Exception ex)
         {
          // If there are any problems reading the file, display an error message
          Console.WriteLine("Error reading file: " + ex.Message);
         }
         finally
         {
          // Close the StreamReader, whether or not an exception occurred
          sr.Close();
         }
      

      - Fijarse que el primer bloque StreamReader sr ... se movió afuera del bloque try esto porque el bloque Finally NO pueda acceder a variables declaradas dentro del bloque Try.
      - En general se declaran la variables afuera del bloque try y en el bloque try se programa todo el codigo.
      - Usar un bloque try/catch tiene una baja penalidad en performance pero la tiene.
      - Ejemplo obtener tipo con IF (Object.GetType().IsValueType)
         SByte a = 0;
         Byte b = 0;
         Int16 c = 0;
         Int32 d = 0;
         Int64 e = 0;
         string s = "";
         Exception ex = new Exception();
         object[] types = { a, b, c, d, e, s, ex };
         foreach ( object o in types )
         {
          string type;
          if (o.GetType().IsValueType)
           type = "Value type";
          else
           type = "Reference Type";
          Console.WriteLine("{0}: {1}", o.GetType(), type );
         }
      

      - Unir elementos de un arreglo de string con espacio:
         string s = "Microsoft .NET Framework 2.0 Application Development Foundation";
         string[] sa = s.Split(' ');
         x = string.Join(" ", sa); -> vuelve a estar como antes.
      

      Lección 3: Construyendo clases

      ¿Qué es un Herencia?

      - La consistencia de clases se hace gracias a la herencia e interfaces.
      - La herencia sirve para crear clases a partir de otras o crear nuevos tipos a partir de otros.
      - Por ejemplo la clase Bitmap herada Image pero la extiende, por lo que tiene mas funcionalidades.
      - Puedes crear tu propia Excepcion heredando de System.ApplicationException.
      - Ejemplo obtener tipo con IF (Object.GetType().IsValueType)
         class DerivedException : System.ApplicationException
         {
           public override string Message
           {
             get { return "An error occurred in the application."; }
           }
         }
      
         //Puedes lanzar la exepcion con throw new 
         // C#
         try
         {
            throw new DerivedException();
         }
         catch (DerivedException ex)
         {
            Console.WriteLine("Source: {0}, Error: {1}", ex.Source, ex.Message);
         }
      
      - La nueva excepción tiene .Source por ejemplo ya que aunque no este implementado, al heredar de System.ApplicationException la tiene.
      - La herencia permite el intercambio de clases, por ejemplo si tenemos 5 clases que heredan de System.Drawing.Brush, si el método Graphics.DrawRectangle requiere un objeto System.Drawing.Brush, se le debe pasar alguno de los que heredan y no el padre.

      ¿Que es una interface?

      - Interfaces o "contrato" definen un conjunto común de miembros que todas las clases que la implementan deben proveer.
      - Por ejemplo la interfaz IComparable define el método CompareTo el cual permite comparar 2 clases. Entones todas las clases que implementen la interface IComparable, ya sean clases propias del F o clases tuyas, pueden ser comparadas por la igualdad.
      - La interfaz "IDisposable" es una interface que solo provee un método Dispose.
      - Permite que otros assemblys creen una instancia de tu clase y puedan liberar cualquier recurso que la instancia haya consumido.
      - Usa interface para definir un conjunto de miembros que DEBEN ser implementados por tipos asociados.
      - Permite a uno escribir código para liberar manualmente los recursos.
      - Ejemplo:
         class BigClass : IDisposable
         {
         }
      
      - Luego con Visual Studio, coloca el boton derecho en IDisposable -> Implement Interface -> Implement Interface y Visual Studio automáticamente coloca el código:
         public void Dispose()
         {
            throw new NotImplementedException();
         }
      
      - Otras interfaces muy usadas IComparable, IDisposable, IConvertible, ICloneable, IEquatable, IFormattable.
      - puedes crear tus propias interfaces por si quieres crear múltiples clases que tengan un comportamiento similar.
      - Ejemplo interfaz con 3 miembros:
         // C#
         interface IMessage
         {
         // Send the message. Returns True is success, False otherwise.
         bool Send();
         // The message to send.
         string Message { get; set; }
         // The Address to send to.
         string Address { get; set; }
         }
      
      - Si quieres implementar esa interfaz en tu clase, Visual Studio genera el siguiente template:
         class EmailMessage : IMessage 
         {
          public bool Send()
          {
          throw new Exception("The method or operation is not implemented.");
          }
          public string Message
          {
          get
          {
          throw new Exception("The method or operation is not implemented.");
          }
          set
          {
          throw new Exception("The method or operation is not implemented.");
          }
          }
          public string Address
          {
          get
          {
          throw new Exception("The method or operation is not implemented.");
          }
          set
          {
          throw new Exception("The method or operation is not implemented.");
          }
          }
         }
      
      - Visual Studio permite extraer o armar una Interfaz a partir de los métodos de una clase, con el 2do. botón sobre la clase dada (que puede o no heredar de una interfaz) -> Refactor -> Extract Interface -> seleccionas que miembro quieres extraer, ok
      - Las clases pueden implementar diferentes interfaces a la vez por ejemplo las interfases IComparable, IDisposable:
         class EmailMessage : IMessage, IComparable, IDisposable

      Clases Parciales
      - Son nuevas en .Net 2.0.
      - Permiten dividir una clase en múltiples archivos, con el beneficio de esconder detalles y enfocarse en los aspectos claves.
      - Un Windows form tiene una clase parcial ya que tiene el código generado por el diseñador en la clase media oculta form.Designer.cs. En Visual Basic hay que escoger View All files, en C# esta enable por defecto.
      - Las Clases parciales no son parte del examen.

      ¿Qué es Generics?

      - Son tipos partes del F, permite definir un tipo dejando detalles sin especificar.
      - En vez de especificar los tipos de parámetros o tipos de miembros en clases, puedes dejar que el código lo haga. Esto permite al consumidor de código especificar el tipo que el requiera.
      - Es nuevo en .Net 2.0 y hay muchas preguntas de estas en el examen.
      - Hay clases genéricas por defecto en el namespace de System.Collections.Generic. Incluyendo: Dictionary, Queue, SortedDictionary, y SortedList.
      - Hay tipos genéricos: Nullable y EventHandler (Boolean y Point no lo son).
      - Estas clases funcionan similar a aquellas no genéricas de System.Collections, pero tiene mejoras en performance y son de tipo seguro (safe type), esto quiere decir que no tiene que ver con seguridad, sino que siempre se accede a los objetos asignados de forma compatible.

      ¿Por qué usar Generic?
      - F 1.0 y 1.1 no soportan generic, en vez de eso se usan clases Object para parámetros y miembros que debías castear a otra Clase.
      - Tiene 2 ventajas:
        A. Reduce errores de runtime: el compilador no puede detectar errores si se usa la clase object, por ejemplo si se castea un string a Object y luego de ese Object a int, el compilador no hara catch del error, sino que el runtime lanzará una excepción. Al usar Generic, el compilador detecta el error antes de iniciarse. Adicionalmente puede escribir constraint para limitar el número de clases que usan generic.
        B. Mejora de Performance: Usar Casting requiere lo que se llama "Boxing" o "Unboxing" lo que hace trabajar al procesador y baja el performance, al usar Generic no se usa casting.
      NOTA del autor del libro: En la vida real, en pruebas hechas no hay mejoras sustanciales en performance, bajo 100.000 iteraciones. y son de pocos segundos, por lo que se recomienda usar generic no tanto por performance, pero si por ser "safe type".
      - Ejemplo de clase que usa Object y otra que usa Genérica.
         // C#
         class Obj
         {
          public Object t;
          public Object u;
          public Obj(Object _t, Object _u)  // -> tiene 2 tipos Object
          {
           t = _t;
           u = _u;
          }
         }
         class Gen     // -> tiene los tipos T y U
         {
          public T t;
          public U u;
          public Gen(T _t, U _u)
          {
           t = _t;
           u = _u;
          }
         }
      
      - El código que consume determina si es T y U es Entero o String.
      - Hay una limitante: el código solo funciona si el desarrollo esta hecho para cada instancia de Generic, int o string ya que estamos limitados a la clase Object, igualmente se puede llamar a ToString() o GetHashCode métodos dentro de la clase pero no + o >.
      - Consumir un tipo Generico: aqui se debe especificar el tipo:
         // Add two strings using the Obj class
         Obj oa = new Obj("Hello, ", "World!");
         Console.WriteLine((string)oa.t + (string)oa.u);
         // Add two strings using the Gen class
         Gen ga = new Gen("Hello, ", "World!");
         Console.WriteLine(ga.t + ga.u);
         
         // Add a double and an int using the Obj class
         Obj ob = new Obj(10.125, 2005);
         Console.WriteLine((double)ob.t + (int)ob.u);
         // Add a double and an int using the Gen class
         Gen gb = new Gen(10.125, 2005);
         Console.WriteLine(gb.t + gb.u);
      
      
      Si lo ejecutas la clase con Gen es un poco mas rapido ya que no requiere Box/Unbox de la clase Object.
      - Los errores surgen en compilación y no en run-time. Es mas fácil determinar errores de compilación que errores de ejecución:
         // C#
         // Add a double and an int using the Gen class
         Gen gc = new Gen(10.125, 2005);
         Console.WriteLine(gc.t + gc.u);
         // Add a double and an int using the Obj class
         Obj oc = new Obj(10.125, 2005);
         Console.WriteLine((int)oc.t + (int)oc.u);   // aqui hay error en (int)oc.t ya que es double, al compilar no se da cuenta
      

      Como usar constraint en Generic
      -Interface: permite solo tipos que implementen interfaces especificas para usar en tu generic.
      -Class: permite solo tipos que implementen clases especificas para usar en tu generic.
      -Constructor: permite decir que requiere tipos que usen genéricos para implementar un constructor con parámetros.
      -Tipo por valor o referencia: Requiere que los tipos que usan tu generic sean de tipo valor o referencia.
      - Se puede usar la clausula where para aplicar la constraint. Por ejemplo la constraint para X interfaz:
         // C#
         class CompGen
         where T : IComparable
         {
          public T t1;
          public T t2;
          public CompGen(T _t1, T _t2)
          {
           t1 = _t1;
           t2 = _t2;
          }
          public T Max()
          {
           if (t2.CompareTo(t1) < 0)
            return t1;
           else
            return t2;
          } 
         }
      
      - Si estas creando un clase genérica y necesitas hacer dispose de los objetos genéricos: Usar una Constraint que requiera un tipo Genérico que implemente la interfaz IDisposable. Y no implementar la interfaz IDisposable directamente.

      Eventos
      - La mayoría de las aplicaciones no son lineales, tienen eventos.
      - Un evento es un mensaje que envía un objeto en señal de una acción, que puede ser un clic del mouse, o gatillado por algún otro programa.
      - El objeto que gatilla el evento se llama event sender y el que captura el evento event receiver y lo maneja (lo que se conoce como handle).
      - El objeto que envía no sabe que objeto recibe (handle) el evento por lo que el F provee un guía o puntero entre quien envía y quien recibe, se llama Delegado.
      - Un Delegado es una clase que tiene el control de la referencia. A diferencia de otras clases, una clase delegado tiene una firma o "signature" y esta puede referenciar solo a métodos que coinciden con dicha firma.
      - Una firma o signature en C# es el nombre del método + el tipo del método + Valor/Referencia/Resultado de Parámetros. Ejemplo:
         interface ITest
         {
            void F();                     // F()
            void F(int x);                // F(int)
            void F(ref int x);            // F(ref int)
            void F(int x, int y);         // F(int, int)
            int F(string s);              // F(string)
         }
      
      - Un delegado es el equivalente a una función type-safe o a un callback.
      - Una declaración del delegado es suficiente para definir un clase delegada, esta declaración reemplaza la firma del delegado y el Common Language Runtime provee la implementación.
      - Ejemplo de una declaración de delegado:
         // C#
         public delegate void AlarmEventHandler(object sender, EventArgs e);
      
      - La firma estándar de un delegado que manejada eventos es definir un método que no retorne valor dado, entonces se usa "void" y donde el primer parámetro es la instancia que gatilla el evento, como no sabemos es tipo "Object", y el segundo es de tipo "EventArgs" que mantiene los datos del evento. Si el evento gatillado no tiene datos de evento, el segundo parámetro solo seria una instancia de EventArgs.
      - El delegado EventHandler es predifinido para los casos que se quiere un manejador de eventos que no genera datos de evento.
      - Para asociar al evento con el método que gatillo el evento, agrega una instancia del delegado en el evento. El event handler sera llamado si el evento ocurre a menos que remuevas el delegado.
      - Como responder a un evento: Se debe hacer 2 cosas: A. Crear un método que responda al evento. Este método debe coincidir con al firma del Delegado. Típicamente retorna un "void" y acepta 2 parámetros un "Objeto" y un "EventAgrs" o (clase derivada)
         // C#
         private void button1_Click(object sender, EventArgs e)
         {
           // Method code
         }
      
      B. Agregar el manejador de eventos (en este caso usamos button1_Click) que indica que método debería recibir el evento (apunta al método anteriormente creado):
         // C#
         this.button1.Click += new System.EventHandler(this.button1_Click);
      
      - NOTA: el .NET Framework 2.0 incluye una nueva version generica del tipo "EventHandler".
      - Cuando el evento ocurre, el método especificado se ejecutara.

      Como lanzar un evento
      - Crear un delegado:
         public delegate void MyEventHandler(object sender, EventArgs e);
      - Crear un miembro de un Evento de tipo que coincida con el Delegado creado:
         public event MyEventHandler MyEvent;
      - Invocar el delegado dentro del método cuando lanzas el evento, con VB es muy simple, C# no tanto:
         'VB
          Dim e As EventArgs = New EventArgs
          RaiseEvent MyEvent(Me, e)
          // C#
          MyEventHandler handler = MyEvent;
          EventArgs e = new EventArgs();
          if (handler != null)
          {
           // Invokes the delegates.
           handler(this, e);
          }
          // Note that C# checks to determine whether handler is null.
          // This is not necessary in Visual Basic
      

      Atributos
      - describen un tipo, método, propiedad/miembro con la idea de programar la técnica de Reflection.
      - algunos usos comunes de los atributos son:
      A. especificar privilegios de seguridad que requiere una clase
      B. especificar privilegios para reducir los riesgos de seguridad
      C. declarar capacidades, como soportar serialización -> transformar una clase a ciertos bytes con un formato determinado, por ejemplo transformar a XML. Solo se serializa métodos puplicos.
      D. describe un assembly dándole un titulo, descripción y copyright.
      - Los atributos derivan de Systenm.Attribute.
      - Los atributos se especifican <> en VB o con [] con C#.
      Ejemplo:
         // C# - AssemblyInfo.cs
         [assembly: AssemblyTitle("ch01cs")]
         [assembly: AssemblyDescription("Chapter 1 Samples")]
         [assembly: AssemblyConfiguration("")]
      
      - Visual Studio automáticamente genera atributos como el titulo, descripción, compañía y versión. Deberías editar esos valores en los proyectos que generes.
      - Otro atributo es definir si la clase es serializable, con el atributo Serializable:
         ' VB
          Class ShoppingCartItem
         End Class
         // C#
         [Serializable]
         class ShoppingCartItem
         {
         }
      
      - Sin el atributo Serializable, la clase no se puede serializar.
      - El siguiente código indica que la clase requiere leer el archivo C:\boot.ini, ya con esto, si hay un error (de privilegio u otro), el runtime puede lanzar una excepción ANTES de ejecutar el bloque de código.
      - Ejemplo:
         // C#
         using System;
         using System.Security.Permissions;
         [assembly:FileIOPermissionAttribute(SecurityAction.RequestMinimum, Read=@"C:\boot.ini")]
         namespace DeclarativeExample
         {
          class Class1
          {
           [STAThread]
           static void Main(string[] args)
           {
            Console.WriteLine("Hello, World!");
           }
          }
         }
      

      ¿Qué es el Type Forwarding (Tipo forwardng)?
      - Es nuevo de F 2.0.
      - Es un atributo (implementado en TypeForwardedTo) que te permite mover el tipo de un assembly (Assembly A) a otro (Assembly B), sin necesidad de recompilar los clientes que consumen el assembly A.
      - Luego que un componente (assembly) viaja y es usado por una aplicación, puedes usar Type Forwarding para mover un tipo de una componente a otro assembly y enviar la componente actualizada y las clientes no necesitan ser recompiladas.
      - Type Forwarding: Es utilizado para cuando por ejemplo, tienes una clase en una dll, pero con el paso del tiempo re estructuras tu aplicación y resulta que esa clase ya no queda en esa dll sino en otra. ¿entonces tienes que ir en cada uno de tus clientes a reinstalar la aplicación? No, entonces puedes utilizar TypeForwarding para indicarle al CLR que busque esa clase en otra dll diferente de la dll original.
      - Para mover el tipo de una class library a otro:
      A. Agrega el atributo TypeForwardedTo a la clase de origen.
      B. Corta de la definición del tipo de la source class library.
      C. Pega la definición del tipo en class library destino.
      D. Recompila ambas librerías.
      - Ejemplo: El siguiente código muestra el atributo que es usado para mover TypeA de la class library a un DestLib:
         // C#
         using System.Runtime.CompilerServices;
         [assembly:TypeForwardedTo(typeof(DestLib.TypeA))]
      

      Lección 4: Conversion entre tipos

      Conversiones en VB y C#

      - Por defecto, VB permite conversión implícita, C# no ya que pierde precisión.
      - Para desactivar la conversión implícita en VB agrega "Option Strict On" en casa archivo o en las propiedades del proyecto en VS.
      - Tanto VB y C# permiten conversión implícita si el tipo destino coincide o se acomoda con el tipo de origen. A esto se le conoce como "widening conversion", ej:
         // C#
         int i = 1;
         double d = 1.0001;
         d = i; // Conversion allowed.
      
      - Si el rango del origen excede en precision al tipo destino, esta operación es llamada "narrowing conversion", requiere una conversión explicita.
      - Métodos de conversiones Explicitas:
         
         Tipo System          VB        C#         Convert
         System.Convert                            entre tipos que implmenten IConvertible
                              Ctype    (type)cast 
         type.ToString()
         type.Parse 
         type.TryParse,                            -> nuevo en F 2.0
         type.TryparseExact                        -> nuevo en F 2.0
                             CBool, Cint, CStr, etc  
                             DirectCast
                             TryCast               -> nuevo en F 2.0
      
      - Las conversiones narrowing fallan si el rango del tipo de origen excede el rango del tipo de destino, por lo que se recomienda usar bloques try, o usar TryParse/TryCast para validar la salida.

      Boxing y UnBoxing
      - Hay que tratar de evitarlos si tiene un código que se repite mucho y usas Boxing/UnBoxing.
      Boxing: Convertir un tipo por valor a uno por referencia.
      - Se debe evitar para no tener overhead o "costo de tiempo extra".
      - Boxing se gatilla igualmente mucho llamas métodos virtuales cuya estructura herede de "System.Object", como "ToString".
         // C#
         int i = 123;
         object o = (object) i;
      
      UnBoxing: Convertir un tipo por referencia a uno por valor.
         // C#
         object o = 123;
         int i = (int) o;
      
      - Para evitar este uso:
        -implementar versiones especificas de procedimientos que acepten ese especifico tipo de dato. La mejor opción es crear métodos sobrecargados que uno que acepte el parámetro OBJECT.
        -usar generics en lo posible en vez de usar parámetros Objects.
        -sobreescribe los miembros virtuales "ToString", Equals y GetHash cuando se definan las estructuras.

      Como implementar la Conversión en Tipos Custom.
      A. Definir operadores de conversión para simplificar las conversiones narrowing y widering.
        - Te permite asignar directamente asignar desde un tipo por valor a tu tipo custom.
        - Usa la clausula Widening/implicit úsala para conversiones que no pierdan precisión.
        - Usa la clausula Narrowing/explicit úsala para conversiones que pueden perder precisión.
      B. Sobreescribir ToString() para proveer conversiones PARA string y sobreecribe Parse para proveer conversión DESDE string.
      C. Implementar System.IConvertible para permitir la conversión a través de System.Convert. Usa esta técnica para permitir conversiones de la cultura.
      D. Implementa una clase TypeConverter para permitir una conversión en tiempo de diseño para ser utilizada en la ventana de Propiedades de VS. Conversiones en tiempo de diseño esta fuera del examen.
      Operadores de Conversión
      - Es nuevo en F 2.0.
      - Por ejemplo asignacion DESDE Enteros y HASTA Enteros usando implicit/explicit, sobreescribiendo ToString y evitando hacer boxing:
       // C#
       struct TypeA
       {
        public int Value;
        // Allows implicit conversion from an integer.
        public static implicit operator TypeA(int arg)
        {
         TypeA res = new TypeA();
         res.Value = arg;
         return res;
        }
        // Allows explicit conversion to an integer
        public static explicit operator int(TypeA arg)
        {
         return arg.Value;
        }
        // Provides string conversion (sin boxing).
        public override string ToString()   // -> To sobreescribimos String, evitamos Boxing
        {
         return this.Value.ToString();   // retornamos algo diferente al nombre del tipo (type name).
        }
       }
       //Ahora podemos asignar Enteros directamente:
       // C#
       TypeA a; int i;
       // Widening conversion is OK implicit.
       a = 42; // Rather than a.Value = 42
       // Narrowing conversion must be explicit.
       i = (int)a; // Rather than i = a.Value
       Console.WriteLine("a = {0}, i = {0}", a.ToString(), i.ToString());
      
      - Para implementar la interface "System.IConvertible":
      - Agrega la interfaz "IConvertible" a la definicion del tipo.
      - Con VS hazlo automáticamente y VS insertara 17 declaraciones de miembros, incluyendo "GetTypeCode", "ChangeType" y "ToType" para cada tipo base.
      - No es necesario implementar todos los métodos como "ToDateTime".
      - Para métodos inválidos solo lanza una excepcion "InvalidCastException"
      - Luego de implementar la Interfaz "IConvertible", el tipo custom puede ser convertido usando el estandar "System.Convert":
         // C#
         TypeA a; bool b;
         a = 42;
         // Convert using ToBoolean.
         b = Convert.ToBoolean(a);
         Console.WriteLine("a = {0}, b = {1}", a.ToString(), b.ToString());
      

      Términos importantes del capítulo


      - boxing: Convertir un tipo por valor a uno por referencia. "overhead" o "costo de tiempo extra".
      - cast
      - constraint
      - contract
      - exception
      - filtering exceptions
      - garbage collection
      - generic type
      - heap
      - interface
      - narrowing: Conversión con perdida de precisión. Por ejemplo de Int32 a Int16.
      - nullable type
      - signature: Es una "firma" que consiste en nombre del método + el tipo del método + Valor/Referencia/Resultado de Parámetros. Ejemplo void F(int x); int X(ref int z)
      - stack
      - structure
      - unboxing: Convertir un tipo por referencia a uno por valor.
      - widening: Conversión sin perdida de precisión. Por ej de Int16 a Int32.

      Fin Traducción capítulo 1 del libro MCTS Self-Paced Training Kit (Exam 70-536): Microsoft® .NET Framework Application Development Foundation, Second edition