IDisposable Thoughts

Honey… where is my coding t-shirt?

Hey there! Thanks for dropping by Theme Preview! Take a look around
and grab the RSS feed to stay updated. See you around!

Posts Tagged ‘asp.net’

A few days ago Scott Guthrie announced the ASP.NET MVC 3 Preview 1 availability. The team did such a great job adding Dependency Injection to the whole framework using a slightly modified Service Locator, in that way you may plug your favorite DI container. As you may imagine, there is no DI container shipped with this first preview, so you need to roll your own. Brad Wilson did such a terrific job writing a post series about DI using MVC 3 Preview 1 and create a Unity Container Service Locator adapter, I really recommend you read his blog post series before continue with this post :)

I prefer Castle Windsor Container, so using his blog posts as a blueprint, I write a simple Service Locator adapter for Castle Windsor.

Let’s tart with the Controller Factory:

using System.Web.Mvc;
using System.Web.Routing;
using Castle.MicroKernel;

namespace Castle.Windsor.Mvc {
    public class WindsorControllerFactory : IControllerFactory {
        private readonly IControllerFactory _defaultFactory;
        private readonly IWindsorContainer _container;

        public WindsorControllerFactory(IWindsorContainer container) : this(container, new DefaultControllerFactory()) {
            _container = container;
        }

        public WindsorControllerFactory(IWindsorContainer container, IControllerFactory defaultFactory) {
            _container = container;
            _defaultFactory = defaultFactory;
        }

        public IController CreateController(RequestContext requestContext, string controllerName) {
            try {
                return _container.Resolve<IController>(controllerName.ToLowerInvariant());
            } catch (ComponentNotFoundException) {
                return _defaultFactory.CreateController(requestContext, controllerName);
            }
        }

        public void ReleaseController(IController controller) {
            _container.Release(controller);
        }
    }
}

Pretty straighforward, now, it’s time for the Castle Windsor adapter for MvcServiceLocator, it is almost a wrap over Windsor methods:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Web.Mvc;

namespace Castle.Windsor.Mvc {
    public class WindsorMvcServiceLocator : IMvcServiceLocator {
        private readonly IWindsorContainer _container;

        public WindsorMvcServiceLocator(IWindsorContainer container) {
            _container = container;
        }

        public object GetService(Type serviceType) {
            return _container.Resolve(serviceType);
        }

        public IEnumerable<TService> GetAllInstances<TService>() {
            return _container.ResolveAll<TService>();
        }

        public IEnumerable<object> GetAllInstances(Type serviceType) {
            return _container.ResolveAll(serviceType).Cast<object>();
        }

        public TService GetInstance<TService>() {
            return _container.Resolve<TService>();
        }

        public TService GetInstance<TService>(string key) {
            return _container.Resolve<TService>(key);
        }

        public object GetInstance(Type serviceType) {
            return GetService(serviceType);
        }

        public object GetInstance(Type serviceType, string key) {
            return _container.Resolve(key, serviceType);
        }

        public void Release(object instance) {
            _container.Release(instance);
        }
    }
}

To allow inject filters you need to provide a IFilterProvider implementation, I did it using Brad’s post about DI on Action Filters:

using System.Web.Mvc;

namespace Castle.Windsor.Mvc {
    public class WindsorFilterAttributeFilterProvider : FilterAttributeFilterProvider {
        private readonly IWindsorContainer _container;

        public WindsorFilterAttributeFilterProvider(IWindsorContainer container) {
            _container = container;
        }

        protected override System.Collections.Generic.IEnumerable<FilterAttribute> GetControllerAttributes(
            ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
            var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor);
            foreach (var attribute in attributes) {
                _container.BuildUp(attribute.GetType(), attribute);
            }

            return attributes;
        }

        protected override System.Collections.Generic.IEnumerable<FilterAttribute> GetActionAttributes(
            ControllerContext controllerContext, ActionDescriptor actionDescriptor) {
            var attributes = base.GetActionAttributes(controllerContext, actionDescriptor);
            foreach (var attribute in attributes) {
                _container.BuildUp(attribute.GetType(), attribute);
            }

            return attributes;
        }
    }
}

