[ASP.NET MVC] Usa sólo el motor de vistas que necesites en tu aplicación.

Introducción

Cuando creamos un proyecto ASP.NET MVC, por defecto tenemos habilitados  los 2 motores de vistas que incluye el framework de MVC:

  1. El motor de vistas de Web Forms.
  2. El motor de vistas de Razor.

Para comprobar que esto es verdad y no te miento, basta con crear una aplicación web de ASP.NET MVC, borrar una de las vistas que vienen por defecto en la plantilla y tratar de acceder a ella:

image

Es más, por defecto siempre usa como primera opción el motor de vistas de Web Forms y sino encuentra ninguna vista en alguna de las localizaciones que están establecidas por defecto (basandose en conveciones), lo intentará con el motor de vistas de Razor, y sino encuentra ninguna, recibiremos ese bonito error.

Que os recomiendo yo, que sólo uses el motor de vistas que necesites, porque ese tiempo extra de estar localizando las vistas te lo puedes ahorrar y mejorar un poquito el rendimiento de tu aplicación ASP.NET MVC.

¿Como le digo a ASP.NET MVC qué motor de vistas quiero usar?

En ASP.NET MVC esto es muy sencillo de configurar. Vamos a decirle a ASP.NET MVC que use Razor como motor de vistas. Para ello vamos al Global.asax y añadimos estas 3 líneas al principio del método Application_Start:

var razorViewEngine = new RazorViewEngine();

ViewEngines.Engines.Clear();

ViewEngines.Engines.Add(razorViewEngine);

Al final quedaría así:

public class MvcApplication : HttpApplication

{

    protected void Application_Start()

    {

        var razorViewEngine = new RazorViewEngine();

        ViewEngines.Engines.Clear();

        ViewEngines.Engines.Add(razorViewEngine);

 

        AreaRegistration.RegisterAllAreas();

        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);

        RouteConfig.RegisterRoutes(RouteTable.Routes);

        BundleConfig.RegisterBundles(BundleTable.Bundles);

    }

}

Volvemos a ejecutar y comprobamos que ahora solo usa el motor de vistas de Razor:

image

Con esas 3 líneas ya estamos ahorrandonos ese tiempo extra.

Buen fin de semana a todos!!!

