Autor en Google+
Saltar al contenido

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

11 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, ASP.NET Core, MVC, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 16 de enero de 2018
ASP.NET CoreYa, sé que puede parecer una pregunta extraña a estas alturas, pero el caso es que un alumno del curso de ASP.NET Core en CampusMVP me la envió hace unos días y me ha parecido interesante comentar el asunto por aquí, por si puede interesar a alguien más.

Aunque a muchos nos pueda parecer raro, aún hay bastantes empresas y desarrolladores trabajando en Visual Basic .NET. En ocasiones sólo es para mantener código antiguo, pero otras veces (más de lo que puede parecer) incluso para crear nuevos sistemas aprovechando la experiencia de los desarrolladores y bases de código existente.
Si estáis en esta situación y vais a comenzar a trabajar con ASP.NET Core, mi recomendación siempre es que aprovechéis el momento de cambios para dar el salto a C#. Spoiler: no os arrepentiréis ;)
Bien, respecto a la pregunta motivo del post, en teoría debería poderse, y de hecho ya difundimos por aquí hace tiempo la noticia oficial de que sería soportado, pero la verdad es que desde entonces no he vuelto a oir hablar mucho del tema, ni he visto ejemplos, ni movimiento en la comunidad ni nada parecido, lo cual me hizo dudar de la situación actual de este tema.

En este post vamos a hacer un tour rápido para ver, en la práctica, cómo está el soporte para VB.NET en la versión actual de ASP.NET Core (2.0).

Creación de proyectos ASP.NET Core en Visual Basic .NET

Bien, en este punto nos encontramos con un primer escollo: no existen plantillas para la creación de este tipo de proyectos en Visual Studio, y tampoco en .NET Core CLI, como podemos ver en la ayuda del comando dotnet new:
C:\Users\josem>dotnet new
Uso: new [opciones]

Opciones:
  -h, --help          Muestra ayuda para este comando.
  -l, --list          Muestra las plantillas que contienen el nombre especificado. Si no se especifica ningún nombre, muestra todas las plantillas.
  -n, --name          Nombre de la salida que se va a crear. Si no se especifica ningún nombre, se usa el nombre del directorio actual.
  -o, --output        Ubicación donde debe ponerse la salida generada.
  -i, --install       Instala un origen o un paquete de plantillas.
  -u, --uninstall     Desinstala un origen o un paquete de plantillas.
  --type              Filtra las plantillas por los tipos disponibles. Los valores predefinidos son "other", "project" o "item".
  --force             Fuerza la generación de contenido aunque se produzcan cambios en los archivos actuales.
  -lang, --language   Especifica el idioma de la plantilla que debe crearse.