That last part was a little different than others mainly because we cannot use constructor injection in Attributes, so an easy way is just to create a simple method extension to extend Windsor and inject the properties in an already created instance:


using System;
using System.Linq;

namespace Castle.Windsor.Mvc {
    public static class WindsorExt {
        public static void BuildUp(this IWindsorContainer container, Type type, object instance) {
            var properties = type.GetProperties().Where(p => p.CanWrite && p.PropertyType.IsPublic);
            foreach (var propertyInfo in properties) {
                if (container.Kernel.HasComponent(propertyInfo.PropertyType)) {
                    propertyInfo.SetValue(instance, container.Resolve(propertyInfo.PropertyType), null);
                }
            }
        }
    }
}

Simple… you can grab the sourcecode from my bitbucket repository http://bitbucket.org/cprieto/castle-windsor-mvc

NOTE: before anybody else start screaming about using Service Locator: I don’t like at all the use of Service Locator, and I think it must be considered the atomic bomb in component injection (it’s even considered an antipattern as Mark Seeman describes). I’m writing this articule to sample how to to plug your own DI framework inside ASP.NET MVC 3 Preview 1… at least we have now a native way to do it.

Hoy tube el placer de compartir con mis camaradas “alt.netters” de Alt.Net Hispano en la VAN titulada “Webmatrix, Razor, MVC3 y otras hierbas”. Interesante la discusión y comentarios post VAN. Pronto publicaran los videos de la VAN para verlos offline, mientras tanto los dejo con las diapositivas :)

NOTA: El código de mi ejemplo de Windsor Service Locator para MVC 3 pueden encontrarlo en mi cuenta de Bitbucket http://bitbucket.org/cprieto/castle-windsor-mvc

Lanzamiento de Visual Studio 2010 en la comunidad

Hace poco más de una semana se llevó a cabo el lanzamiento comunitario de Visual Studio 2010 en la Ciudad de Guatemala, junto con compañeros como Carlos Lone (Microsoft Client Application Development MVP) y Manolo Herrera (Microsoft Sharepoint MVP) tube el honor de presentar las nuevas características y ventajas de esta nueva versión de ASP.NET 4.0 y Visual Studio 2010.

Como alguno siempre me pide las diapositivas de la presentación, se las dejo para que puedan descargarlas (en Slideshare).

¡Saludos!

Como ustedes habrán notado la comunidad ha estado en un estado de "pausa" por los últimos meses. Para aprovechar el momentum hemos estado organizando un evento de lanzamiento para Visual Studio 2010 a nivel comunitario. Los dejo con la información :)

Lugar: Oficinas de Microsoft, Edificio Torre Citibank (Intercontinental) [3a Avenida 13-78 Zona 10, Of 1101, Guatemala]

Fechas: Miércoles 23, Jueves 24, Viernes 25 de Julio

Horas: de 6pm a 9pm

Expositores y temas

Silverlight/WPF 4.0 Development

Expositor: Carlos Lone, Microsoft MVP Client Application Development, http://weblogs.asp.net/carloslone/

Fecha: Miércoles 23 de Junio

La nueva era de websites en el internet cada vez más demandan la inclusión de una mejor experiencia de usuario (UX) en donde la interactividad, contenido multimedia y uso del sitio sea más sencillo y amigable para los usuarios.

Se ha dicho de que las versiones anteriores de Silverlight estaban muy orientadas a relizar animaciones y a presentar imagenes  y videos con mejor definición. Sin embargo desde la versión 3.0 y ahora en la versión 4.0 la capacidad de poder utilizar esta herramienta para hacer aplicaciones de linea de negocio es cada vez más sencillo.

Acompañanos a descubrir todas las novedades de Silverlight y WPF en VS2010

- Demistificando Silverlight y WPF 4.0

- Novedades

- Construcción de aplicaciones de linea de negocio.

- Construiremos una aplicación 0 a 100.

Sharepoint 2010 Development

Expositor: Manolo Herrera, Microsoft MVP Sharepoint, http://jmhogua.blogspot.com/

Fecha: Jueves 24 de Junio

