Blog de Nicoloco

ASP.NET – Entity Framework – Windows Azure – How To | Todo en C#

  • MVP Visual C#

  • MCC 2011

    MCC 2011
  • MCS Colombia

    Microsoft Community Specialist
  • Comunidades

    Lider de BogotaDotNet
  • Encuentrame en

    Sigueme en Twitter
  • Mi perfil de LinkedIn

[CSharp][Roslyn] InteractiveCS

Publicado por nicolocodev en 28 marzo, 2013

Hace unos días tuve la oportunidad de ver a un colega que usa una maquina MAC, todo iba bien hasta que el hombre lanzó una de esas IDEs que me cautivan, que son tan extremadamente sencillas e “improductivas” (pero llamativas para mi) por su estilo de “hacker“. Esta IDE no era más que una Consola REPL con cierta transparencia y letras verdes donde se escribía código y se tenía una respuesta inmediata. No es la primera vez que veo interfaces con este estilo tan “cautivante“, las he visto en varias máquinas pero nunca he trabajado con IDEs así. En el tiempo que llevo escribiendo código he tenido la oportunidad de interactuar con varias herramientas y variados lenguajes, hasta que un día llegué a Visual Studio :D , realmente adoro este IDE, así como adoro el lenguaje C# (Momento fanboy). Visual Studio es de seguro el mejor IDE que ha creado la humanidad, desde la versión 2010 de Visual Studio no se necesitan más herramientas para gestionar todo el ciclo de vida de un proyecto. Poderosas herramientas para hacer debug, refactoring, todo un set para trabajar con metodologías agiles… ¡en fin! Visual Studio es genial! Pero no puedo desconocer que siento cierto encanto por la consola y escribir código como lo hizo aquel desarrollador en sus demostraciones… así que me di a la tarea de escribir mi propia REPL para escribir código C#. En este post voy a describir como lo tengo pensado :P

Esto no es posible con C#!

Todos sabemos que escribir un programa con C# debe ser compilado, si quieres hacerlo por fuera de Visual Studio puedes escribir desde tu editor de texto preferido y emplear el Microsoft C# Compiler (csc.exe), como resultado tendremos un .exe si el código fuente tiene un punto de entrada (método main). Entonces ¿Cómo conseguir una interacción inmediata con el usuario que desea escribir código C# por fuera de Visual Studio?

Roslyn al rescate

Ya llevo algunos meses trabajando con el proyecto Roslyn, es realmente maravilloso poder tener el compilador como servicio y en este caso me iba a servir bastante. El proyecto Roslyn expone tres conjuntos de APIs, entre las que está el Scrpting API que hace parte del Compiler API, esta nos expone un contexto de ejecución de código y ScriptEngine que permite la evaluación de expresiones. Con esto entonces soluciono mi problema de la interpretación del código C# :D ya no lo compilo, lo interpreto como cualquier lenguaje de script :P

InteractiveCS

Así pues cierta envidia me motivo a tener una consola con ese estilo y el estilo es que más me llama la atención, así que decidí escribir un proyecto WPF con una única ventana y cierta transparencia que le da ese aspecto tan genial. Todo el código XAML que necesite:

<Window x:Class="Interactivecs.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        WindowStartupLocation="CenterScreen"
        WindowStyle="None"
        AllowsTransparency="True"
        Height="600"
        Width="800"
        Background="Black"
        Opacity="0.9"
        >
    <Grid>
        <RichTextBox Foreground="Green"
                     Background="Transparent"
                     CaretBrush="White"
                     FontSize="18"
                     FontFamily="Consolas"
                     x:Name="richTextBoxPrincipal"
                     PreviewKeyDown="RichTextBoxPreviewKeyDown"
                     Cursor="None"/>

    </Grid>
</Window>

En el código fuente en su mayoría es para controlar la interacción con el usuario… donde realmente ocurre la magia es con el uso de:

using Roslyn.Compilers;
using Roslyn.Scripting;
using Roslyn.Scripting.CSharp;

