Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
domingo, 11 de abril de 2010
Como adelantaba en el post anterior, esta es la primera recopilación de los enlaces publicados en la página Variable not found en Facebook. Por ser la primera entrega, vamos a recoger los de las últimas semanas, desde el miércoles 24 de marzo de 2010 hasta el domingo 11 de abril de 2010.
Espero os resulten interesantes :-)

AntiXSS como codificador de salida por defecto en ASP.NET.AntiXSS como codificador de salida por defecto en ASP.NET.
Scott Guthrie recently wrote about the new syntax for HTML encoding output in ASP.NET 4. I also covered the topic of HTML encoding code nuggets in the past as well providing some insight into our design choices for the approach we took.
Fuente: haacked.com

Fecha: 09/04/2010
Stephen Walther habla sobre cómo mantener el historial del navegador en aplicaciones Ajax.Stephen Walther habla sobre cómo mantener el historial del navegador en aplicaciones Ajax.
One objection that people always raise against Ajax applications concerns browser history. Because an Ajax application updates its content by performing sneaky Ajax postbacks, the browser backwards and forwards buttons don’t work as you would normally expect.
Fuente: stephenwalther.com

Fecha: 09/04/2010
Creación de interfaces de introducción de datos con MVC 2.Creación de interfaces de introducción de datos con MVC 2.
The next part to this article series on MVC 2.0 is the user interface. We saw in the last article some basics on the changes of the user interface, which we'll delve into more in this article series. Here we will begin to look at how developers can construct the view user interface.
Fuente: dotnetslackers.com

Fecha: 09/04/2010
Novedades de VS 2010 relativas al soporte de Intellisense en javascript.Novedades de VS 2010 relativas al soporte de Intellisense en javascript.
ASP.NET, Visual Studio, ASP.NET 2.0, .NET
Fuente: weblogs.asp.net

Fecha: 09/04/2010
Interesante debate sobre la forma de gestionar el envío de passwords a la vista.Interesante debate sobre la forma de gestionar el envío de passwords a la vista.
Let's suppose you have a model like this: public class User { public string Username { get; set; } [DataType(DataType.Password)] public string Password { get; set; } } To test this out, you write an action: public ActionResult Index() {...
Fuente: bradwilson.typepad.com

Fecha: 08/04/2010
Proveedor LINQ para Twitter, en Codeplex.Proveedor LINQ para Twitter, en Codeplex.
LINQ to Twitter is a LINQ Provider for the Twitter micro-blogging service. It uses standard LINQ syntax for queries and includes method calls for changes via the Twitter API.ExampleYou can try LINQ to Twitter, even if you don't have a twitter account. ...
Fuente: linqtotwitter.codeplex.com

Fecha: 08/04/2010
¿Un ViewEngine para Balsamiq?¿Un ViewEngine para Balsamiq?
Invitation Message: A preview of the message appears below. A link and password (if necessary) is automatically appended to the message upon sending. A Screencast.com user has invited you to view content on Screencast.com:
Fuente: http://www.screencast.com/

Fecha: 08/04/2010
Serie de posts estudiando la propuesta de Áreas Portables del proyecto MvcContrib.Serie de posts estudiando la propuesta de Áreas Portables del proyecto MvcContrib.
Fuente: geekswithblogs.net

Fecha: 07/04/2010
Rutas editables moviendo el código de inicialización al global.asax.Rutas editables moviendo el código de inicialización al global.asax.
Introduction : Phil Haack's had written two great articles about Editable Routes, Editable Routes or Editable Routes Using App_Code.These Article are great. But if you not need to unit test your ...
Fuente: weblogs.asp.net

Fecha: 07/04/2010
Cómo renderizar una plantilla a un string en MVC 2. Por ejemplo, para componer mensajes de correo en formato HTML.Cómo renderizar una plantilla a un string en MVC 2. Por ejemplo, para componer mensajes de correo en formato HTML.
In one of the projects that I am currently working on we have a lot of different emails we want to send out to users and we would like to build those emails from templates. My goal was the leverage the ...
Fuente: http://www.joeyb.org/

Fecha: 07/04/2010
Aspectos importantes para evitar el síndrome "It works on my machine".Aspectos importantes para evitar el síndrome "It works on my machine".
ALT.NET dotnet .NET C# Agile BizTalk ASP.NET
Fuente: codebetter.com