El desarrollo en SharePoint nunca antes ha sido tan fácil y práctico

- Desarrollando en Web Part Visual para SharePoint en 15 minutos

- Depurando e instalando tu código en SharePoint desde Visual Studio con presionar una sola tecla.

- Descubriendo el nuevo Developer Dashboard de SharePoint

- Conociendo el Client Object Model de SharePoint desde un aplicación Windows.

- Creando una Sandbox Solution para que nos sirve y ayuda.

Web development con ASP.NET 4.0

Expositor: Cristian Prieto, Microsoft MVP ASP.NET, http://www.cprieto.com

Fecha: Viernes 25 de Junio

ASP.NET ha evolucionado muchísimo en los últimos años con la adición de ASP.NET MVC y Dynamic Data, además de las mejoras continuas a la plataforma de WebForms y ASP.NET AJAX. Hablaremos de como aumentar la productividad y al mismo tiempo construir aplicaciones web que manejen de una manera transparente CSS, controles finos sobre el renderizado y markup al mismo tiempo que podemos mejorar SEO y muchas otras características nuevas en ASP.NET 4.0

 

El cupo es limitado, así que sugiero que corran al link de registro y aparten su lugar http://bit.ly/launchgt

¡Espero verlos en el lanzamiento!

NOTA: Recuerden imprimir y llevar al evento el ticket de inscripción que se genera en el momento del registro

Saludos,

.NET y Configuraciones – Parte 6

Bueno, miren que lejos hemos llegado con el asunto de las configuraciones :) pero no se preocupen, aún falta mucho más que aprender sobre nuestros amigos los archivos app/web.config y sobre nuestras configuraciones personalizadas, imagínense un mundo con menos y con configuraciones más claras y con mayor significado para el desarrollador. Hasta el momento hemos explorado secciones, grupos de secciones, elementos, colecciones todas personalizadas, hoy aprenderemos un poco acerca de validadores.

Element Validators

Imagínense que en su sistema de configuración necesitan validar que el número ingresado por el usuario en la configuración se encuentre dentro de un rango, o que el texto ingresado cumpla con una expresión regular o cumpla una longitud mínima o máxima (si, ya se, ambos se pueden lograr con un regex, pero para efectos de ejemplo digamos que son dos diferentes). Muchos quizás nos veremos tentados a obtener el valor de la configuración y posteriormente validarlo, bien, en el caso de elementos de configuración es buena idea abstenerse de hacerlo. La buena noticia es que tenemos a nuestra disposición toda una infraestructura de validación de valores de configuración y esta se lleva a cabo en el momento en que el ConfigurationManager lee los valores.

Los Validators son atributos especiales que acompañan a nuestros elementos de configuración, podemos definir nuestros propios validadores (ese será el tema de un post futuro) pero por defecto la framework nos empaca un par de validadores simples y sencillos:

IntegerValidator Valida un entero dentro de un rango
LongValidator Valida un número dentro de un rango
PositiveTimeSpanValidator Valida un timespan dentro de un rango positivo
RegexStringValidator Valida que una cadena cumple con una expresión regular
StringValidator Valida que una cadena debe cumplir una longitud máxima/mínima
TimeSpanValidator Valida un timespan dentro de un rango

Usar los validadores no puede ser más sencillo, simplemente adornamos nuestras propiedades o elementos con el atributo del validador que nos interesa y la framework de configuración se encarga del resto

using System;
using System.Configuration;

namespace Samples {
    public class SampleConfigurationSection : ConfigurationSection {
        [ConfigurationProperty("port", DefaultValue = 80)]
        [IntegerValidator(MaxValue = 100, MinValue = 20)]
        public int Port {
            get { return (int) this["port"]; }
        }

        [ConfigurationProperty("host", IsRequired = true)]
        public string Host {
            get { return (string) this["host"]; }
        }

        [ConfigurationProperty("timeout")]
        [TimeSpanValidator(MinValueString = "00:00:00",
            MaxValueString = "00:01:00")]
        public TimeSpan Timeout {
            get { return (TimeSpan) this["timeout"]; }
        }
    }
}

