Migración de ASP.NET Web API a ASP.NET Core

ASP.NET Core combina los modelos de aplicación MVC y Web API de ASP.NET 4.x en un único modelo de programación conocido como ASP.NET Core MVC.

En este artículo se muestra cómo migrar el controlador Products creado en Introducción con ASP.NET Web API 2 a ASP.NET Core.

Requisitos previos

Crear el nuevo proyecto ASP.NET Core Web API

  1. En el menú Archivo, seleccione Nuevo>Proyecto.
  2. Escriba API web en el cuadro de búsqueda.
  3. Seleccione la plantilla API web de ASP.NET Core y seleccione Siguiente.
  4. En el cuadro de diálogo Configure su nuevo proyecto, nombre el proyecto ProductsCore y seleccione Siguiente.
  5. En el cuadro de diálogo Información adicional:
    1. Confirme que el Marco es .NET 6.0 (Compatibilidad a largo plazo).
    2. Confirme que la casilla Use controllers(uncheck to use minimal APIs) [Usar controladores (desactivar para usar API mínimas)] está activada.
    3. Desactive Habilitar compatibilidad con OpenAPI.
    4. Seleccione Crear.

Elimine los archivos de plantilla WeatherForecast.

  1. Elimine los archivos de ejemplo WeatherForecast.cs y Controllers/WeatherForecastController.cs del nuevo proyecto ProductsCore.
  2. Abra Properties\launchSettings.json.
  3. Cambie las propiedades de launchUrlde weatherforcast a productscore.

La Configuración para ASP.NET Core Web API

ASP.NET Core no utiliza la carpeta App_Start ni el archivo Global.asax. El archivo web.config se añade en el momento de la publicación. Para más información, consulte archivo web.config.

El archivo Program.cs:

  • Sustituye a Global.asax.
  • Maneja todas las tareas de inicio de la aplicación.

Para obtener más información, vea Inicio de la aplicación en ASP.NET Core.

A continuación se muestra el código de inicio de la aplicación en el archivo ASP.NET Core Program.cs:

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Copiar el modelo Producto

  1. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto. Seleccione Agregar>Nueva carpeta. Asigne a la carpeta el nombre Models.
  2. Haga clic con el botón derecho en la carpeta Models. Seleccione Agregar>Clase. Nombre la clase Producto y seleccione Añadir.
  3. Sustituya el código del modelo de plantilla por lo siguiente:
namespace ProductsCore.Models
{
    public class Product
    {
        public int Id { get; set; }
        public string? Name { get; set; }
        public string? Category { get; set; }
        public decimal Price { get; set; }
    }
}

El código resaltado anterior cambia lo siguiente:

  • Se ha añadido la anotación ? para declarar las propiedades Name y Category como tipos de referencia nula.

Al utilizar la función Nullable introducida en C# 8, ASP.NET Core puede proporcionar un análisis de flujo de código adicional y seguridad en tiempo de compilación en el manejo de tipos de referencia. Por ejemplo, protección frente a excepciones de referencia null.

En este caso, la intención es que Name y Category puedan ser tipo que acepta valores NULL.

Los proyectos ASP.NET Core 6.0 permiten tipos de referencia nula de manera predeterminada. Para más información, consulte Tipos de referencia que admiten un valor NULL.

Copie el ProductsController

  1. Haga clic con el botón derecho en la carpeta Controllers.
  2. Seleccione Añadir > Controlador....
  3. En el cuadro de diálogo Agregar nuevo elemento de andamio, seleccione Controlador Mvc - Vacío y, a continuación, seleccione Agregar.
  4. Nombre el controlador ProductsController y seleccione Agregar.
  5. Sustituya el código del controlador de plantilla por el siguiente:
using Microsoft.AspNetCore.Mvc;
using ProductsCore.Models;

namespace ProductsCore.Controllers;

[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    Product[] products = new Product[]
    {
            new Product
            {
                Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1
            },
            new Product
            {
                Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M
            },
            new Product
            {
                Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M
            }
    };

    [HttpGet]
    public IEnumerable<Product> GetAllProducts()
    {
        return products;
    }

    [HttpGet("{id}")]
    public ActionResult<Product> GetProduct(int id)
    {
        var product = products.FirstOrDefault((p) => p.Id == id);
        if (product == null)
        {
            return NotFound();
        }
        return product;
    }
}