Fecha: 07/04/2010
Los nuevos bloques de salida codificada <%: %> en ASP.NET 4 y MVC 2.Los nuevos bloques de salida codificada <%: %> en ASP.NET 4 y MVC 2.
ASP.NET, Visual Studio, ASP.NET 2.0, .NET
Fuente: weblogs.asp.net

Fecha: 07/04/2010
No te pierdas la celebración de Krasis por su décimo aniversario. ¡Felicidades!No te pierdas la celebración de Krasis por su décimo aniversario. ¡Felicidades!
1.- Ir a la tienda2.- Meter en el carrito lo que quieras comprar (una unidad de cada cosa máximo)3.- Y a la hora de pagar usar el siguiente cupón de descuento:
Fuente: http://www.jasoft.org/

Fecha: 07/04/2010
Uso de CopyModel (MVC Futures) para copiar valores de propiedades entre objetos de forma automática.Uso de CopyModel (MVC Futures) para copiar valores de propiedades entre objetos de forma automática.
Brad Wilson just mentioned that the MVC Futures library has a static ModelCopier class with a CopyModel(object from, object to) static method. It uses reflection to match properties with the same name and compatible types.
Fuente: weblogs.asp.net

Fecha: 06/04/2010
Propiedades automáticas, inicialización de colecciones y continuador implícito de líneas en VB 2010.Propiedades automáticas, inicialización de colecciones y continuador implícito de líneas en VB 2010.
ASP.NET, Visual Studio, ASP.NET 2.0, .NET
Fuente: weblogs.asp.net

Fecha: 06/04/2010




Vídeo sobre MVC 2 avanzado, de Brad Wilson. Muy interesante.Vídeo sobre MVC 2 avanzado, de Brad Wilson. Muy interesante.
My re-recorded Advanced ASP.NET MVC 2 video is available now. The original video, from my C4MVC presentation, turned out to have a combination of bad audio and bad video, most of which I take the blame for, so I re-recorded...
Fuente: bradwilson.typepad.com

Fecha: 05/04/2010
Parámetros opcionales y con nombre en C#, y su uso en acciones MVCParámetros opcionales y con nombre en C#, y su uso en acciones MVC
ASP.NET, Visual Studio, ASP.NET 2.0, .NET
Fuente: weblogs.asp.net

Fecha: 05/04/2010
Tras once años de desarrollo, ayer fue lanzado OpenSSL 1.0.Tras once años de desarrollo, ayer fue lanzado OpenSSL 1.0.
Here you can find hints to the regular news about the OpenSSL project. Check this table from time to time when you want to be up-to-date with the latest OpenSSL development.
Fuente: http://www.openssl.org/

Fecha: 30/03/2010
Activar/Desactivar el copiado y pegado de líneas en blanco en Visual Studio 2010.Activar/Desactivar el copiado y pegado de líneas en blanco en Visual Studio 2010.
As you may know, Visual Studio’s cut and copy commands are useful for more than just selected text. If you invoke them when there is no selection, VS will cut or copy your entire line, which saves you the trouble of selecting the line before adding it
Fuente: blogs.msdn.com

Fecha: 29/03/2010
Diferencias entre First() y Single() en LINQ.Diferencias entre First() y Single() en LINQ.
.NET, Software Architecture
Fuente: weblogs.asp.net

Fecha: 29/03/2010
Hanselman comenta las mejoras en el tiempo de arranque de aplicaciones ASP.NET 4.Hanselman comenta las mejoras en el tiempo de arranque de aplicaciones ASP.NET 4.
Scott Hanselman on Programming, User Experience, The Zen of Computers and Life in General
Fuente: http://www.hanselman.com/

Fecha: 29/03/2010
Implementando un captcha en un ActionResult, parte I.Implementando un captcha en un ActionResult, parte I.
Fuente: dotnetslackers.com

Fecha: 29/03/2010
Lanzado jQuery UI 1.8.Lanzado jQuery UI 1.8.
jQuery UI is jQuery's user interface library that comes with many widgets, interaction modules and themes.
Fuente: blog.jqueryui.com