Que nos permite hacer uso de ScriptEngine y Session para poder procesar el código que el usuario ingresa:

        private void ProccessCommand(string currentCode)
        {
            try
            {
                _result = _session.Execute(currentCode);
            }
            catch (CompilationErrorException errorException)
            {
                var run = new Run(errorException.Message) {Foreground = new SolidColorBrush(Colors.Red)};
                _flowDocument.Blocks.Add(new Paragraph(run));
            }
            if (_result == null)
            {
                AddStartContentLine();
                return;
            }
            _flowDocument.Blocks.Add(new Paragraph(new Run(_result.ToString())));
            AddStartContentLine();
        }

El código completo:

    public partial class MainWindow
    {
        private readonly ScriptEngine _scriptEngine;
        private readonly Session _session;
        private string _currentDirectory;
        private FlowDocument _flowDocument;
        private object _result;

        public MainWindow()
        {
            _scriptEngine = new ScriptEngine();
            _session = _scriptEngine.CreateSession();
            _scriptEngine.CreateSession();
            InitializeComponent();
            Loaded += MainWindowsLoaded;
        }

        private void MainWindowsLoaded(object sender, RoutedEventArgs e)
        {
            _currentDirectory = string.Format("{0}>",
                                              Environment.GetFolderPath(Environment.SpecialFolder.UserProfile));
            _flowDocument = new FlowDocument();
            _flowDocument.Blocks.Add(new Paragraph(new Run(_currentDirectory)));
            richTextBoxPrincipal.Document = _flowDocument;
        }

        private void RichTextBoxPreviewKeyDown(object sender, KeyEventArgs e)
        {
            switch (e.Key)
            {
                case Key.Back:
                    {
                        TextPointer start = richTextBoxPrincipal.CaretPosition;
                        string text = start.GetTextInRun(LogicalDirection.Backward);
                        if (text == _currentDirectory)
                            e.Handled = true;
                    }
                    break;
                case Key.Enter:
                    string currentCode = richTextBoxPrincipal.CaretPosition.GetTextInRun(LogicalDirection.Backward);
                    ProccessCommand(currentCode);
                    e.Handled = true;
                    break;
                case Key.Left:
                    {
                        TextPointer start = richTextBoxPrincipal.CaretPosition;
                        string text = start.GetTextInRun(LogicalDirection.Backward);
                        if (text == _currentDirectory || text == string.Empty)
                            e.Handled = true;
                    }
                    break;
            }
        }

        private void ProccessCommand(string currentCode)
        {
            try
            {
                _result = _session.Execute(currentCode);
            }
            catch (CompilationErrorException errorException)
            {
                var run = new Run(errorException.Message) {Foreground = new SolidColorBrush(Colors.Red)};
                _flowDocument.Blocks.Add(new Paragraph(run));
            }
            if (_result == null)
            {
                AddStartContentLine();
                return;
            }
            _flowDocument.Blocks.Add(new Paragraph(new Run(_result.ToString())));
            AddStartContentLine();
        }

        private void AddStartContentLine()
        {
            _flowDocument.Blocks.Add(new Paragraph(new Run(_currentDirectory)));
            richTextBoxPrincipal.Document = _flowDocument;
            richTextBoxPrincipal.CaretPosition = richTextBoxPrincipal.CaretPosition.DocumentEnd;
        }
    }

Descarga la versión 0

He subido este proyecto a GitHub si quieren descargarlo, probarlo y mejorarlo :D , cualquier mejora/feedback será bienvenido. https://github.com/nicolocodev/interactivecs

Como siempre… cualquier duda, comentario o sugerencia es bienvenido.

Hasta el próximo post.

Publicado en C#.NET | 2 Comentarios »

[Windows Azure][IIS Express] ¿Por qué los Request se hacen con otro puerto?

Publicado por nicolocodev en 22 marzo, 2013

