ASP.NET 4.x Web API 是一种 HTTP 服务,它可达到各种客户端,包括浏览器和移动设备。 ASP.NET Core 将 ASP.NET 4.x 的 MVC 和 Web API 应用模型统一到称为 ASP.NET Core MVC 的更简单的编程模型中。 本文演示从 ASP.NET 4.x Web API 迁移到 ASP.NET Core MVC 所需的步骤。
警告
如果使用 Visual Studio 2017,请参阅 dotnet/sdk 问题 #3124,以了解无法与 Visual Studio 一起使用的 .NET Core SDK 版本的信息。
作为起点,本文使用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 } ); } } }
此类配置属性路由,不过实际上它并不是在项目中使用。 它还配置 ASP.NET Web API 使用的路由表。 在这种情况下,ASP.NET 4.x Web API 需要 Url 与格式 /api/{controller}/{id}
,{id}
是可选的。
ProductsApp项目包含一个控制器。 控制器继承自 ApiController
,其中包含两个操作:
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); } } }
ProductsController
使用的 Product
模型是一个简单的类:
namespace ProductsApp.Models { public class Product { public int Id { get; set; } public string Name { get; set; } public string Category { get; set; } public decimal Price { get; set; } } }
以下部分演示了如何将 Web API 项目迁移到 ASP.NET Core MVC。
在 Visual Studio 中完成以下步骤:
解决方案现在包含两个项目。 以下各节介绍了如何将ProductsApp项目的内容迁移到ProductsCore项目。
ASP.NET Core 不使用App_Start文件夹或global.asax文件,并且在发布时添加web.config文件。 Startup.cs是global.asa的替代,位于项目根目录中。 Startup
类处理所有应用启动任务。 有关更多信息,请参见ASP.NET Core 中的应用启动。
在 ASP.NET Core MVC 中,当在 Startup.Configure
中调用 UseMvc 时,默认情况下将包含特性路由。 以下 UseMvc
调用替换ProductsApp项目的App_Start/webapiconfig.cs文件:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseHsts(); } app.UseHttpsRedirection(); app.UseMvc(); }
复制ProductApp项目的控制器及其使用的模型。 按照以下步骤进行操作:
using ProductsApp.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;
按如下所示配置路由:
用以下特性标记 ProductsController
类:
[Route("api/[controller]")] [ApiController]
前面的[Route]
属性配置控制器的属性路由模式。 [ApiController]
特性使特性路由成为此控制器中所有操作的要求。
特性路由支持令牌,如 [controller]
和 [action]
。 在运行时,每个标记分别替换为应用了属性的控制器或操作的名称。 这些标记减少了项目中的幻字符串的数目。 标记还可确保在应用自动重命名重构时,路由与相应的控制器和操作保持同步。
将项目的兼容模式设置为 ASP.NET Core 2.2:
public void ConfigureServices(IServiceCollection services) { services.AddMvc() .SetCompatibilityVersion(CompatibilityVersion.Version_2_2); }
上述更改:
[ApiController]
特性。启用 ProductController
操作的 HTTP Get 请求:
GetAllProducts
操作应用[HttpGet]
特性。GetProduct
操作应用 [HttpGet("{id}")]
特性。前面的更改和删除未使用的 using
语句后, ProductsController.cs文件如下所示:
using System.Collections.Generic; using System.Linq; 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; } } }
运行迁移的项目,并浏览到 /api/products
。 此时会显示三个产品的完整列表。 浏览到 /api/products/1
。 第一个产品随即出现。
AspNetCore库提供兼容性填充码,以将 ASP.NET 4.X Web API 项目移动到 ASP.NET Core。 兼容性填充码扩展 ASP.NET Core,以支持 ASP.NET 4.x Web API 2 中的一些约定。 本文档前面的示例移植的基本操作足以确保兼容性填充程序是不必要的。 对于较大的项目,使用兼容性填充码对于临时桥接 ASP.NET Core 与 ASP.NET 4.x Web API 2 之间的 API 间隙非常有用。
Web API 兼容性填充码旨在用作一种临时度量,以支持将大型 ASP.NET 4.x Web API 项目迁移到 ASP.NET Core。 随着时间推移,应更新项目以使用 ASP.NET Core 模式,而不是依靠兼容性填充码。
Microsoft.AspNetCore.Mvc.WebApiCompatShim
中包含的兼容性功能包括:
ApiController
类型,以便不需要更新控制器的基类型。HttpRequestMessage
类型的参数。HttpResponseMessage
类型的结果。HttpResponseMessage
生成器:
CreateResponse<T>
CreateErrorResponse
BadRequestErrorMessageResult
ExceptionResult
InternalServerErrorResult
InvalidModelStateResult
NegotiatedContentResult
ResponseMessageResult
IContentNegotiator
的实例添加到应用的依赖项注入(DI)容器,并使WebApi中与内容协商相关的类型可用。 此类类型的示例包括 DefaultContentNegotiator
和 MediaTypeFormatter
。使用兼容性填充码:
Startup.ConfigureServices
中调用 services.AddMvc().AddWebApiConventions()
,将兼容性填充程序的服务注册到应用的 DI 容器。IApplicationBuilder.UseMvc
调用中 IRouteBuilder
上的 MapWebApiRoute
定义特定于 web API 的路由。