Fecha: 26/03/2010
Algunos casos de éxito de ASP.NET MVC.Algunos casos de éxito de ASP.NET MVC.
Shiju Varghese's Blog on ASP.NET MVC
Fuente: weblogs.asp.net

Fecha: 26/03/2010
Convergencia VB y C# en las últimas versiones de los lenguajesConvergencia VB y C# en las últimas versiones de los lenguajes
C# 3 had new language extensions that are practical for every kind of application. No matter what application you’re creating, property initializers, collection initializers, Lambda expressions, LINQ… ...
Fuente: weblogs.thinktecture.com

Fecha: 25/03/2010
Mejoras en controles de datos disponibles en ASP.NET 4.Mejoras en controles de datos disponibles en ASP.NET 4.
This article, by Scott Mitchell, explores the enhancements made to the data Web controls in ASP.NET 4.0.
Fuente: http://www.4guysfromrolla.com/

Fecha: 25/03/2010
Facilitar el diagnóstico de problemas con ASP.NET MVC: unautilidad para mostrar información de entorno, versiones de ensamblados MVC, Futures, y algunas cosas más.Facilitar el diagnóstico de problemas con ASP.NET MVC: unautilidad para mostrar información de entorno, versiones de ensamblados MVC, Futures, y algunas cosas más.
When we released ASP.NET MVC 2, we included a file in the MvcFutures package (download) called MvcDiagnostics.aspx. This single WebForms page can be dropped into any MVC site, and then viewed in your browser. It will give you diagnostic information...
Fuente: bradwilson.typepad.com

Fecha: 25/03/2010
Uso de desplegables en ASP.NET MVC, partiendo de cero.Uso de desplegables en ASP.NET MVC, partiendo de cero.
DropDownLists in ASP.NET MVC seem to cause a fair amount of confusion to developers fresh from Web Forms World. This article looks to provide you with all (well, most) of what you need to know to get your DropDownLists working in ASP.NET MVC.
Fuente: http://www.mikesdotnetting.com/

Fecha: 24/03/2010

Y no olvides que, si te interesa, puedes seguir esta información en vivo y en directo desde Variable not found en Facebook, o siguiéndome en Twitter.

Publicado en: Variable not found
Llevo ya algún tiempo utilizando la página de Variable Not Found en Facebook para publicar enlaces interesantes sobre desarrollo, ASP.NET, MVC y otros temas que voy encontrando por ahí. Normalmente anoto entradas en blogs, artículos o sitios webs a los que considero que vale la pena echar un vistazo en los ratos libres.

Integración Facebook-Twitter-BlogAdemás de en la página del blog en la red social, como por arte de magia, estos enlaces se difunden simultáneamente desde mi perfil personal de Facebook y a través de Twitter. Sin embargo, desde hace tiempo estaba estudiando la posibilidad de recopilar a su vez toda esta información para poder publicarla en el blog, cerrando completamente el círculo.

Aprovechando un huequito he creado una pequeña aplicación que toma esos enlaces y los maqueta de forma automática para mostrarlos en Variable not found. Así, a la vez que hago llegar estos enlaces a los suscriptores y lectores ocasionales del blog, los almaceno agrupados en una única ubicación sobre la que es posible realizar búsquedas, que es más cómodo que tomar rabos de pasas ;-)

En un principio orienté la solución utilizando el SDK de Facebook (como introducción os recomiendo leer esta magnífica serie del amigo Eduard Tomás), pero estaba intentando matar mosquitos a cañonazos: demasiada complejidad para una necesidad tan simple.

Afortunadamente, me di cuenta de que esta información está disponible en formato ATOM y RSS, por lo que en principio puede ser consumida utilizando las clases de sindicación introducidas con .NET 3.5 en el espacio de nombres System.ServiceModel.Syndication del ensamblado System.ServiceModel.Web.

Por tanto, debería bastar con obtener las feeds, por ejemplo en formato ATOM, desde la dirección del feed http://www.facebook.com/feeds/page.php?format=atom10&id=94490426991, ¿no?

XmlException: Por razones de seguridad DTD está prohibido en este documento…

Pero claro, las cosas nunca son tan sencillas como se prevé en un principio. Utilizando contra los feeds de Facebook el código convencional para acceder a este tipo de información (y que de hecho funciona con muchos otros feeds), se lanzaba una excepción con un misterioso mensaje:

XmlReader reader = XmlReader.Create(feedURL);
SyndicationFeed feed = SyndicationFeed.Load(reader);
 
// Excepción XmlLException              ^^^^
//   "Por razones de seguridad DTD está prohibido en este documento XML. 
//    Para habilitar el procesamiento DTD establezca la propiedad ProhibitDtd 
//    en XmlReaderSettings como false y pásela al método XmlReader.Create."

Gracias a la inestimable colaboración del compañero Fiddler, pude averiguar que el problema se debía a que Facebook no estaba retornando la información en el formato solicitado (en este caso, ATOM), sino HTML:

Capturando tráfico con Fiddler

Si observáis, la petición inicial es redirigida a un nuevo recurso mediante un código de respuesta 302, una página web en cuyo título podemos observar el texto “Navegador incompatible”.

El motivo es que, obviamente, la petición realizada automáticamente por XmlReader para obtener los datos no incluye información sobre el navegador utilizado, Facebook detecta esta circunstancia y nos devuelve una página como la siguiente:

Estoy utilizando un navegador no compatible

Y esa es precisamente la causa de la excepción: los datos retornados no se encuentran en el formato esperado.

Para cambiar esto es necesario modificar ligeramente el código anterior, creando de forma manual la petición HTTP e inyectándole en el encabezado User-Agent un valor reconocible por los servidores de Facebook, como “Mozilla/4.0”, el empleado por IE8.

Para crear el objeto XmlReader utilizamos otra sobrecarga, de forma que le suministramos el Stream de respuesta de la conexión que hemos creado:

HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(feedURL);
wr.UserAgent = "Mozilla/4.0";
 
XmlReader reader = XmlReader.Create(
   wr.GetResponse().GetResponseStream()
);
 
SyndicationFeed feed = SyndicationFeed.Load(reader);
foreach (var item in feed.Items)
{
   // Procesar entrada...

De esta forma, podemos acceder a feeds, incluso a los de Facebook, para obtener información y procesarla a nuestro antojo.

En el caso de mi megasuperaplicación, simplemente he tenido que parsear un poco el contenido y generar marcado HTML para cada entrada del feed con objeto de conseguir algo parecido a lo siguiente:

Aspecto de enlaces en Variable Not Found
Y ya está. No me queda más que avisaros de que a partir de ahora veréis de vez en cuando posts como ese, con enlaces que espero que os resulten interesantes. :-)

Publicado en: Variable Not Found.
Hey, ¡estoy en Twitter!
miércoles, 7 de abril de 2010
Hace un año hablábamos por aquí sobre los ajustes que debíamos realizar para compilar las vistas de MVC 1.0 como parte del proceso de construcción del proyecto. De esta forma tendremos las ventajas del chequeo en tiempo de compilación, que bien valen la pena aún a costa de tener que esperar algo más en cada montaje.

MVC 2 también permite habilitar esta característica en Visual Studio de forma muy sencilla. Sólo seguir los pasos descritos a continuación.

En primer lugar, con el botón derecho del ratón sobre el proyecto MVC 2, selecciona la opción “Descargar proyecto”:

Descargar proyecto

A continuación, de nuevo con el botón derecho sobre el proyecto, seleccionamos la opción “Editar NombreProyecto.csproj” (o .vbproj, dependiendo del lenguaje utilizado):

Editar archivo de proyecto

Con estas operaciones hemos conseguido traer al editor de Visual Studio el archivo de definición del proyecto, en el que debemos buscar el siguiente texto que deshabilita expresamente la compilación de vistas:

<PropertyGroup>
...
   <MvcBuildViews>false</MvcBuildViews>
</PropertyGroup>

Y efectivamente, el único cambio a realizar sería sustituir “false” por “true” :-). Salvando el archivo y volviendo a cargar el proyecto, habremos conseguido lo que pretendíamos.

Volver a cargar el proyecto

Publicado en: Variable not found
Hey, ¡estoy en twitter!
domingo, 4 de abril de 2010
Hace casi un año hablaba de la segunda versión de NDepend, una herramienta capaz de ayudaros a mejorar nuestro código, analizando cientos de aspectos, métricas y reglas a nivel de fuentes y ensamblados.