Para probar la configuración podemos usar este simple app.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="sample" type="Samples.SampleConfigurationSection, ValidatorSample"/>
  </configSections>
  <sample host="localhost" port="80" timeout="00:00:30" />
</configuration>

Y este pequeño programa de consola puede servirnos como simple prueba

using System;
using System.Configuration;

namespace Samples {
    internal class Program {
        private static void Main(string[] args) {
            var cfg = ConfigurationManager.GetSection("sample")
                as SampleConfigurationSection;
            if (cfg == null)
                return;

            Console.WriteLine("Host: {0}, Port: {1}, Timeout: {2}",
                cfg.Host, cfg.Port, cfg.Timeout);

            Console.ReadLine();
        }
    }
}

Si algún elemento no cumple con lo esperado por el validador el ConfigurationManager tirará una excepción de tipo ConfigurationErrorsException que a su vez en la propiedad Errors contendrá los ConfigurationException en forma de arreglo.

Mapeo, DTO’s y ViewModels en ASP.NET MVC

Los DTO’s –Data Transfer Objects- (algunos los llaman ViewModels/EditModels según el uso para el que existan) nacen por una razón específica: El modelo de lo que ves en la vista no representa directamente tu modelo de negocio. Mi ejemplo tradicional siempre ha sido el formulario de Login/Usuario/Contraseña.

Con el pasar del tiempo mi postura hacia este tema ha sido variada y se ha hecho bastante flexible. Por ejemplo, si tu modelo y tu aplicación es lo suficientemente sencilla y sabes que luego de eso jamás se va a modificar ni cambiar entonces es suficientemente fácil quedarte con el modelo y permearlo hacia la vista y vice versa, eso es precisamente lo que hace la generación Rails/Django/Whatever y lo que solemos hacer con MonoRail y Castle ActiveRecord, ¿la razón? simple, el modelo es sencillo, el dominio es sencillo y no es un proyecto complicado.

Para bien o para mal, en el entorno en que muchos se mueven no se ven cosas tan estáticas y los modelos y reglas de negocio son mucho más complejos siendo generalmente nuestros modelos de negocio , de hecho, si trasladamos eso a una visión de diseño orientado a servicio las cosas cambian aún más (ni hablemos de una "DDD shop"), lugares donde vemos que esta regla se revienta es en sistemas empresariales al estilo CRM/ERP o las siglas que sean…

En el contexto de una aplicación MVC se sobreentiende que el viewmodel es un concern de la vista, por lo tanto esta restringido a los conceptos de presentación. Recordemos también que un controller también es un concern de la vista (si, para aquellos que siguen creyendo que el controlador es la lógica de negocio, les vuelvo a romper el corazón en este momento), un buen lugar para que vivan los viewmodels es dentro de la aplicación MVC, surge el problema entonces, ¿cómo mapeo de un modelo de negocio al modelo de la vista?, bueno, les presento un par de ideas.

Usando el mapper como un servicio

Podemos usar un mapper automático como nuestro intermediario en el controlador entre el modelo de dominio y el viewmodel y de esta manera separar e injectar el mapper en el controlador

public class OrdersController : BaseController {
    readonly IOrdersRepository _ordersRepository;
    readonly IOrdersMapper _mapper;

    public OrdersController(IOrdersRepository ordersRepository, IOrdersMapper mapper) {
        _ordersRepository = ordersRepository;
        _mapper = mapper;
    }

    public ViewResult List() {
        var orders = _ordersRepository.FindAll();
        View(_mapper.Map(orders));
    }
}

Usando un Application Service

En este caso el Application Service se encarga de tomar las decisiones y luego retornar hacia el controlador los resultados, en este caso el controlador no sabe nada de la entidad original del dominio ni sobre el repositorio original, este es sumamente flexible cuando nuestro dominio original suele cambiar drásticamente o tomar decisiones muy complejas para delegárselas al controlador. En este caso es posible que a su vez el mapper sea inyectado y sea una dependencia del servicio. De hecho, podría ser que el servicio no use un mapper para nada, si no que simplemente arme el resultado usando varias uniones de otros resultados sobre la marcha (usando LINQ por ejemplo).