El código resaltado anterior cambia lo siguiente, para migrar a ASP.NET Core:

  • Quita las sentencias con de los siguientes componentes de ASP.NET 4.x que no existen en ASP.NET Core:

    • Clase ApiController
    • Espacio de nombres System.Web.Http
    • IHttpActionResult (interfaz)
  • Cambia la sentencia using ProductsApp.Models; por using ProductsCore.Models;.

  • Establece el espacio de nombres raíz en ProductsCore.

  • Cambia ApiController por ControllerBase.

  • Añade using Microsoft.AspNetCore.Mvc; para resolver la referencia ControllerBase.

  • Cambia el tipo de retorno de la acción GetProduct de IHttpActionResult a ActionResult<Product>. Para obtener más información, consulte Tipos de valor devuelto de acción del controlador.

  • Simplifica la sentencia return de la acción GetProduct a la siguiente sentencia:

    return product;
    
  • Añade los siguientes atributos que se explican en las siguientes secciones:

    • [Route("api/[controller]")]
    • [ApiController]
    • [HttpGet]
    • [HttpGet("{id}")]

Enrutamiento

ASP.NET Core proporciona un modelo de alojamiento mínimo en el que el middleware de enrutamiento de punto de conexión envuelve toda la canalización de middleware, por lo tanto, las rutas se pueden agregar directamente a la WebApplication sin una llamada explícita a UseEndpoints o UseRouting para registrar rutas.

UseRouting todavía se puede usar para especificar dónde se produce la coincidencia de rutas, pero UseRouting no es necesario llamar explícitamente si las rutas deben coincidir al principio de la canalización de middleware.

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.

builder.Services.AddControllers();

var app = builder.Build();

// Configure the HTTP request pipeline.

app.UseHttpsRedirection();

app.UseAuthorization();

app.MapControllers();

app.Run();

Nota: Las rutas agregadas directamente a WebApplication se ejecutan al final de la canalización.

Enrutamiento en el ProductsController migrado

El ProductsController migrado contiene los siguientes atributos resaltados:

using Microsoft.AspNetCore.Mvc;
using ProductsCore.Models;

namespace ProductsCore.Controllers;

[Route("api/[controller]")]
[ApiController]
public class ProductsController : ControllerBase
{
    Product[] products = new Product[]
    {
            new Product
            {
                Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1
            },
            new Product
            {
                Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M
            },
            new Product
            {
                Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M
            }
    };

    [HttpGet]
    public IEnumerable<Product> GetAllProducts()
    {
        return products;
    }

    [HttpGet("{id}")]
    public ActionResult<Product> GetProduct(int id)
    {
        var product = products.FirstOrDefault((p) => p.Id == id);
        if (product == null)
        {
            return NotFound();
        }
        return product;
    }
}
  • El atributo [Route]configura el patrón de enrutamiento de atributos del controlador.

  • El atributo [ApiController] hace que el enrutamiento de atributos sea un requisito para todas las acciones de este controlador.

  • El enrutamiento de atributos admite tokens, como [controller] y [action]. En tiempo de ejecución, cada token se sustituye por el nombre del controlador o acción, respectivamente, al que se ha aplicado el atributo. Los tokens:

    • Reducen o eliminan la necesidad de utilizar cadenas codificadas para la ruta.
    • Garantizan que las rutas permanezcan sincronizadas con los controladores y acciones correspondientes cuando se aplican refactorizaciones automáticas de cambio de nombre.
  • Las peticiones HTTP Get están habilitadas para las acciones ProductController con los siguientes atributos:

    • [HttpGet] atributo aplicado a la acción GetAllProducts.
    • [HttpGet("{id}")] atributo aplicado a la acción GetProduct.

Ejecute el proyecto migrado y vaya a /api/products. Por ejemplo: https://localhost:<port>/api/products. Aparece una lista completa de tres productos. Vaya a /api/products/1. Aparece el primer producto.

Vea o descargue el código de ejemplo (cómo descargarlo)

Recursos adicionales

En este artículo se muestran los pasos necesarios para migrar de ASP.NET API web 4.x a ASP.NET Core MVC.

Vea o descargue el código de ejemplo (cómo descargarlo)

Requisitos previos

Revisión ASP.NET proyecto de API web 4.x

En este artículo se usa el proyecto ProductsApp creado en Introducción con ASP.NET Web API 2. En ese proyecto, se configura un proyecto de API web de ASP.NET 4.x básico como se indica a continuación.

En Global.asax.cs, se realiza una llamada a WebApiConfig.Register:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Routing;

namespace ProductsApp
{
    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }
    }
}

La clase WebApiConfig se encuentra en la carpeta App_Start y tiene un método estático Register:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http;

namespace ProductsApp
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API configuration and services

            // Web API routes
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }
}

La clase anterior:

  • Configura el enrutamiento de atributos, aunque realmente no se usa.
  • Configura la tabla de enrutamiento. El código de ejemplo espera que las URL coincidan con el formato /api/{controller}/{id}, siendo {id} opcional.

Las siguientes secciones demuestran la migración del proyecto de API web a ASP.NET Core MVC.

Creación del proyecto de destino

Cree una nueva solución en blanco en Visual Studio y añada el proyecto ASP.NET 4.x Web API que desea migrar:

  1. En el menú Archivo, seleccione Nuevo>Proyecto.
  2. Seleccione la plantilla Solución en blanco y seleccione Siguiente.
  3. Nombre la solución WebAPIMigration. Seleccione Crear.
  4. Añada el proyecto ProductsApp existente a la solución.