Recientemente se ha publicado la tercera versión de NDepend, que ofrece interesantes novedades respecto a las anteriores, como la integración absoluta con Visual Studio, el soporte para soluciones multi-proyecto, potentes mecanismos de búsqueda, edición múltiple de CQL, o el seguimiento de cambios, además de las tradicionales características del producto.

Los 10 métodos más extensos de ASP.NET MVC 2
Pero sin duda, lo que me ha parecido más espectacular es su magnífica integración con Visual Studio (2005, 2008 y 2010), que permite disfrutar de toda la potencia de análisis de NDepend, y sus facilidades para la navegación desde el mismo entorno de desarrollo.

Para habilitar esta característica es necesario instalar el plugin en el IDE, que se realiza desde el propio entorno visual de NDepend:

Instalar plugin NDepend en Visual Studio
De esta forma, ya no es necesario acudir a la herramienta Visual NDepend para realizar búsquedas, comprobar reglas o navegar a través de la base de código: lo haremos directamente desde VS, utilizando los menús contextuales. Y gracias a ello, podemos disfrutar de las nuevas opciones de navegación, que nos permitirá surcar el código utilizando rutas distintas a las habituales:

Navegar por el código con NDepend
U obtener diagramas de dependencias de componentes, utilizando el botón derecho del ratón:

Dependencias con NDepend 3

Además, como comenta Patrick Smacchia, padre de la criatura, el rendimiento del entorno prácticamente no se resiente, dado que los análisis se ejecutan en segundo plano de forma incremental.

Recordar, por último, que NDepend es una aplicación comercial, pero dispone de una versión limitada gratuita utilizable por universidades, desarrolladores open source e incluso, durante un tiempo determinado, de prueba en proyectos comerciales.

Página del producto: http://www.ndepend.com/
Publicado en: Variable not found
Hey, ¡estoy en twitter!
miércoles, 24 de marzo de 2010
jQuery Sí, habéis leído bien: ASP a secas, sin la habitual terminación “.NET” que venimos usando mucho últimamente ;-).

Resulta que estoy metido en un proyecto colaborando con un equipo de trabajo que está desarrollando un portal web con esa tecnología (!), y me han encargado la creación de unas herramientas ajaxificadas dentro del mismo.

Aunque pueda parecer lo contrario, las aplicaciones desarrolladas con las vetustas (pero aún vivas) páginas activas de servidor (ASP) pueden aprovechar toda la potencia de las librerías de script de última generación, como la maravillosa jQuery. Vamos a ver lo sencillo que resulta tanto implementar un servicio JSON como consumirlo desde una página ASP.

El lado servidor

El servicio JSON lo implementaremos en un archivo al que llamaremos, por ejemplo, JsonObtenerProductos.asp, cuyo código podría ser como el siguiente:

<!--#INCLUDE FILE="Includes\Functions.asp" -->
<%
   Dim categoryId, Rs, count
 
   Response.Expires = -1
   If Not UserLogged() or Request("categoryId")="" Then
      Response.End
   End If
 
   categoryId = Cint(Request("categoryId"))
 
   OpenDatabase()
   Set Rs = GetProductsByCategoryRecordset(categoryId)
 
   Response.ContentType = "application/json"
   Response.Write "{"
   Response.Write "  ""datos"": ["
   count = 0
 
   While Not Rs.Eof
      Dim id, name, desc
      id = Rs("id")
      name = Rs("name")
      desc = Rs("desc")
      count = count + 1
      If count > 1 Then
         Response.Write ", "
      End If
 
      Response.Write "{ "
      Response.Write "   ""productId"": " & id & ", "
      Response.Write "   ""productName"": """ & name & """, "
      Response.Write "   ""productDesc"": """ & desc & """"
      Response.Write "}"
      Rs.MoveNext      
   Wend
   Response.Write "         ]"
   Response.Write "}"
 
   Rs.Close
   CloseDatabase()
%>

Como se observa, se establece el tipo de contenido a “application/json”, y a continuación se envía al cliente un objeto en formato JSON, en este caso un array de objetos construidos a partir de la información obtenida desde un RecordSet.

Así, una llamada al servicio mediante la petición GET /JsonObtenerProductos.asp?categoryId=3 podría retornar el siguiente resultado:

{  
   "datos": 
   [
      { "productId": 1, "productName": "Producto 1", "productDesc": "Descripción 1"}, 
      { "productId": 2, "productName": "Producto 2", "productDesc": "Descripción 2"}, 
      { "productId": 3, "productName": "Producto 3", "productDesc": "Descripción 3"}
   ]
}

Se puede entender a simple vista; se trata de una serie de objetos, separados por comas, en cuyo interior se definen cada una de sus propiedades con su correspondiente valor. Fijaos que el mismo nombre de la propiedad va entrecomillado.

El lado cliente

Desde la página .asp que consumirá el servicio, como siempre, lo primero es referenciar la librería jQuery en la página, así:

<script src="Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>

A continuación, introducimos en el marcado de la página el siguiente código, que muestra un desplegable con categorías de productos, cuyo cambio provocará la llamada al servidor, y reserva un bloque <div> para mostrar el resultado:

<select id="categories" onchange="reloadProducts()">
   <option value="1">Electrodomésticos</option>
   <option value="2">Informática</option>
   <option value="3">Cocina</option>
   ...
</select>
<div id="result">
</div>

El código de la función reloadProducts() es el mostrado a continuación. Utiliza el método getJSON() de jQuery para realizar la llamada Ajax, suministrándole como parámetro la categoría seleccionada en el desplegable en forma de objeto anónimo.

<script type="text/javascript">
  function reloadProducts() {
    $.getJSON(       
    "JsonObtenerProductos.asp",               // URL del servicio
    { categoryId: $("#categories").val() },   // Parámetros
    function(data) {                          // Función callback          
      var elem = $("#result");elem.empty(); // Limpiamos el contenedor          
      var s = "<ul>";
      $.each(data.datos, function(i, item) {
        s += "<li>" + item.productName + "</li>";
      });
      s += "</ul>";
      elem.html(s);   // Insertamos la lista en el contenedor
    });
  }
</script>

En la función callback, invocada por jQuery cuando la llamada Ajax ha sido completada con éxito, recibimos en el parámetro “data” los datos obtenidos desde el servidor, en nuestro caso un array de objetos.

Tras limpiar el <div> donde depositaremos la información, recorremos con $.each() el array de objetos data.datos para crear una lista de productos, que insertamos a continuación en el interior del contenedor.Observad que en el interior del bucle estamos accediendo directamente a la propiedad “productName” del elemento.

Y voila! Con esto tendríamos listo un sistema completo de carga asíncrona de elementos utilizando ASP y jQuery. Pero no sólo eso, podríamos utilizar la misma técnica para realizar actualizaciones de zonas de página definidas en archivos .asp independientes, o aprovechar la potencia de plugins y librerías adicionales para mejorar la experiencia de usuario de nuestros sistemas.

Y es que ASP todavía se utiliza bastante y, aunque se trate de una tecnología obsoleta, puede resultar totalmente válida para crear aplicaciones actuales desde el punto de vista de interfaces de usuario e interacción con el servidor, utilizando librerías de scripts de última hornada.

Publicado en: Variable not found.
Hey, ¡estoy en twitter!
lunes, 22 de marzo de 2010
imageUna interesante característica de ASP.NET MVC, o más concretamente del conjunto de herramientas incluidas en Visual Studio para darle soporte, es la posibilidad de personalizar las plantillas que el IDE utiliza a la hora de agregar controladores y vistas a un proyecto.

Por ejemplo, cuando añadimos un controlador a nuestro proyecto, el entorno genera por defecto un código como el mostrado a continuación:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
 
namespace MiProyecto.Controllers
{
   public class ProductsController : Controller
   {
      //
      // GET: /Products/
 
      public ActionResult Index()
      {
         return View();
      }
 
   }
}

Pero, ¿qué ocurre si todos nuestros controladores heredan de un controlador base? ¿O si solemos incluir un código de inicialización o métodos comunes? ¿Y si disponemos de un código estandarizado para los métodos Create(), Edit(), etc? ¿O simplemente queremos cambiar el nombre de los métodos propuestos? En todos los casos la respuesta es simple: tendríamos que retocar a mano cada uno de los controladores para adaptarlos a nuestras necesidades.

imageY lo mismo ocurre, aunque de forma aún más frecuente, con las vistas. Al añadir un elemento de este tipo al proyecto es posible seleccionar la plantilla a utilizar, que determinará el contenido generado automáticamente por Visual Studio en función de si se trata de una vista parcial o completa, si será fuertemente tipada y otros aspectos.

Las plantillas disponibles para las vistas aparecen en el desplegable “View Content” del cuadro de diálogo de creación, como se aprecia en la captura de pantalla adjunta.

El contenido generado en cada caso pocas veces resulta válido directamente y requiere bastantes retoques, que debemos repetir una y otra vez en todas las vistas que generemos. Incluso en bastantes ocasiones optaremos por seleccionar la plantilla en blanco (“empty” en el desplegable) para introducir nuestro propio código.

Afortunadamente, podemos personalizar muy fácilmente las plantillas a utilizar en ambos casos:
  • de forma global, es decir, a nivel de entorno de desarrollo en el equipo, por lo que las modificaciones que introduzcamos estarán disponibles para todos los proyectos MVC que utilicemos.
  • de forma local al proyecto, siendo utilizadas únicamente al crear elementos dentro del mismo.

Personalización a nivel de equipo

Las plantillas que utiliza Visual Studio para generar tanto los controladores como las vistas están almacenadas en la carpeta Common7\IDE\ItemTemplates\CSharp\Web\MVC 2\CodeTemplates, dentro del directorio de instalación del IDE.

Por ejemplo, en mi Visual Studio 2010 las podemos encontrar en C:\Archivos de programa\Microsoft Visual Studio 10.0\Common7\IDE\ItemTemplates\CSharp\Web\MVC 2\CodeTemplates\AddController. En VS2008 es la misma, salvo por la versión del entorno, la 9.0.

En el interior de dicho directorio hay dos carpetas, llamadas “AddController” y “AddView” en las que encontraremos las plantillas T4 que generan el código por defecto para controladores y vistas, respectivamente.

En el caso del controlador, el archivo AddController/Controller.tt contiene la lógica de generación del código, a la que podemos acceder abriendo el archivo con un editor de texto plano, o con el propio Visual Studio, y realizar los cambios que estimemos oportunos (¡previo backup del archivo original, claro!).
Aunque T4 puede llegar a ser complejo, en la plantilla de controladores el código resulta bastante fácil de leer, comprender y modificar.
Para las vistas, si accedemos a la carpeta AddView, observaremos que existe una plantilla T4 para cada una de las posibilidades de contenido disponibles en el desplegable del formulario de diálogo de creación de este tipo de elementos:
Plantillas de creación de vistas
Esto ya nos sugiere dos posibilidades a la hora de personalizar los contenidos de las vistas:
  • la primera, sustituir el contenido de las plantillas incluidas por defecto, como “Create”, o “Details”, de la misma forma que hemos hecho anteriormente con los controladores,
  • o bien, crear nuestras propias plantillas. De hecho, cualquier archivo .tt añadido a esta carpeta hará que en el desplegable aparezca un nuevo elemento:
png
El código de las plantillas por defecto para las vistas es más complejo que el de los controladores, pero aun sin conocimientos de T4 pueden ser adaptados con relativa facilidad.

imagePersonalización a nivel de proyecto

Una vez comprendido lo anterior, la personalización a nivel exclusivamente de proyecto es trivial, gracias a un interesante detalle: Visual Studio, a la hora de generar el código de controladores y vistas acude en primer lugar la carpeta ~/CodeTemplates del proyecto, y busca unas subcarpetas llamadas AddController y AddView, desde donde según el caso, tomará las plantillas.

En el caso de la creación de controladores, si existe  ~/CodeTemplates/AddController/Controller.tt, se utilizará como plantilla en lugar de la definida a nivel de equipo.

Para las vistas, Visual Studio poblará el desplegable de plantillas de contenido a partir de los archivos .tt disponibles en la carpeta ~/CodeTemplates/AddView, sumados a los existentes en la carpeta de la aplicación. En caso de coincidencia de nombre (por ejemplo, si creamos aquí una nueva plantilla “Create.tt”) se tomará siempre la plantilla definida en el proyecto.

imageEso sí, para que el compilador no genere errores al ejecutar las plantillas a deshora, es necesario retocar sus propiedades, eliminando la herramienta personalizada y dejando esta propiedad en blanco.

Publicado en: Variable not found.
Hey, ¡estoy en Twitter!