[C#] Sobreescribir ToString en nuestras clases para mejorar la información en modo depuración

Seguro que como yo muchas veces te has preguntado cual puede ser una razón para sobreescribir ToString en alguna clases, verdad?

Yo hace poco empecé a hacerlo para mejorar la información que recibo en modo depuración en Visual Studio de las listas, colecciones, enumerados

Ejemplo

Supongamos que partimos de la siguiente clase:

public class Product

{

    public string Code { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

 

    public Product(string code, string name, string description)

    {

        Code = code;

        Name = name;

        Description = description;

    }

}

Ahora vamos a crear una lista de productos:

class Program

{

    static void Main(string[] args)

    {

        var products = new List<Product>

        {

            new Product("XBOX1", "XBox One", "New generation of games and entertainment."),

            new Product("PS4", "Play Station 4", "New generation of games and entertainment."),

            new Product("WIIU", "Wii U", "New generation of games and entertainment.")

        };

    }

}

Y vamos a depurar este pequeño programa:

image

De un simple vistazo no podemos ver que contiene la lista de productos, solo que son del tipo PocNet.Product y que hay 3 y para ver que hay en cada uno deberíamos desplegar otro nivel:

image

El caso es que el intellisense de Visual Studio para mostrarnos esa información llama al método ToString de los objectos y por defecto nos muestra el tipo del objeto. Para modificar este comportamiento vamos a sobreescribir ToString y a mostrar el código del producto:

public class Product

{

    public string Code { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

 

    public Product(string code, string name, string description)

    {

        Code = code;

        Name = name;

        Description = description;

    }

 

    public override string ToString()

    {

        return String.Format("Code - {0}", Code);

    }

}

Depuramos la aplicación, y ya en el primer nivel podemos ver al menos el código del producto que me aporta más información que el tipo.

image

Y como plus, si quieres mostrar por ejemplo todos los elementos de la clase producto vamos a utilizar JSON.NET para que lo serialice a JSON:

public class Product

{

    public string Code { get; set; }

    public string Name { get; set; }

    public string Description { get; set; }

 

    public Product(string code, string name, string description)

    {

        Code = code;

        Name = name;

        Description = description;

    }

 

    public override string ToString()

    {

        return JsonConvert.SerializeObject(this);

    }

}

Depuramos, y ya tenemos una vista de todas las propiedades y sus valores en el primer nivel:

image

Un saludo y buen fin de semana a todos.

[NoSQL] Replace vs Modified arrays en MongoDb

Introducción

MongoDb es una base de datos documental (Orientadas a documentos) y forma parte de la familia de las bases de datos NoSQL. MondoDb almacena la información en documentos en vez de guardar los datos en tablas relacionales como lo hacen las base de datos relacionales. Estos documentos se almacenan en un formato propio de MongoDb que es BSON (JSON binario) lo que hace que el sistema de almacenamiento sea muy dinámico y no esté ligado a un esquema como en las bases de datos relacionales (se conoce como schema free).

Para trabajar con MongoDb existen una gran variedad de drivers. Yo voy usar el driver oficial de C# que puedes añadirlo a trus proyectos desde Nuget.

Bueno, vista una pequeñisima introducción teórica a que es MongoDb. Recomendaría para seguir el artículo, leer un poco acerca de arrays en MongoDb y documentos embebidos. Pues dicho esto, vamos a ver que diferencia hay entre las operaciones Replace y Modified y cual usar en cada caso.

Caso práctico

Debemos usar Replace siempre que nuestra prioridad no sea el rendimiento y la concurrencia y si modelar un dominio de aplicación y que este no esté acoplado a MongoDb (Ya veremos más adelante porque).

Disclaimer: Quizás no sea el mejor ejemplo del mundo y el más acertado pero es sufiente para ver la diferencia entre ambos comandos.

Por ejemplo, imaginad que estamos diseñando un blog para una pequeña empresa. En este caso contamos con que el número de comentarios que se harán sobre un post será muy pequeño (Tal vez 5 o 6 comentarios) puesto que esta empresa no es muy conocida y la temática será sobre la vida en dicha empresa y solo los clientes comentarán los artículos. En este caso hemos decidido modelar un dominio de aplicación para nuestro blog y los vamos a  usar en un controlador para añadir un comentario:

[HttpPost]

public ActionResult AddComment(string message, string id)

{

    var post = GetPost(id);

    var comment = new Comment(message);

    

    post.AddComment(comment);

    _blogContext.Posts.Save(post);

 

    return RedirectToAction("Details", new {id});

}

El método Save si no existe  el documento lo inserta y si existe lo reemplaza (http://docs.mongodb.org/manual/tutorial/modify-documents/). Como dijimos anteriormente el rendimiento no es nuestra prioridad y y sí diseñar un modelo no anémico. Pero, ¿Que pasa si usamos esta aproximación en un blog cuyas visitas e interacción de los usuarios se cuentan por miles? Pues que vamos a encontrarnos con un problema de rendimiento y/o concurrencia y vamos a ir viendo por qué.

Lo primero que vamos a hacer es ver que pasa cuando ejecutamos un Replace sobre un documento en el que hemos añadido un nuevo elemento a un array de documentos.

Voy a usar un cliente visual para administrar MongoDb, en mi caso MongoVue:

image

Como podmeos observar, tenemos una colección donde almacenamos los posts y dentro de cada post tenemos un array para almacenar los comentarios (Hay que vigilar cuantos comentarios vamos a insertar y su tamaño ya que el tamaño máximo de un documento en MongoDb es de 16Mb)

Vamos a activar el profiler de MongoDb sobre la base de datos de blog para ver que pasa cuando añadimos un nuevo comentario:

image

image

o desde la consola de MongoDb con el comando db.setProfilingLevel(2)

Cuando activamos el profiler se crea una colección llamada system.profile

image

Añadimos un nuevo comment y vamos a buscar la operación de update:

image

o desde la consola de MongoDb con el comando db.system.profile.find({ “op” : “update” }).limit(50)

Y vamos a estudiar el resultado:

image

Como podemos observar el campo updateobj contiene el objeto post que había antes pero ahora la colección de comentarios tiene 2, el anterior que había y el nuevo que hemos añadido, es decir que cada vez que añadamos un nuevo comentario hará un Replace de todo el documento añadiendo el nuevo comentario al array de documentos.

¿Pero esto impacta al rendimiento?

Pues si, a medida que el número de comentarios crezca, cada operación de Replace ira creciendo exponencialmente. Como decía anteriormente, esto no está mal, es un comportamiento estandard de este tipo de operación, pero si buscas rendimiento esta no es tu mejor opción y vamos a ver porque.

Vamos a ejecutar una prueba para añadir 1000, 2500 y 5000 comentarios a un post y vamos a medir tiempos, ok?

image

Como podéis observar Replace es bastante más lento que Modify. Un crece de manera exponencial mientras que la otra crece de menera más o menos lineal.

¿Entonces que hace Modify con respecto a Replace?

Lo primero es mostrar la diferencia en el código:

[HttpPost]

public ActionResult AddComment(string message, string id)

{

    var comment = new Comment { Message = message };

    var update = Update<Post>.Push(p => p.Comments, comment);

    _blogContext.Posts.Update(Query.EQ("_id", ObjectId.Parse(id)), update);

 

    return RedirectToAction("Details", new {id});

}

Como podemos observar, en este caso hacemos uso de la clase Update, para hacer un push a la colección de comments. Si este código lo metemos dentro de la entidad Post estaremos acoplando nuestro modelo a MongoDb, de ahí que Replace encaja mejor en ese tipo de escenarios, pero como decíamos, si buscamos rendimiento y/o concurrencia, Modify es nuestra solución.

Si ejecutamos el profiler y añadimos un comentario con Modify:

image

¿Veís la diferencia? Ahora solo se añade un comentario al array de documentos pero no se reemplaza todo el post como ocurría con Replace, por lo tanto es una operación menos costosa.

Conclusión

Si lo que te importa es el rendimiento y la concurrencia, olvidate de modelar tu dominio y usa directamente Modify para operaciones sobre arrays, para todo lo demás Replace.

Un saludo.