WebAPIをバージョン管理する方法

可能な限り同じURIを維持しながら、常にWebAPIをバージョン管理する必要があります。本番環境で稼働していて、ユーザーによって消費されているWebAPIがある状況を想像してみてください。ここで、Web APIにさらに多くの機能が必要であるが、既存の機能をそのまま維持する必要があるとします。古いAPIをまだ必要としているユーザーもいれば、新機能または拡張機能を備えたバージョンが必要なユーザーもいます。これはまさにWebAPIのバージョン管理が助けになるところです。

次のいずれかの方法でWebAPIをバージョン管理できます。

  1. URLを使用:バージョン情報は、クエリ文字列としてURLで指定されます。
  2. カスタムリクエストヘッダーを使用する:コントローラーのバージョン情報はリクエストヘッダーで指定され、URLを変更する必要はありません。
  3. Acceptヘッダーを使用する:Acceptヘッダーは通常、メディアタイプと文字エンコードを定義します。URLを変更せずに、acceptヘッダーを介してWebAPIのバージョン情報を渡すことができます。

URLを使用したWebAPIのバージョン管理

命名されている次のWeb APIコントローラー、考えてみましょう AuthorsV1ControllerAuthorsV2Controller、それぞれを。

パブリッククラスAuthorsV1Controller:ApiController

    {{

        [HttpGet]

        public IEnumerable GetAuthors()

        {{

          新しい文字列を返す[] {"Joydip Kanjilal"、 "Gerben Wierda"};

        }

    }

パブリッククラスAuthorsV2Controller:ApiController

    {{

        [HttpGet]

        public IEnumerable GetAuthors()

        {{

            新しい文字列を返す[] {"Joydip Kanjilal、INDIA"、 "Gerben Wierda、Netherlands"};

        }

    }

この図を簡略化するためにGetAuthors()、各コントローラーで指定されたメソッドを組み込みました。ながらGetAuthors()AuthorsV1Controller戻っのみ著者名、GetAuthors()AuthorsV2Controller(新バージョン)著者が存在する国の名前と一緒に著者名を返します。

次のコードスニペットは、2つのコントローラーがWebApiConfigクラスのRegisterメソッドをどのように使用するかを示しています。

config.Routes.MapHttpRoute(

                名前: "WebAPIV1"、

                routeTemplate: "api / v1 / {controller} / {id}"、

                デフォルト:new {controller = "AuthorsV1Controller"、action = "GetAuthors"、id = RouteParameter.Optional}

            );

config.Routes.MapHttpRoute(

                名前: "WebAPIV2"、

                routeTemplate: "api / v2 / {controller} / {id}"、

                デフォルト:new {controller = "AuthorsV2Controller"、action = "GetAuthors"、id = RouteParameter.Optional}

            );

これでGetAuthors、次のURLを使用してWebAPIメソッドを呼び出すことができます。

// localhost / WebAPI / api / v1 / Authors / GetAuthors

リクエストヘッダーを使用したWebAPIのバージョン管理

リクエストヘッダーを使用して、WebAPIのバージョン管理を実装することもできます。これを実現するには、クラスを拡張するカスタムクラスを実装してから、カスタムクラスでDefaultHttpControllerSelectorオーバーライドする必要がありSelectControllerます。DefaultHttpControllerSelectorクラスがIHttpControllerSelectorインターフェースを実装していることに注意してください。 内部でSelectController呼び出しGetControllerName、のインスタンスをHttpRequestMessageパラメータとして受け入れます。

次のコードスニペットは、リクエストヘッダーからバージョン情報を取得する方法を示しています。

プライベート文字列GetControllerVersionFromRequestHeader(HttpRequestMessage request)

        {{

            var acceptHeader = request.Headers.Accept;

            const string headerName = "バージョン";

            string controllerVersion = string.Empty;

            if(request.Headers.Contains(headerName))

            {{

                controllerVersion = "V" + request.Headers.GetValues(headerName).First();               

            }

            controllerVersionを返します。

        }

acceptヘッダーを使用したWebAPIのバージョン管理

次のメソッドは、acceptヘッダーからWebAPIのバージョン情報を取得する方法を示しています。このメソッドはMIMEタイプをチェックし、バージョン情報を適切に返します。メディアタイプが。でないapplication/json場合、デフォルトバージョンはとして返されV1ます。

private string GetControllerVersionFromAcceptHeader(HttpRequestMessage request)

        {

            var acceptHeader = request.Headers.Accept;

            string controllerVersion = string.Empty;

            foreach (var mime in acceptHeader)

            {

                if (mime.MediaType.Equals("application/json"))

                {

                    NameValueHeaderValue version = mime.Parameters.FirstOrDefault(v => v.Name.Equals("Version", StringComparison.OrdinalIgnoreCase));

                    controllerVersion = "V" + version.Value.ToString();

                    return controllerVersion;

                }

            }

            return "V1";

        }

You can invoke your Web API from Fiddler by passing the accept header as shown below.

Accept: application/json; charset=utf-8;version=2

The following code listing illustrates how you can override SelectController to select a controller dynamically. Note how GetControllerVersionFromRequestHeader has been used. If you would like to retrieve the controller version from the accept header, you should leverage GetControllerVersionFromAcceptHeader instead.

public override HttpControllerDescriptor SelectController(HttpRequestMessage request)

        {

            try

            {

                string controllerName = base.GetControllerName(request);

                var controllers = GetControllerMapping();

                var routeData = request.GetRouteData();

                string controllerVersion = GetControllerVersionFromRequestHeader(request);             

                controllerName = String.Format("{0}{1}", controllerName, controllerVersion);

                HttpControllerDescriptor controllerDescriptor;

                if (!controllers.TryGetValue(controllerName, out controllerDescriptor))

                {

                    string message = "No HTTP resource was found that matches the specified request URI {0}";

                    throw new HttpResponseException(request.CreateErrorResponse(System.Net.HttpStatusCode.NotFound, String.Format(message, request.RequestUri)));

                }

                return controllerDescriptor;

            }

            catch (Exception ex)

            {

                throw new HttpResponseException(request.CreateErrorResponse(System.Net.HttpStatusCode.NotFound, String.Format(ex.Message, request.RequestUri)));

            }

        }

You should add the following line in the Register method of the WebApiConfig class to provide support for controller selection at runtime.

config.Services.Replace(typeof(IHttpControllerSelector)、new ControllerSelector((config)));

これで、Fiddlerを使用してWeb APIをテストできます— Fiddlerのcomposerタブを使用して、必要に応じてURLとバージョン情報を提供します。Web APIコントローラーのバージョン2を呼び出す場合はVersion: 2、Fiddlerの[Composer]タブでリクエストヘッダー情報を作成するときに指定する必要があります。