Añada un nuevo proyecto API al que migrar:

  1. Añada un nuevo proyecto ASP.NET Core Web Application a la solución.
  2. En el cuadro de diálogo Configure su nuevo proyecto, nombre el proyecto ProductsCore y seleccione Crear.
  3. En el cuadro de diálogo Crear una aplicación web ASP.NET Core, confirme que las opciones .NET Core y ASP.NET Core 3.1 estén seleccionadas. Seleccione la plantilla de proyecto API y, luego, Crear.
  4. Elimine los archivos de ejemplo WeatherForecast.cs y Controllers/WeatherForecastController.cs del nuevo proyecto ProductsCore.

La solución contiene ahora dos proyectos. En las siguientes secciones se explica cómo migrar el contenido del proyecto ProductsApp al proyecto ProductsCore.

Migración de la configuración

ASP.NET Core no utiliza la carpeta App_Start ni el archivo Global.asax. Además, el archivo web.config se añade en el momento de la publicación.

La clase Startup:

  • Sustituye a Global.asax.
  • Maneja todas las tareas de inicio de la aplicación.

Para obtener más información, vea Inicio de la aplicación en ASP.NET Core.

Migrar modelos y controladores

El siguiente código muestra el ProductsController que debe actualizarse para ASP.NET Core:

using ProductsApp.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Web.Http;

namespace ProductsApp.Controllers
{
    public class ProductsController : ApiController
    {
        Product[] products = new Product[] 
        { 
            new Product
            {
                Id = 1, Name = "Tomato Soup", Category = "Groceries", Price = 1
            }, 
            new Product
            {
                Id = 2, Name = "Yo-yo", Category = "Toys", Price = 3.75M
            }, 
            new Product
            {
                Id = 3, Name = "Hammer", Category = "Hardware", Price = 16.99M
            } 
        };

        public IEnumerable<Product> GetAllProducts()
        {
            return products;
        }

        public IHttpActionResult GetProduct(int id)
        {
            var product = products.FirstOrDefault((p) => p.Id == id);
            if (product == null)
            {
                return NotFound();
            }
            return Ok(product);
        }
    }
}

Actualizar el ProductsController para ASP.NET Core:

  1. Copie Controllers/ProductsController.cs y la carpeta Models del proyecto original al nuevo.
  2. Cambie el espacio de nombres raíz de los archivos copiados a ProductsCore.
  3. Actualice la declaración using ProductsApp.Models; a using ProductsCore.Models;.

Los siguientes componentes no existen en ASP.NET Core:

  • Clase ApiController
  • Espacio de nombres System.Web.Http
  • IHttpActionResult (interfaz)

Realice los cambios siguientes:

  1. Cambio de ApiController a ControllerBase. Añada using Microsoft.AspNetCore.Mvc; para resolver la referencia ControllerBase.

  2. Elimine using System.Web.Http;.

  3. Cambiar el tipo de retorno de la acción GetProduct de IHttpActionResult a ActionResult<Product>.

  4. Simplifique la declaración return de la acción GetProduct a lo siguiente:

    return product;
    

Configuración del enrutamiento

La plantilla de proyecto ASP.NET Core API incluye la configuración de enrutamiento de punto de conexión en el código generado.

Las siguientes llamadas UseRouting y UseEndpoints:

  • Registrar la coincidencia de rutas y la ejecución de puntos de conexión en la canalización middleware.
  • Sustituya el archivo App_Start/WebApiConfig.cs del proyecto ProductsApp.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });
}

Configure el enrutamiento como se indica a continuación:

  1. Marque la clase ProductsController con los siguientes atributos:

    [Route("api/[controller]")]
    [ApiController]
    

    El atributo [Route] anterior configura el patrón de enrutamiento de atributos del controlador. El atributo [ApiController] hace que el enrutamiento de atributos sea un requisito para todas las acciones de este controlador.

    El enrutamiento de atributos admite tokens, como [controller] y [action]. En tiempo de ejecución, cada token se sustituye por el nombre del controlador o acción, respectivamente, al que se ha aplicado el atributo. Los tokens:

    • Reduzca el número de cadenas mágicas del proyecto.
    • Garantizan que las rutas permanezcan sincronizadas con los controladores y acciones correspondientes cuando se aplican refactorizaciones automáticas de cambio de nombre.
  2. Habilitar peticiones HTTP Get a las acciones ProductsController:

    • Aplicar el atributo [HttpGet] a la acción GetAllProducts.
    • Aplicar el atributo [HttpGet("{id}")] a la acción GetProduct.

Ejecute el proyecto migrado y vaya a /api/products. Aparece una lista completa de tres productos. Vaya a /api/products/1. Aparece el primer producto.

Recursos adicionales