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!
martes, 7 de noviembre de 2017
ASP.NET Core MVCTrabajando con ASP.NET Core MVC desde Visual Studio, seguro que alguna vez habéis creado vistas, controladores u otros elementos utilizando las plantillas disponibles en el IDE, seleccionando la opción del menú Add > New Scaffolded Item, por lo que os habréis encontrado con un cuadro de diálogo como el siguiente:

Cuadro de diálogo de adición de scaffolded item

Tras seleccionar el tipo de elemento a crear, aparecerá un segundo cuadro de diálogo solicitándonos información sobre el mismo. Por ejemplo, en la siguiente captura de pantalla se muestra el diálogo de creación de vistas MVC, donde debemos introducir el nombre de la vista, la plantilla a utilizar, la clase del Modelo para vistas tipadas, etc:

Cuadro de diálogo de creación de vista MVC

Después de cumplimentar estos datos, se generará automáticamente el código fuente del elemento indicado. Hasta aquí bien, pero, ¿qué ocurre si ese código generado no se ajusta exactamente a nuestras necesidades? O preguntándolo de otra forma, ¿es posible modificar las plantillas de generación de código utilizadas en estos casos para adaptarlas a nuestras preferencias?

Pues sí, y vamos a ver cómo :)

Modificando las plantillas de generación de código a nivel de equipo

En ASP.NET Core 2.0, las plantillas utilizadas para generar estos artefactos desde Visual Studio se encuentran en la carpeta del SDK de .NET Core %programfiles%\dotnet\sdk\NuGetFallbackFolder\microsoft.visualstudio.web.codegenerators.mvc\2.0.0\Templates, organizadas a su vez en subcarpetas según el tipo de elemento:
  • ControllerGenerator → Generadores de controladores MVC.
  • MvcLayout → Layouts de MVC.
  • RazorPageGenerator → Generadores de páginas Razor.
  • Startup → Plantilla de clase Startup.
  • ViewGenerator → Generadores de vistas MVC.
Contenido de la carpeta de plantillas

A su vez, en cada una de estas carpetas encontramos las plantillas disponibles, escritas con sintaxis Razor (bye bye, T4). Por ejemplo, en el caso de los generadores de controladores MVC, encontramos las siguientes, que corresponden con los distintos tipos de controlador que podemos crear usando las herramientas de scaffolding:

Archivos de plantillas de generación de controladores

Aunque ya se puede intuir por el nombre de los archivos, la correspondencia con las plantillas ofrecidas en el cuadro de diálogo de scaffolding es la siguiente:
Plantillas de scaffold
  1. ApiControllerWithActions.cshtml
  2. ApiControllerWithContext.cshtml
  3. ApiEmptyController.cshtml
  4. ControllerWithActions.cshtml
  5. EmptyController.cshtml
  6. MvcControllerWithContext.cshtml
El código que podemos encontrar en cada una de estas plantillas es fácil de descifrar si estamos familiarizados con la sintaxis Razor. Por ejemplo, si echamos un vistazo a una plantilla simple, como es `EmptyController.cshtml”, nos encontraremos un código como el siguiente:
@inherits Microsoft.VisualStudio.Web.CodeGeneration.Templating.RazorTemplateBase
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace @Model.NamespaceName
{
    public class @Model.ClassName : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}
Seguro que ya véis claro cómo podemos personalizar esta plantilla a nivel de equipo: basta con editar ese archivo (requiere permisos de administrador) y ponerlo a nuestro gusto. Obviamente, los cambios que hagamos tendrán efecto a partir de ese momento, aunque sólo en nuestro equipo.

Por ejemplo, podríamos modificar la plantilla EmptyController.cshtml de la siguiente forma. Observad que lo único que hemos hecho es añadir un comentario de documentación con <summary>:
@inherits Microsoft.VisualStudio.Web.CodeGeneration.Templating.RazorTemplateBase
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace @Model.NamespaceName
{
    /// <summary>Controller class for @Model.ClassName.Replace("Controller", string.Empty)</summary> 
    public class @Model.ClassName : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
} 
Así, si ahora creamos un scaffolded item de tipo “MVC Controller Empty”, obtendremos el siguiente resultado:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace MyMvcApp.Controllers
{
    /// <summary>Controller class for Test</summary> 
    public class TestController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
} 
Esto podemos hacerlo con cada una de las plantillas que nos interese para personalizar el código generado. Podemos aprender muchas cosas interesantes simplemente observando el código original, donde veremos qué información recibimos desde el entorno en la propiedad Model y cómo utilizarla.

Modificando las plantillas de generación de código a nivel de proyecto

Anteriormente hemos visto cómo modificar las plantillas de generación de código, pero con algunas limitaciones, puesto que los cambios que hagamos:
  • Sólo están visibles en nuestro equipo, pues estamos tocando archivos locales.
  • Se aplicarán en todos los proyectos a partir de ese momento.
  • No estarán incluidos en Git o el sistema de control de código fuente que utilicemos.
Carpeta Templates en el proyecto ASP.NET Core Sin embargo, es posible, y además bastante sencillo, crear plantillas específicas para determinados proyectos, que además puedan ser introducidas en el control de código fuente como parte de los mismos y ser compartidas por el equipo de desarrollo.
Para ello, simplemente tenemos que copiar el contenido de la carpeta %programfiles%\dotnet\sdk\NuGetFallbackFolder\microsoft.visualstudio.web.codegenerators.mvc\2.0.0\Templates a la carpeta Templates del proyecto donde queramos incluirlas. El resultado, visto en el explorador de soluciones de Visual Studio, sería algo como lo mostrado en la captura de pantalla lateral.

A partir de ese momento estas plantillas serán las utilizadas para crear los elementos, por lo que cualquier cambio aplicado a ellas serán tenidos en cuenta :)

Por ejemplo, podríamos modificar la plantilla Templates/EmptyController.cshtml de la siguiente forma para añadir información en el encabezado del archivo y hacer que por defecto los controladores hereden de una clase llamada CustomBaseController de nuestro proyecto:
// 
// File Creation: @DateTime.Now.ToLongDateString()
// Author: @Environment.UserName from @Environment.MachineName
// License: MIT
// 
@inherits Microsoft.VisualStudio.Web.CodeGeneration.Templating.RazorTemplateBase
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using @(Model.NamespaceName).Extensions;

namespace @Model.NamespaceName
{
    public class @Model.ClassName : CustomBaseController
    {
        public IActionResult Index()
        {
            return View();
        }
    }
} 
Así, el resultado obtenido al crear un nuevo controlador vacío podría ser el siguiente:
// 
// File Creation: domingo, 29 de octubre de 2017
// Author: josem from PC-JMA
// License: MIT
// 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using CustomTemplatesDemo.Controllers.Extensions;

namespace CustomTemplatesDemo.Controllers
{
    public class DefaultController : CustomBaseController
    {
        public IActionResult Index()
        {
            return View();
        }
    }
} 
¡Espero que os sea útil!

Publicado en Variable not found.

Aún no hay comentarios, ¡sé el primero!