Cuando trabajamos con el Windows Azure Compute Emulator (en entornos locales de desarrollo) podemos notar un comportamiento que de entrada puede parecer extraño, si nosotros especificamos un puerto para trabajar con nuestros sitios ¿por qué los Request se realizan con otro?

Sigo sin entender, muéstrame el código

Supongamos que tenemos un proyecto Web trabajando en el puerto 80:

Si revisamos el Request en uno de sus controladores podemos ver lo siguiente:

Ahora entra en juego Windows Azure y agregamos este site como un role para nuestro CloudService, al ejecutar se lanzará el Windows Azure Compute Emulator y veremos algo como lo siguiente:

Pero ¿por qué? Si revisamos el Compute Emulator UI veremos lo siguiente:

Pues parece que si está saliendo por el puerto 80 (esto es porque ese es el endpoint que viene definido en el role):

Pero… si damos un vistazo al IIS Express:

Vemos que ahora el sitio está trabajando en otro puerto :o Esto es porque cuando se despliega en el Development Fabric el emulador creara un balanceador para nosotros con el puerto 80 (este es el que se ve en el Detail Service), y se creará un WebSite para cada instancia del rol asignándole una IP con el formato 127.255.0.x, con el puerto inmediatamente disponible, es decir que si agrego otra instancia a mi Cloud Service se debería crear otra aplicación con dirección 127.255.0.1:81 por ejemplo:

Y lo que ocurre entonces es que el Request se hace con el puerto del sitio creado por el emulador (con la dirección del Balanceador), en este caso :81 y no el puerto del balanceador de carga. Si realizo la petición a la dirección que me ha generado el emulador para el Role:

¿Pero por que en la nube no pasa esto?

Este comportamiento solo sucede en el entorno local, porque cuando se despliega el CloudService sobre Windows Azure este corre sobre una Maquina virtual y el balanceador de carga corre en un host distinto a este, es decir, si es posible que los dos atiendan por el mismo puerto porque son host distintos.

Espero sea de utilidad la aclaración.

Hasta el próximo post.

Publicado en ASP.NET, Windows Azure | Deja un Comentario »

[Web API] Versionando nuestros servicios – Evolución de la representación por adición

Publicado por nicolocodev en 10 marzo, 2013

Siempre que trabajamos con servicios HTTP (sean REST o no) un factor que nos preocupa es el del versionamiento del servicio, la constante evolución del mismo y como los distintos clientes interactuaran con este sin romper lo que se ha construido.

Esta evolución puede darse por distintos aspectos, uno de los más frecuentes es la evolución de nuestros recursos (que vienen a ser identificados por una URI). Estos recursos son conceptuales y la única manera de materializarlos es por medio de representaciones (html, json, xml…) y cada uno de los formatos que soportemos brindaran a cada petición de cada cliente una forma de obtener el mismo recurso, esto es lo que conocemos como negociación de contenido.

Si intentamos llevar esta conceptualización a un entorno con ASP.NET Web Api por ejemplo, tendríamos “entidades” que no son más que nuestros recursos, así podemos tener una clase Persona definida de la siguiente manera:

    public class Persona
    {
        public string Nombre { get; set; }

        public string Apellido { get; set; }
    }

Y un controlador que se encargue de entender las peticiones a la URI que identifica el recurso, así:

    public class PersonaController : ApiController
    {
        private static List<Persona> _personas = CreatePersonas();

        private static List<Persona> CreatePersonas()
        {
            return _personas ?? (_personas = new List<Persona>
                                                 {
                                                     new Persona
                                                         {
                                                             Nombre = "Nicolas",
                                                             Apellido = "Herrera"
                                                         }
                                                 });
        }

        // GET api/values
        public IEnumerable<Persona> Get()
        {
            return _personas;
        }

        // GET api/values/5
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        public void Post([FromBody]string value)
        {
        }

        // PUT api/values/5
        public void Put(int id, [FromBody]string value)
        {
        }

        // DELETE api/values/5
        public void Delete(int id)
        {
        }
    }