Plantillas                                        Nombre corto      Idioma            Etiquetas
---------------------------------------------------------------------------------------------------------
Console Application                               console           [C#], F#, VB      Common/Console
Class library                                     classlib          [C#], F#, VB      Common/Library
Unit Test Project                                 mstest            [C#], F#, VB      Test/MSTest
xUnit Test Project                                xunit             [C#], F#, VB      Test/xUnit
ASP.NET Core Empty                                web               [C#], F#          Web/Empty
ASP.NET Core Web App (Model-View-Controller)      mvc               [C#], F#          Web/MVC
ASP.NET Core Web App                              razor             [C#]              Web/MVC/Razor Pages
ASP.NET Core with Angular                         angular           [C#]              Web/MVC/SPA
ASP.NET Core with React.js                        react             [C#]              Web/MVC/SPA
ASP.NET Core with React.js and Redux              reactredux        [C#]              Web/MVC/SPA
ASP.NET Core Web API                              webapi            [C#], F#          Web/WebAPI
global.json file                                  globaljson                          Config
NuGet Config                                      nugetconfig                         Config
Web Config                                        webconfig                           Config
Solution File                                     sln                                 Solution
Razor Page                                        page                                Web/ASP.NET
MVC ViewImports                                   viewimports                         Web/ASP.NET
MVC ViewStart                                     viewstart                           Web/ASP.NET

Examples:
    dotnet new mvc --auth Individual
    dotnet new angular
    dotnet new --help

C:\Users\josem>_
Tampoco hay referencias a plantillas de este tipo en el repositorio oficial el sitio dotnet templates, por lo que supongo que estamos en una vía muerta. Habrá que probar con otras alternativas.

¿Quién dijo que necesitábamos plantillas?

Hemos de recordar que una aplicación ASP.NET Core es simplemente una aplicación de consola venida a más ;) Debido a ello, es completamente posible crear una simple aplicación de consola .NET Core e instalarle los paquetes relativos al framework ASP.NET Core que, como sabemos, en la versión 2.0 están resumidos en el metapaquete Microsoft.AspNetCore.All (puedes leer más sobre este paquete especial en este gran post del amigo Eduard Tomás).

Por tanto, podemos comenzar a trabajar si creamos una simple aplicación de consola para .NET Core, ya sea desde Visual Studio (este tipo de proyectos sí dispone de plantilla) o desde línea de comandos. Una vez creada, añadiremos la referencia al citado metapaquete, por ejemplo editando el archivo .vbproj:
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" /
  </ItemGroup>
</Project>
Con esto ya tenemos la infraestructura necesaria, pero aún nos queda algo de tarea por delante. Lo primero, recordad que para ejecutar una aplicación ASP.NET Core necesitamos crear un servidor y echarlo a andar, algo que tradicionalmente implementamos en el archivo Program.cs de nuestro proyecto. El equivalente en VB.NET sería implementar el siguiente código en la clase Program:
Module Program
    Sub Main(args As String())
        BuildWebHost(args).Run()
    End Sub

    Function BuildWebHost(args As String()) As IWebHost
        Return WebHost.CreateDefaultBuilder(args).UseStartup(Of Startup)().Build()
    End Function
End Module
También necesitamos crear una clase Startup para implementar los métodos de configuración de servicios y el pipeline de nuestra aplicación. Comencemos por algo sencillo como lo siguiente:
Public Class Startup
    Sub Configure(app as IApplicationBuilder)
        app.UseWelcomePage()
    End Sub
End Class
En este momento, si ejecutamos la aplicación y accedemos con el navegador a la dirección localhost:5000, veremos que, como no podría ser de otra forma, ¡nuestra aplicación ASP.NET Core creada con Visual Basic .NET funciona!

Welcome page

Incluso, aunque de forma un pelín incómoda para los que estamos acostumbrados a la concisión de C#, podemos codificar middlewares para procesar peticiones, por lo que ya tendríamos todo lo necesario para crear aplicaciones ASP.NET Core:
Sub Configure(app as IApplicationBuilder)
    app.Run(Async Function(context) 
        Await context.Response.WriteAsync("Hello, world!")
    End Function)
End Sub
Por tanto, en este punto podríamos asegurar que, a pesar de que el tooling no nos ayuda especialmente, usando Visual Basic .NET podemos desarrollar aplicaciones ASP.NET Core.

Subimos la apuesta: ¿podemos usar ASP.NET Core MVC con VB.NET?

Para comprobarlo, obviamente lo primero que tendríamos que hacer es configurar apropiadamente los servicios y el pipeline de la aplicación. Un par de líneas en la clase de configuración y listo:
Public Class Startup
    Sub ConfigureServices(services as IServiceCollection)
        Services.AddMvc()
    End Sub

    Sub Configure(app as IApplicationBuilder)
        app.UseMvcWithDefaultRoute()
    End Sub
End Class
Creemos también un controlador para comprobar el funcionamiento del framework MVC:
Public Class HomeController
    Inherits Controller
    public Function Index() as IActionResult
        Return Content("Hello from Visual Basic .NET!")
    End Function

End Class
Y por supuesto, todo funcionará como esperamos. Si ejecutamos la aplicación y accedemos a localhost:5000, podremos ver el correspondiente mensaje de saludo:



Entonces, ¿podríamos usar cualquier herramienta del framework MVC, como el rutado por atributos, o el retorno de resultados más complejo, por ejemplo un objeto serializado en formato JSON? Por supuesto:
Public Class HomeController
    Inherits Controller

    <Route("test")>
    Public Function Test() As IActionResult
        Return Json(New With {.Name = "John Smith", .Age = 34})
    End Function

End Class

JSON object

A tenor de los resultados obtenidos, podríamos concluir que es totalmente posible configurar y poner a funcionar una aplicación con el framework MVC desde un proyecto Visual Basic .NET.

Pero, ah, no podía ser tan sencillo…

¿Y se pueden crear vistas Razor usando Visual Basic .NET?

Pues aquí es donde nos vamos a encontrar los problemas de verdad. Podemos hacer una prueba rápida como la siguiente:
Public Class HomeController
    Inherits Controller
    Public Function Index() As IActionResult
        Return View()
    End Function
End Class
Ahora introducimos en la carpeta /Views/Home un archivo Index.vbhtml (recordad que el “vb” en la extensión indica que se trata de sintaxis Razor con Visual Basic .NET):
<!DOCTYPE html>
@{
        Dim title = "Hello from VB.NET!"
}

<html>
<head>
    <title>@title</title>
</head>
<body>
    <div>
        <h1>@title</h1>
    </div>
</body>
</html>
Si ejecutamos la aplicación y nos dirigimos al raíz del sitio web, veremos que retorna un error 500 y encontraremos la siguiente información en el log:
System.InvalidOperationException: The view 'Index' was not found. The following locations were searched:
/Views/Home/Index.cshtml
/Views/Shared/Index.cshtml
El motivo de este error es que, por defecto, el motor de vistas Razor ni siquiera incluye en sus rutas de búsqueda las vistas con extensión .vbhtml. Podríamos pensar que sería sólo cuestión de retocar las rutas de búsqueda del view engine, pero si lo hacemos veremos que el tema es bastante más profundo: en la actualidad, Razor no soporta el lenguaje VB.NET; y, lo que es peor, no parece que vaya a hacerlo a corto plazo.

Y para mayor desconsuelo, si en un proyecto Visual Basic .NET intentamos introducir una vista .cshtml (Razor con C#) tampoco funcionará. Es decir, no podemos tener esta mezcla de lenguajes en el mismo proyecto.

Entonces, ¿No se puede? ¿No quedamos en que VB iba a ser soportado?

Buceando un poco por GitHub podemos encontrar un issue bastante reciente donde se discute sobre el tema y se muestra el siguiente timeline de la información que ha sido difundida al respecto por parte de miembros del equipo del proyecto:
  • Diciembre 2014: “Tenemos planeado tener puntos de extensibilidad para que otros lenguajes como VB o F# puedan ser añadidos en forma de paquete (…)”
  • Abril 2015: “¡Buenas noticias! ¡Hemos anunciado planes para añadir soporte para VB en ASP.NET 5/DNX!”.
  • Noviembre 2016: El soporte para VB en ASP.NET Core desaparece del roadmap oficial.
  • Diciembre 2017: “No hay planes para añadir a ASP.NET Core plantillas para VB”
O sea, que parece que los planes para VB se han quedado en meras buenas intenciones ;) Citando textualmente un comentario de Ryan Nowak, miembro del equipo ASP.NET Core de Microsoft:
“It unfortunately would be incredibly, incredibly expensive for us to add good support for using Razor in a VB project to tooling. The project system in VS for Razor intellisense is based on the idea that we can piggyback on your app’s C# project for intellisense, references, and other settings”  
“(…) For these reasons we have no plans to support Razor in VB projects. Our recommendation is factor your code into a C# app and VB class library. This way if you prefer VB you can write basically everything except Program.Main in VB (including startup, controllers, and models).”

En conclusión

En estos momentos el soporte completo para Visual Basic .NET está encallado, y esta situación no parece que vaya a cambiar de momento. Como hemos visto en este post, técnicamente es posible crear aplicaciones ASP.NET Core e incluso implementar alguno de sus componentes utilizando VB.NET, lo que abriría las puertas a su utilización en el desarrollo de servicios. Es decir, a priori no parece que haya inconveniente en usar este lenguaje si nuestro sistema lo único que hace es responder peticiones de tipo Ajax a un frontend o a otras aplicaciones remotas.

Sin embargo, si intentamos utilizar Visual Basic para implementar soluciones completas, al llegar a las vistas nos toparemos con un muro infranqueable, por lo que la recomendación oficial en este caso es crear un proyecto C# para esta parte y mover el resto, que hemos visto que funciona, a una biblioteca de clases VB :(
Podéis ver un ejemplo de este “mix” en el siguiente repositorio de GitHub.
Por tanto, como os adelanté al principio de este post, si programáis con Visual Basic y estáis en el momento de comenzar un proyecto ASP.NET Core, ni lo penséis: aprovechad la ocasión para saltar a C# :)

Lecturas relacionadas:

Publicado en Variable not found.

Estos contenidos se publican bajo una licencia de Creative Commons Licencia Reconocimiento-No comercial-Compartir bajo la misma licencia 3.0 España de Creative Commons

4 Comentarios:

Pablo dijo...

Creo que MS esta fallando mucho en la forma de "matar" a VB.NET, esta clase de ambiguedades (en 2015 lo soportamos en Core, ahora no) lo único que hace es confundir a todo el mundo.

Tendrían que poner una fecha en particular (o a partir de una versión determinada de .NET) y MS ponerse los pantalones y decir "a partir de aquí no evoluciona más VB.NET". Con esa información oficial, y con un tiempo prudente, los jefazos pueden tomar decisiones (reescribir en c#, migrar de plataforma, pegarse un tiro, etc)

Apertil dijo...

La opción que mas me gusta para los jefazos es la última que mencionas.....:-D

Jorge dijo...

Muy interesante el artículo. Gracias por el post.

P.D.: Creo que hay un pequeño desliz sin mucha importancia, por si lo quieres cambiar para no confundir. En el 4º párrafo del apartado de las vistas Razor pone:

El motivo de este error es que, por defecto, el motor de vistas Razor ni siquiera incluye en sus rutas de búsqueda las vistas con extensión .cshtml.... Creo que te refieres a que sus rutas de búsqueda no incluye las extensiones de VB.NET .vbhtml

José M. Aguilar dijo...

Hola!

Cierto, muchas gracias por avisar. Está corregido :)

Saludos!