public interface IOrdersService {
    IEnumerable<OrderView> GetOrders();
}

public class OrdersController : BaseController {
    readonly IOrdersService _orderService;
    public OrdersController(IOrdersService orderService) {
        _orderService =  orderService;
    }

    public ViewResult List() {
        var orders = orderService.GetOrders();
        View(orders);
    }
}

Delegando el mapeo a un ModelBinder y ActionFilter

Debo admitir que aunque este es uno de mis resultados o formas favoritas de hacerlo en una aplicación MVC, lo siento a mi criterio demasiado “opionated” (entiéndase, fumado o cargado). En este escenario no es responsabilidad directa ni de un mapper ni de un servicio el retornar los resultados esperados, si no de un Model Binder junto con un ActionFilter en ASP.NET MVC. El controlador luciría algo así:

public class OrdersController : BaseController {
    readonly IOrdersRepository _ordersRepository;

    public OrdersController(IOrdersRepository ordersRepository) {
        _ordersRepository = ordersRepository;
    }

    [Automap(typeof(Order), typeof(OrderView)]
    public ViewResult List() {
        var orders = _ordersRepository.FindAll();
        View(orders);
    }
}

Este último caso es bastante flexible pero involucra que conozcamos bien que es un Model Binder y un ActionFilter, claro, nada que un par de minutos al frente de Visual Studio no pueda solucionar :)

Debo admitir que el caso de usar un Application Service me parece más natural si nuestra aplicación es simplemente un front end a una infraestructura orientada más hacia servicios que hacia un modelo directo de consumo (entiéndase, cosas como un ERP/CRM que probablemente usemos sus interfaces por otro lado y no solamente en nuestra aplicación de “CRUD”) y es mucho más flexible para casos en que necesitamos aislar completamente la “orquestración” del resultado del “despliegue” del resultado, suena extraño al principio pero se me ocurren bastantes casos donde esto se puede presentar.

Debo hacer notar que estas observaciones son meramente orientadas al contexto de una aplicación en ASP.NET MVC y no directamente se pueden trasladar a una aplicación o a un Tier en WCF, en este caso lo único que debemos compartir entre servicios es su esquema, no sus objetos.

Como siempre, espero sus comentarios o críticas al respecto, siempre son bienvenidas, recuerden, estamos en este barco del aprendizaje todos juntos como marineros.

¡Saludos!

UPDATE: Mi amigo José Romaniello me comenta del uso de una interface estilo IMapper en vez de una especializada para mapeo (como lo es IOrdersMapper), este patrón de uso lo considero igual al uso de una especializada, por lo tanto no la incluyo.

UPDATE 2: No incluyo implementaciones definidas de como crear estos mappers, para esto se puede hacer de forma directa o usando una herramienta de mapeo de clases como Automapper, pero eso lo dejo para otro post futuro.

.NET y Configuraciones – Parte 3

Ok, hasta el momento ya vimos como crear nuestras propias secciones y valores de configuración, además de darnos una vuelta por las opciones de crear y agregar elementos a nuestras secciones personalizadas. Hoy continuaremos indagando un poco más en el mundo de las configuraciones personalizadas en .NET.

Grupos de Secciones

Imagínense que la configuración de nuestra aplicación es mucho más compleja de lo usual y que además de elementos personalizados necesitamos agregar “subsecciones” de configuración. Dentro de la .Net Framework es algo común en ASP.NET. Crear secciones de configuración no puede ser más fácil, basta con crear las secciones como lo hemos estado haciendo hasta el momento. Tomemos por ejemplo las siguientes dos secciones:

public class SampleSection : ConfigurationSection {
    [ConfigurationProperty("name", IsRequired = true)]
    public string Name {
        get { return (string) base["name"]; }
        set { base["name"] = value; }
    }

    [ConfigurationProperty("port", DefaultValue = 80)]
    public int Port {
        get { return (int) base["port"]; }
        set { base["port"] = value; }
    }
}

public class AnotherSection : ConfigurationSection {
    [ConfigurationProperty("times", IsRequired = true)]
    public int TimesPerDay {
        get { return (int) base["times"]; }
        set { base["times"] = value; }
    }
}

Basta ahora con crear un ConfigurationSectionGroup para obtener ambas secciones dentro de un mismo grupo

public class SampleSectionGroup : ConfigurationSectionGroup {
    [ConfigurationProperty("sample")]
    public SampleSection Sample {
        get { return (SampleSection) Sections["sample"]; }
    }

    [ConfigurationProperty("another")]
    public AnotherSection Another {
        get { return (AnotherSection) Sections["another"]; }
    }
}

Agregarla en el web.config es un poco más laborioso pero continúa siendo sencillo

<configuration>
  <configSections>
    <sectionGroup name="sampleGroup" type="WebApplication2.SampleSectionGroup">
      <section name="sample" type="WebApplication2.SampleSection"/>
      <section name="another" type="WebApplication2.AnotherSection"/>
    </sectionGroup>
  </configSections>
  <sampleGroup>
    <sample name="sample" port="31" />
    <another times="5" />
  </sampleGroup>
</configuration>

Creo que para estas alturas el usarla en el código debe ser algo sencillo y "straighforward"

.NET y Configuraciones – Parte 2

Anteriormente habíamos conversado acerca de como trabajar nuestras propias secciones “customizadas” de configuración usando las facilidades de configuración que nos da la .Net Framework. Como vemos es sumamente fácil crear nuestras secciones “personalizadas”. Conversaremos hoy un poco más de como sacarle mayor provecho y extender nuestras secciones de configuración y así sacar mucho mayor provecho.

Elementos personalizados anidados

Observemos el siguiente snippet de código

public class HostInfo : ConfigurationElement {
    [ConfigurationProperty("server", DefaultValue = "localhost")]
    public string Server {
        get { return (string) base["server"]; }
        set { base["server"] = value; }
    }

    [ConfigurationProperty("port", DefaultValue = 80)]
    public int Port {
        get { return (int) base["port"]; }
        set { base["port"] = value; }
    }

    [ConfigurationProperty("ssl", DefaultValue = false)]
    public bool IsSecure {
        get { return (bool) base["ssl"]; }
        set { base["ssl"] = value; }
    }
}

Aunque nos recuerda a la forma en que creamos una sección de configuración, realmente estamos creando un elemento de la configuración (ConfigurationElement). En otras palabras, podemos tener elementos anidados y de esa manera lograr que nuestros elementos de configuración obedezcan a una más clara semántica. Utilizarlo en la sección de configuración no puede ser más fácil

public class ServerConfigurationSection : ConfigurationSection {
    [ConfigurationProperty("name", IsRequired = true)]
    public string Name {
        get { return (string)base["name"]; }
        set { base["name"] = value; }
    }

    [ConfigurationProperty("host")]
    public HostInfo Host {
        get { return (HostInfo)base["host"]; }
        set { base["host"] = value; }
    }
}

Usarlo no puede ser más fácil que esto

<configuration>
  <configSections>
    <section name="server" type="WebApplication2.ServerConfigurationSection"/>
  </configSections>
  <server name="myconfiguration">
    <host server="192.168.1.1" port="81"/>
  </server>
</configuration>

.NET y configuraciones – Parte 1

Hace unos días 0Gis0 publicó un buen artículo sobre el archivo de configuración en .Net y como crear nuestras propias secciones personalizadas. Bien, he decidido ahondar un “poco” más en el asunto aprovechando el hecho que tengo prometido a un par de amigos desde hace ratos que publicaría acerca de configuración en .Net, es buena idea que antes le den una rápida leída al artículo que en cuestión.

Recapitulando lo que nos menciona nuestra compañera, es sencillo crear una sección personalizada de configuración en .Net, basta solamente de heredar de la clase ConfigurationSection y listo. Bueno, no tan rápido, hay un par de cosas de hacer notar, la sección personalizada de configuración debe exponer propiedades que se mapean a las opciones de configuración, estas propiedades deben estar “adornados” con los atributos ConfigurationProperty y obligatoriamente debemos indicar a que atributo de la sección de configuración a la cual se mapea. A partir de esto usamos el indexer de la clase base y la casteamos al tipo que necesitamos.

public class SimpleConfigurationSection : ConfigurationSection {

    [ConfigurationProperty("port")]
    public int Port {
       get {
           return (int) this["port"];
       }
       set {
           this["port"] = value;
       }
    }
}

Esto correspondería a algo así en el archivo de configuración

<configSections>
    <section name="smtp" type="SimpleConfigurationSection, MyAssembly" />
</configSections>
<smtp port="25">

Simple y sencillo, de igual manera podemos indicar si el elemento es requerido y también el valor por defecto de la propiedad con simplemente modificar un poco el atributo

public class SimpleConfigurationSection : ConfigurationSection {

    [ConfigurationProperty("port", DefaultValue = 80, IsRequired = true)]
    public int Port {
       get {
           return (int) this["port"];
       }
       set {
           this["port"] = value;
       }
    }
}

Simple y sencillo, como lo menciona nuestra amiga. Con esto como base podemos acceder la configuración de forma simple

var config = (SimpleConfigurationSection) ConfigurationManager.GetSection("smtp");
var port = config.Port;

Con esto como base estamos listos para profundizar un poco más en el asunto. En la próxima entrega veremos como definir jerarquías de configuración en nuestras secciones personalizadas.

Saludos!

UPDATE: otros post de la serie han sido publicados

Lo nuevo en ASP.NET 4.0: Proyectos

Una de las primeras cosas que nos encontraremos diferentes (o ligeramente diferentes) al crear un proyecto web nuevo en ASP.NET 4.0 con Visual Studio 2010, es las ligeras variaciones con respecto a los proyectos web existentes, una vista rápida a los templates existentes en Visual Studio 2008 SP1 (tengan en cuenta que tengo un par de templates de usuario agregados)

New_Project-2010-04-10_22.11.42

Y el mismo cuadro mostrado en el nuevo cuadro de diálogo de Visual Studio 2010

New_Project-2010-04-10_22.15.26

Algo que notamos a simple vista es la existencia de un tipo “nuevo” de template de web application: Empty Web Application, realmente la Empty Web Application es algo muy similar al template de Web Application que encontrábamos en ASP.NET 3.5 pero sin Default.aspx ni Global.asax, es un template simple, excelente para crear aplicaciones web que simplemente seran repositorios de servicios o que luego tendran nuestro propio layout específico.

WebApplication4_-_Microsoft_Visual_Studio-2010-04-10_22.17.19

El contraparte de la Empty Web Application es la Web Application ejemplo, esta incluye scripts de javascript (la librería JQuery ahora es incluída junto con ASP.NET, si, javascript ahora es al fin considerado ciudadano de primer tipo en ASP.NET) junto con páginas para el manejo de las cuentas típicas del Membership y Role Providers de ASP.NET.

WebApplication5_-_Microsoft_Visual_Studio-2010-04-10_22.18.02

El sitio por defecto incluye estilos y una master page que para serles sincero no se ve nada mal (le recordaran mucho al template que venía con ASP.NET MVC)

SS-2010-04-10_22.23.09

Otros cambios notables que podemos notar en los templates de ASP.NET 4.0 son:

  • Se eliminó el proyecto de ASP.NET Web Service Application (si, los proyectos con asmx), recuerden que desde hace ratos existe WCF y los proyectos de servicio de WCF son la forma recomendada, ASMX es cosa del pasado.
  • El proyecto de servicio de WCF se movió a la categoría de WCF
  • Los dos proyectos de Dynamic Data fueron renombrados, probablemente por branding.

NOTA: Eso no implica que no pueden hacer ASMX’s en ASP.NET 4.0, simplemente ya no hay un proyecto para hacerlo.

El cuadro de diálogo para crear websites cambió también:

New_Web_Site-2010-04-10_22.31.45

Personalmente hubiera preferido que eliminaran el concepto de Website, pero creo que mucha gente en ese sentido diferirá grandemente conmigo :)

Por último, el landscape actual de ASP.NET 4.0 y su relación con los diferentes componentes puede ilustrarse de la siguiente manera (incluyendo su relación con librerías como JQuery):

image_2

¡Hasta la próxima pronta entrega!