Y un cliente que se encarga de consumir esta información implementando la negociación de contenido que viene predeterminada en Web Api

        private static void Main(string[] args)
        {
            var httpClient = new HttpClient();
            httpClient.BaseAddress = new Uri("http://localhost:64186/api/persona");
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/xml"));
            string json = httpClient.GetStringAsync(string.Empty).Result;
            var personas = JsonConvert.DeserializeObject<List<PersonaCliente>>(json);

            Console.WriteLine("Personas");
            foreach (PersonaCliente personaCliente in personas)
            {
                Console.WriteLine("Nombre y apellido: {0} {1}", personaCliente.Nombre,
                                  personaCliente.Apellido);
            }
            Console.ReadKey();
        }
    }

    public class PersonaCliente
    {
        public string Nombre { get; set; }

        public string Apellido { get; set; }
    }

Si nuestra entidad evolucionara adicionando una nueva propiedad sería lógico que su representación lo hiciera también y esta es la característica de versionamiento más pequeña que podemos encontrar, pues es muy común que necesitemos más información de una persona, información como por ejemplo la edad. Así:

    public class Persona
    {
        public string Nombre { get; set; }

        public string Apellido { get; set; }

        public int  Edad { get; set; }
    }

El primer approach y uno de los más usados es el versionamiento por la URI, y personalmente no es una solución que me agrade mucho, pues el concepto sigue siendo el mismo y no debería tener una nueva URI, pues esto significaría que es un nuevo concepto.

Cuando se le agregan elementos a la representación del recurso no debería afectar en nada a un cliente en específico porque en ese momento el ignora la existencia de ese elemento, en muchas ocasiones se rompe dicho contrato es porque se remueven elementos de la representación, elementos que desconocemos como los trabajaba cada uno de los clientes.

Teniendo esto presente a mi cliente de consola le dará igual que le agregué a la representación mientras el siga trabajando con dicha versión del API no rompo nada. Esta nueva propiedad será ignorada.

Ahora la pregunta es, como se apega mi cliente a una nueva versión si no estamos realizando peticiones a URIs distintas? La respuesta viene dada por la negociación de contenido y la cabecera accept por supuesto. Pero esto ya da para un segundo post que quiero escribir en mas detalle y no como un punto adicional de este.

Hasta el próximo post.

Publicado en ASP.NET Web API | Deja un Comentario »

Xamarin y yo – Bienvenida

Publicado por nicolocodev en 26 febrero, 2013

La semana pasada Miguel de Icaza anunció con esta publicación la posibilidad a los Microsoft MVPs de obtener una copia gratuita de Xamarin Business edition for iOS and Android y pues esta es una de esas oportunidades que no se puede dejar pasar, no solo por el hecho que sea gratis por ser MVP sino porque como dice Joseph Hill en el artículo que anuncia la oferta los MVPs somos criaturas con una relación simbiótica con el IDE (el mejor IDE creado por la humanidad) y podremos explotar muchas de las características del producto y contribuir con el proyecto sino es con código con algo que se valora mucho… dando feedback del producto.

Hasta aquí todo muy bonito, pero y ¿qué es Xamarin? y ¿por qué estoy tan emocionado?

Desarrollo para dispositivos móviles

Cuando conocí el concepto de desarrollo para dispositivos móviles lo conocí en la academia con Java, pequeñas formas y cosas no muy avanzadas, jamás hice algo que no fuera estrictamente académico.

Luego conocí los buenos Windows Mobile y el Compact Framework que para mí eran altamente competitivos en proyectos reales, en fin siempre estuve en el mercado sobre plataforma Microsoft mientras a su lado crecían los mercados de IOs y Android. Luego llegó el Windows Phone y redefinió un nuevo rumbo para Microsoft en el mercado sistemas operativos para dispositivos móviles, aprendieron mucho de todo lo vivido con Windows Mobile.

