如何在 C# ASP.NET WebAPI 中使用查询字符串参数进行版本控制?
WebApi 中的 **DefaultHttpControllerSelector** 类负责选择我们在 URI 中发送的相应控制器操作方法。
假设我们必须在查询字符串中实现版本控制,如下所示
v=1 StudentsV1Controller (Version 1) v=2 StudentsV2Controller (Version 2)
如果我们在查询字符串中传递版本信息,例如 https://127.0.0.1:58174/api/student?v=1,则会返回 404 未找到错误响应,因为 DefaultHttpControllerSelector 中的 SelectController() 方法将查找 StudentsController,但我们只有 StudentsV1Controller 和 StudentsV2Controller。
为了处理这种情况,我们应该添加我们自己的 **CustomControllerSelector**,它实现了 DefaultHttpControllerSelector 类。
**CustomControllerSelector** −
示例
using System.Net.Http; using System.Web; using System.Web.Http; using System.Web.Http.Controllers; using System.Web.Http.Dispatcher; namespace WebAPI.Custom{ public class CustomControllerSelector : DefaultHttpControllerSelector{ private HttpConfiguration _config; public CustomControllerSelector(HttpConfiguration config) : base(config){ _config = config; } public override HttpControllerDescriptor SelectController(HttpRequestMessage request){ var controllers = GetControllerMapping(); var routeData = request.GetRouteData(); var controllerName = routeData.Values["controller"].ToString(); string versionNumber = "1"; var versionQueryString = HttpUtility.ParseQueryString(request.RequestUri.Query); if (versionQueryString["v"] != null){ versionNumber = versionQueryString["v"]; } if (versionNumber == "1"){ controllerName = controllerName + "V1"; } else if (versionNumber == "2"){ controllerName = controllerName + "V2"; } HttpControllerDescriptor controllerDescriptor; if (controllers.TryGetValue(controllerName, out controllerDescriptor)){ return controllerDescriptor; } return null; } } }
接下来我们需要用自定义控制器选择器替换默认的控制器选择器。这在 WebApiConfig.cs 文件中完成。请注意,我们正在用我们的 CustomControllerSelector 替换 IHttpControllerSelector。DefaultHttpControllerSelector 实现 IHttpControllerSelector,这就是我们替换 IHttpControllerSelector 的原因。
示例
public static class WebApiConfig{ public static void Register(HttpConfiguration config){ config.Services.Replace(typeof(IHttpControllerSelector), new CustomControllerSelector(config)); config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
**StudenV1Controller** −
using DemoWebApplication.Models; using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace DemoWebApplication.Controllers{ public class StudentV1Controller : ApiController{ List<StudentV1> students = new List<StudentV1>{ new StudentV1{ Id = 1, Name = "Mark" }, new StudentV1{ Id = 2, Name = "John" } }; public IEnumerable<StudentV1> Get(){ return students; } public StudentV1 Get(int id){ var studentForId = students.FirstOrDefault(x => x.Id == id); return studentForId; } } }
**StudentV2Controller** −
using DemoWebApplication.Models; using System.Collections.Generic; using System.Linq; using System.Web.Http; namespace DemoWebApplication.Controllers{ public class StudentV2Controller : ApiController{ List<StudentV2> students = new List<StudentV2>{ new StudentV2{ Id = 1, FirstName = "Roger", LastName = "Federer" }, new StudentV2{ Id = 2, FirstName = "Tom", LastName = "Bruce" } }; public IEnumerable<StudentV2> Get(){ return students; } public StudentV2 Get(int id){ var studentForId = students.FirstOrDefault(x => x.Id == id); return studentForId; } } }
输出
下面的输出显示了我们从 StudentV1 和 StudentV2 控制器获得的结果,并在查询字符串中进行了版本控制。
广告