ASP.NET Core 将 ASP.NET 4.x 的 MVC 和 Web API 应用模型合并为称为 ASP.NET Core MVC 的单个编程模型。
本文介绍如何将 ASP.NET Web API 2 入门中创建的产品控制器迁移到 ASP.NET Core。
Prerequisites
- 带有 ASP.NET 和 Web 开发工作负载的 Visual Studio 2022。
- .NET 6 SDK
创建新的 ASP.NET Core Web API 项目
- 在“文件”菜单中,选择 “新建>项目”。
- 在搜索框中输入 Web API。
- 选择 ASP.NET 核心 Web API 模板,然后选择“下一步”。
- 在 配置新项目 对话框中,将项目命名为 ProductsCore,然后选择 下一步。
- 在“其他信息”对话框中:
- 确认 框架 为 .NET 6.0(长期支持)。
- 确认已选中“使用控制器(取消选中以使用最小 API)”复选框。
- 取消选中“启用 OpenAPI 支持”。
- 选择 创建。
删除 WeatherForecast 模板文件
- 从新的
WeatherForecast.cs项目中删除Controllers/WeatherForecastController.cs和 示例文件。 - 打开属性\launchSettings.json。
- 将
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();
复制 产品 模型
- 在 解决方案资源管理器中,右键单击项目。 选择“添加>新文件夹。 把文件夹命名为 Models。
- 右键单击 模型 文件夹。 选择添加>类。 将类命名为“产品”,然后选择“添加”。
- 将模板模型代码替换为以下内容:
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; }
}
}
上述突出显示的代码将更改以下内容:
- 添加了
?批注,以将Name和Category属性声明为可为 null 的引用类型。
通过利用 C# 8 中引入的Nullable 功能,ASP.NET Core 可以在处理引用类型时提供额外的代码流分析和编译时安全性。 例如,防止 null 引用异常。
在这种情况下,意图是 Name 和 Category 可以是可为空的类型。
在 .NET 6 项目的 ASP.NET Core 中,默认启用可空引用类型。 有关详细信息,请参阅可为空引用类型。
复制 ProductsController
- 右键单击 控制器 文件夹。
- 选择 添加 > 控制器...。
- 在“添加新基架项”对话框中,选择“Mvc 控制器 - 空”,然后选择“添加”。
- 将控制器命名为 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;
}
}
上述突出显示的代码将更改以下内容,以迁移到 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}")]
Routing
ASP.NET Core 提供最少的托管模型,其中终结点路由中间件包装整个中间件管道,因此可以直接将路由添加到 WebApplication,而无需显式调用 UseEndpoints 或 UseRouting 来注册路由。
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]。 在运行时,每个令牌分别替换为应用了该属性的控制器或操作的名称。 令牌:- 减少或消除对路由使用硬编码字符串的需要。
- 在应用自动重命名重构时,确保路由与相应的控制器和动作保持同步。
为
ProductController操作启用了具有以下属性的 HTTP Get 请求:-
[HttpGet]属性应用于GetAllProducts动作。 -
[HttpGet("{id}")]属性应用于GetProduct动作。
-
运行迁移的项目,并浏览到 /api/products。 例如:https://localhost:<port>/api/products。 将显示三个产品的完整列表。 导航至 /api/products/1 。 第一个产品出现了。
其他资源
- 使用 ASP.NET Core 创建 Web API
- ASP.NET Core Web API 中控制器操作的返回类型
- ASP.NET Core MVC 的 兼容性版本
本文演示从 ASP.NET 4.x Web API 迁移到 ASP.NET Core MVC 所需的步骤。
Prerequisites
- 具有 ASP.NET 和 Web 开发工作负载的 Visual Studio 2019 16.4 或更高版本
- .NET Core 3.1 SDK
查看 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 项目以迁移:
- 在“文件”菜单中,选择 “新建>项目”。
- 选择“空白解决方案”模板,然后选择“下一步”。
- 将解决方案命名为 WebAPIMigration。 选择 创建。
- 将现有的 ProductsApp 项目添加到解决方案。
添加新的 API 项目以迁移到:
- 将新的 ASP.NET Core Web 应用程序 项目添加到解决方案。
- 在“配置新项目”对话框中,将项目命名为 ProductsCore,然后选择“创建 ”。
- 在“创建新的 ASP.NET 核心 Web 应用程序 对话框中,确认已选择 .NET Core 和 ASP.NET Core 3.1。 选择“API”项目模板,然后选择“创建” 。
- 从新的
WeatherForecast.cs项目中删除Controllers/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:
- 将
Controllers/ProductsController.cs和 模型 文件夹从原始项目复制到新项目。 - 将复制文件的根命名空间更改为
ProductsCore。 - 将
using ProductsApp.Models;语句更新为using ProductsCore.Models;。
ASP.NET Core 中不存在以下组件:
-
ApiController类 -
System.Web.Http命名空间 -
IHttpActionResult接口
进行以下更改:
将
ApiController更改为 ControllerBase。 添加using Microsoft.AspNetCore.Mvc;以解析ControllerBase引用。删除
using System.Web.Http;。将
GetProduct作的返回类型从IHttpActionResult修改为ActionResult<Product>。将
GetProduct动作的return语句简化为以下内容:return product;
配置路由
ASP.NET Core API 项目模板包括生成的代码中的终结点路由配置。
以下 UseRouting 和 UseEndpoints 调用会执行以下操作:
- 在中间件管道中注册路由匹配和终结点执行。
- 替换 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();
});
}
按如下所示配置路由:
使用以下属性标记
ProductsController类:[Route("api/[controller]")] [ApiController]前面的
[Route]属性配置控制器的属性路由模式。[ApiController]属性把属性路由设为此控制器中所有操作的必要条件。属性路由支持令牌,例如
[controller]和[action]。 在运行时,每个令牌分别替换为应用了该属性的控制器或操作的名称。 令牌:- 减少项目中的魔法字符串数量。
- 在应用自动重命名重构时,确保路由与相应的控制器和动作保持同步。
启用对
ProductsController操作的 HTTP GET 请求。- 将
[HttpGet]属性应用于GetAllProducts操作。 - 将
[HttpGet("{id}")]属性应用于GetProduct操作。
- 将
运行迁移的项目,并浏览到 /api/products。 将显示三个产品的完整列表。 导航至 /api/products/1 。 第一个产品出现了。
其他资源
- 使用 ASP.NET Core 创建 Web API
- ASP.NET Core Web API 中控制器操作的返回类型
- ASP.NET Core MVC 的 兼容性版本