Nunca miré hacía otros lados porque mi trabajo no era apuntarle a estos dispositivos, cuando trabajé Windows Mobile era de forma corporativa, nada personal, pero no veía mucha fuerza (económica) allí, me pagaban solo por software a la medida y vivía feliz así. En cambio ahora vemos mucha fuerza con el mercado de las Apps y el tema de grandes capacidades de cómputo en pequeños dispositivos (tema por el que siempre se ha caracterizado IPhone por ejemplo).

Si quieres lanzarte por desarrollar para IPhone de entrada aprendes Objetive C (corríjanme si me equivoco) y si ingresas al mundo Android te encuentras con Java, aparte claro de sus SDKs correspondientes. Personalmente conocí en su tiempo alguito Java, Python, C y C++ llegando por ultimo al lenguaje y plataforma con la que trabajo y me consigo el dinero la para cerveza y la conexión a internet… mi amado C#! y es precisamente esto lo que viene a solucionarme Xamarin, la posibilidad de desarrollar aplicaciones nativas para IOs, Android y MAC con Visual C# y ahora con la posibilidad de trabajarlo con el IDE que más me gusta! ¿Desarrolladores altamente competitivos? ¿Dónde?

La nube esta lista.

Algo que siempre argumento en mis conferencias es que un backend solido es un factor determinante para el triunfo de muchas Apps (como muchas de las que me gustan) y si le sumo a esta oportunidad de desarrollo multiplataforma la posibilidad de todo el poder de Windows Azure Mobile Services? Las oportunidades son ilimitadas!

Ya basta Nicolás! Screenshots!

Realmente es un proyecto que me gusta mucho (y más ahora empapado del tema de las Apps) así que la emoción es inmensa y aquí van algunas fotografías de la instalación y de mi IDE para que se antojen.

Por ahora me dedicaré a jugar un poco con mi nuevo juguete y ya les estaré contando.

Hasta el próximo post.

Publicado en C#.NET, En general | 3 Comentarios »

[IIS Express] Configuration web for ASP.NET 4.5 failed

Publicado por nicolocodev en 25 febrero, 2013

En una ocasión quise iniciar un proyecto asp.net MVC con Framework 4.5 y recibí el siguiente error:

En esa ocasión no estaba en mi maquina así que supuse que habían roto algo allí pero no era mi culpa :P , ahora me ha pasado en mi máquina y no se siente muy agradable, pues ahora es personal.

Historia

Como tal no existe un Framework 4.5, ya verán a que me refiero, si miramos en el Application pool de IIS veremos algo como lo siguiente:

Y si miramos el sistema de archivos (para usar el aspnet_regiis.exe) veremos lo siguiente:

En un blog de MSDN
esta esté buen artículo donde explican esta característica del versiona miento del Framework.

Teniendo presente esto surge la pregunta, y entonces porque Visual Studio se queja por la versión 4.5?

Si miramos IIS Express maneja un Application Pool en el archivo de configuración en la sección applicationPools

Hasta aquí ya se puede pensar en varias soluciones:

Solución 1

Pues muy simple, como la teoría dice que no existe diferencia en los Application Pools de aplicaciones creadas para Framework 4.5 basta con ubicar el Site en el archivo de configuración y agregar el atributo applicationPool indicándole que deseamos usar el Clr4IntegratedAppPool :

Solución 2

Ya sé que estarás pensando que hacer esto una y otra vez con cada uno de los proyectos puede ser tedioso, por fortuna en la sección de Sites podemos definir un elemento applicationDefaults, así:

Y con esto ya no tendrás que entrar a modificar cada site que se te cree.

Solución 3, bonus

En caso que pienses, hey! que tonto es Nicolás! (lo soy) porque no define la versión especifica del Framework en el Application Pool?, así?:

Con estos enfoques (el segundo) solucioné mi problema y ya no recibo más ese molesto error.

Espero les sea de utilidad.

Hasta el próximo post.

Publicado en ASP.NET | Deja un Comentario »

 
Seguir

Recibe cada nueva publicación en tu buzón de correo electrónico.

Únete a otros 56 seguidores

%d bloggers like this: