如何在 C# ASP.NET WebAPI 中使用 Accept 頭進行版本控制?


Accept 頭告訴伺服器瀏覽器希望以何種檔案格式接收資料。這些檔案格式通常稱為 MIME 型別。MIME 代表多用途網際網路郵件擴充套件。

版本控制可以像下面這樣在請求頭中傳送。

Version=1 StudentsV1Controller
Version=2 StudentsV2Controller

由於我們尚未在 Accept 頭中處理版本資訊,因此我們收到 404 未找到錯誤,因為我們只有 StudentV1 和 StudentV2 控制器。讓我們新增我們自己的 **自定義控制器選擇器**,它實現了 DefaultHttpControllerSelector 類。

**自定義控制器選擇器** −

示例

using System.Linq;
using System.Net.Http;
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 = "";
         var acceptHeader = request.Headers.Accept.Where(a => a.Parameters
         .Count(p => p.Name.ToLower() == "version") > 0);
         if (acceptHeader.Any()){
            versionNumber = acceptHeader.First().Parameters
            .First(p => p.Name.ToLower() == "version").Value;
         }
         HttpControllerDescriptor controllerDescriptor;
         if (versionNumber == "1"){
            controllerName = string.Concat(controllerName, "V1");
         }
         else if (versionNumber == "2"){
            controllerName = string.Concat(controllerName, "V2");
         }
         if (controllers.TryGetValue(controllerName, out controllerDescriptor)){
            return controllerDescriptor;
         }
         return null;
      }
   }
}

接下來,我們需要用自定義控制器選擇器替換預設的控制器選擇器。這在 WebApiConfig.cs 檔案中完成。請注意,我們用自定義控制器選擇器替換了 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 }
      );
   }
}

**StudentV1Controller** −

示例

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 控制器獲得的結果,其中包含 Accept 頭中的版本資訊。


更新於:2020年8月19日

536 次瀏覽

開啟您的 職業生涯

完成課程獲得認證

開始學習
廣告