從 ASP.NET Web API 移轉至 ASP.NET Core Web API

ASP.NET Core 會將 ASP.NET 4.x 的 MVC 和 Web API 應用程式模型結合成稱為 ASP.NET Core MVC 的單一程式設計模型。

本文會說明如何將 ASP.NET Web API 2 使用者入門 中建立的產品控制器移轉至 ASP.NET Core。

必要條件

建立新的 ASP.NET Core Web API 專案

  1. 從 [檔案] 功能表選取 [新增] >[專案] 。
  2. 在搜尋方塊中輸入 Web API
  3. 選取 [ASP.NET Core Web API] 範本,然後選取 [下一步]
  4. [設定新專案] 對話方塊中,將專案命名為 ProductsCore,然後選取 [下一步]
  5. [其他資訊] 對話方塊中:
    1. 確認 Framework.NET 6.0 (長期支援)
    2. 確認已核取 [使用控制器 (取消核取以使用最小 API)] 核取方塊。
    3. 取消核取 [啟用 OpenAPI 支援]
    4. 選取建立

移除 WeatherForecast 範本檔案

  1. 從新的 ProductsCore 專案中移除 WeatherForecast.csControllers/WeatherForecastController.cs 範例檔案。
  2. 開啟 Properties\launchSettings.json
  3. launchUrl 屬性從 weatherforcast 變更為 productscore

ASP.NET Core Web API 的設定

ASP.NET Core 不會使用 App_Start 資料夾或 Global.asax 檔案。 web.config 檔案會在發佈時新增。 如需詳細資訊,請參閱 Web.config 檔案

Program.cs 檔案:

  • 取代 Global.asax
  • 處理所有應用程式啟動工作。

如需詳細資訊,請參閱 ASP.NET Core 中的應用程式啟動

下列顯示 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();

複製 [產品] 模型

  1. 在 [方案總管] 中,以滑鼠右鍵按一下專案。 選取 [新增]>[新增資料夾]。 將資料夾命名為 Models
  2. 以滑鼠右鍵按一下 [模型] 資料夾。 選取 [新增]>[類別]。 將類別命名為 [產品],然後選取 [新增]
  3. 以下列項目取代範本模型程式碼:
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; }
    }
}

上述醒目提示的程式碼會變更下列內容:

  • 已新增 ? 註釋來將 NameCategory 屬性宣告為可為 Null 的參考型別。

藉由利用 C# 8 中引進的可為 Null 功能,ASP.NET Core 可以在處理參考型別時提供額外的程式碼流程分析和編譯時間安全性。 例如,防止 null 參考例外狀況。

在此情況下,意圖是 NameCategory 可以是可為 Null 的型別。

ASP.NET Core 6.0 專案預設會啟用可為 Null 的參考型別。 如需詳細資訊,請參閱 可為 Null 的參考型別

複製 ProductsController

  1. 以滑鼠右鍵按一下 Controllers 資料夾。
  2. 選取 [新增]>[控制器...]
  3. [新增新的 Scaffolded 項目] 對話方塊中,選取 [MVC 控制器 - 空白]然後選取 [新增]
  4. 將控制器命名為 ProductsController,然後選取 [新增]
  5. 使用下列項目取代範本控制器:
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;
    }
}

上述醒目提示的程式碼會變更下列項目,以移轉至 ASP.NET Core:

  • 針對 ASP.NET Core 中不存在的下列 ASP.NET 4.x 元件移除 using 陳述式:

    • ApiController 類別
    • System.Web.Http 命名空間
    • IHttpActionResult 介面
  • using ProductsApp.Models; 陳述式變更為 using ProductsCore.Models;

  • 將根命名空間設定為 ProductsCore

  • ApiController 變更為 ControllerBase

  • 新增 using Microsoft.AspNetCore.Mvc; 以解析 ControllerBase 參考。

  • GetProduct 動作的傳回型別從 IHttpActionResult 變更為 ActionResult<Product>。 如需詳細資訊,請參閱 控制器動作傳回類型

  • GetProduct 動作的 return 陳述式簡化為下列陳述式:

    return product;
    
  • 新增下列屬性,這些屬性會在下一章節中說明:

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

路由

ASP.NET Core 提供最少的裝載模型,其中端點路由中介軟體會包裝整個中介軟體管線,因此可以直接將路由新增至 WebApplication,而不需要明確呼叫 UseEndpointsUseRouting 來註冊路由。

UseRouting 仍然可以用來指定路由比對發生的位置,但如果路由應在中介軟體管線的開頭進行配對,則不需要明確呼叫 UseRouting

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();

注意: 路由直接新增至管線尾端WebApplication 執行。

已移轉 ProductsController 中的路由

已移轉的 ProductsController 包含下列反白顯示的屬性:

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;
    }
}
  • [Route] 屬性 會設定控制器的屬性路由 模式。

  • [ApiController] 屬性讓屬性路由成為此控制器中所有動作的要求。

  • 屬性路由支援權杖,例如 [controller][action]。 在執行時間,每個權杖會分別取代為套用屬性的控制器或動作名稱。 權杖:

    • 減少或排除對路由使用硬式編碼字串的需求。
    • 確定套用自動重新命名重構時,路由會與對應的控制器和動作保持同步。
  • HTTP 取得要求會針對具有下列屬性的 ProductController 動作啟用:

    • 套用至 GetAllProducts 動作的 [HttpGet] 屬性。
    • 套用至 GetProduct[HttpGet("{id}")] 屬性。

執行已移轉的專案,然後瀏覽至 /api/products。 例如: https://localhost:<port>/api/products。 隨即出現三個產品的完整清單。 瀏覽至 /api/products/1。 第一個產品隨即出現。

檢視或下載範例程式碼 \(英文\) (如何下載)

其他資源

本文示範從 ASP.NET 4.x Web API 移轉至 ASP.NET Core MVC 所需的步驟。

檢視或下載範例程式碼 \(英文\) (如何下載)

必要條件

檢閱 ASP.NET 4.x Web API 專案

本文會使用 [ASP.NET Web API 2 使用者入門] 中建立的 [ProductsApp] 專案。 在該專案中,基本的 ASP.NET 4.x Web API 專案設定如下。

Global.asax.cs 中,會呼叫 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);
        }
    }
}

WebApiConfig 類別位於 [App_Start] 資料夾中,且具有靜態 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 }
            );
        }
    }
}

上述類別:

  • 會設定 屬性路由,雖然它實際上並未使用。
  • 設定路由表。 範例程式碼預期 URL 符合格式 /api/{controller}/{id},且 {id} 為選擇性。

下列各章節會示範如何將 Web API 專案移轉至 ASP.NET Core MVC。

建立目的地專案

在 Visual Studio 中建立新的空白解決方案,並新增要移轉的 ASP.NET 4.x Web API 專案:

  1. 從 [檔案] 功能表選取 [新增] >[專案] 。
  2. 選取 [空白解決方案] 範本,然後選取 [下一步]
  3. 將解決方案命名為 WebAPIMigration。 選取建立
  4. 將現有的 ProductsApp 專案新增至解決方案。

新增新 API 專案以移轉至:

  1. 將新的 ASP.NET Core Web 應用程式 專案新增至解決方案。
  2. [設定新專案] 對話方塊中,將專案命名為 [ProductsCore],然後選取 [建立]
  3. [建立新的 ASP.NET Core Web 應用程式] 對話方塊中,確認已選取 [.NET Core][ASP.NET Core 3.1]。 選取 [API] 專案範本,然後選取 [確定]
  4. 從新的 ProductsCore 專案中移除 WeatherForecast.csControllers/WeatherForecastController.cs 範例檔案。

解決方案包含兩個專案。 下列各章節會說明如何將 ProductsApp 專案的內容移轉至 ProductsCore 專案。

移轉組態

ASP.NET Core 不會使用 App_Start 資料夾或 Global.asax 檔案。 除此之外,web.config 檔案會在發佈時新增。

Startup 類別:

  • 取代 Global.asax
  • 處理所有應用程式啟動工作。

如需詳細資訊,請參閱 ASP.NET Core 中的應用程式啟動

移轉模型與控制器

下列程式碼顯示要更新 ASP.NET Core 的 ProductsController:

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);
        }
    }
}

更新 ASP.NET Core 的 ProductsController:

  1. Controllers/ProductsController.cs[模型] 資料夾從原始專案複製到新的專案。
  2. 將複製的檔案根命名空間變更為 ProductsCore
  3. using ProductsApp.Models; 陳述式更新為 using ProductsCore.Models;

ASP.NET Core 中不存在下列元件:

  • ApiController 類別
  • System.Web.Http 命名空間
  • IHttpActionResult 介面

進行下列變更:

  1. ApiController 變更為 ControllerBase。 新增 using Microsoft.AspNetCore.Mvc; 以解析 ControllerBase 參考。

  2. 刪除 using System.Web.Http;

  3. GetProduct 動作的傳回型別從 IHttpActionResult 變更為 ActionResult<Product>

  4. GetProduct 動作的 return 陳述式簡化為下列項目:

    return product;
    

設定路由

ASP.NET Core API 專案範本會在產生的程式碼中包含端點路由設定。

下列 UseRoutingUseEndpoints 呼叫:

  • 中介軟體 管線中註冊路由比對和端點執行。
  • 取代 ProductsApp 專案的 App_Start/WebApiConfig.cs 檔案。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseHttpsRedirection();

    app.UseRouting();

    app.UseAuthorization();

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

設定路由,如下所示:

  1. 使用下列屬性標記 ProductsController 類別:

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

    上述 [Route] 屬性會設定控制器的屬性路由模式。 [ApiController] 屬性讓屬性路由成為此控制器中所有動作的要求。

    屬性路由支援權杖,例如 [controller][action]。 在執行時間,每個權杖會分別取代為套用屬性的控制器或動作名稱。 權杖:

    • 減少專案中的魔術字串數目。
    • 確定套用自動重新命名重構時,路由會與對應的控制器和動作保持同步。
  2. 啟用 HTTP 取得 ProductsController 動作的要求:

    • [HttpGet] 屬性套用至 GetAllProducts 動作。
    • [HttpGet("{id}")] 屬性套用至 GetProduct 動作。

執行已移轉的專案,然後瀏覽至 /api/products。 隨即出現三個產品的完整清單。 瀏覽至 /api/products/1。 第一個產品隨即出現。

其他資源