web-dev-qa-db-ja.com

ASP.NET Core Web APIでバージョン管理を行う方法

以前のasp.net web apiでは、DefaultHttpControllerSelectorを実装して、リクエストでコントローラーを見つける方法を指定しました。私はしばしば異なる名前の異なるコントローラーを持っていますが、同じプロセスを対象としています。唯一の違いは、一方が他方よりも高いバージョンであることです。

たとえば、BookingV1Controllerという名前のコントローラーを使用できます。これは、サービスのバージョン1を処理するためのものです。また、サービスのバージョン2を処理するように設計されたBookingV2Controllerも必要です。クライアントアプリケーションは、このURL http://myservice.com/api/v2/booking/someaction?id=12を使用してサービスにリクエストを送信します。リクエストを処理するため、DefaultHttpControllerSelectorのカスタム実装を提供して、リクエストされたバージョンに基づいて必要なコントローラーの適切なバージョンを選択します。

ただし、ASP.NET Coreでこれを行う方法がないようです。私は無駄にどこでも検索しました。どちらにも役立つドキュメントはありません。

ここで誰かが助けてくれるとありがたいです。ありがとう。

[〜#〜] update [〜#〜]カスタムヘッダーでバージョンが指定されている場合の対処方法も知りたいです。例:X-Version:v1

更新2

要件は、サービスのバージョンをURLで公開しないことでした。バージョンが存在しない場合、サービスはバージョンを追加する方法の指示とともに戻ります。要求されたコントローラが要求されたバージョンに存在しない場合、システムは下位バージョンを検索します。以前のバージョンで見つかった場合は、それを使用します。これは、すべてのバージョンでコントローラが繰り返されないようにするためです。ただし、ASP.NET Coreでは、これができない場合があります。

この問題に頭を数日間叩いた直後に、この目的のためのパッケージを作成しました。属性は必要ありません。

https://github.com/GoAheadTours/NamespaceVersioning

要約すると、IApplicationModelConventionをスタートアップファイルに登録して、コントローラーを反復処理し、名前空間に基づいてルートを登録することができます。 v1フォルダーを作成し、コントローラーを中に入れました

IApplicationModelConventionを実装するクラスは、アプリケーションのコントローラーとその既存のルートにアクセスできるApplicationModelパラメーターを使用してApplyメソッドを実装します。コントローラのクラスにルートが設定されていない場合、名前空間からバージョンを取得し、事前定義されたURLプレフィックスを使用して、そのバージョンのルートを生成します。

public void Apply(ApplicationModel application) {
    foreach (var controller in application.Controllers) {
        var hasRouteAttribute = controller.Selectors.Any(x => x.AttributeRouteModel != null);
        if (hasRouteAttribute) {
            continue;
        }
        var nameSpace = controller.ControllerType.Namespace.Split('.');
        var version = nameSpace.FirstOrDefault(x => Regex.IsMatch(x, @"[v][\d*]"));
        if (string.IsNullOrEmpty(version)) {
            continue;
        }
        controller.Selectors[0].AttributeRouteModel = new AttributeRouteModel() {
            Template = string.Format(urlTemplate, apiPrefix, version, controller.ControllerName)
        };
    }
}

私はすべてのコードをgithubに用意しており、パッケージへのリンクもnugetにあります

11
Peter Lazzarino

これは私が偶然見つけた非常に古い質問ですが、今はもっと良い解決策があります。このパッケージがあります

Microsoft.AspNetCore.Mvc.Versioning

これには、バージョン管理を実装するためのはるかに機能豊富な方法があります。これには、URLクエリ文字列、URLパス、ヘッダー、またはカスタムバージョンリーダーを使用できることが含まれます。 HTTPContextなどからバージョンを読み取ることができる.

つまり、startup.csのConfigureServicesメソッドに以下を追加します。

services.AddApiVersioning(o => {
    o.ReportApiVersions = true;
    o.AssumeDefaultVersionWhenUnspecified = true;
            o.DefaultApiVersion = new ApiVersion(1, 0);
});

次に、コントローラーをApiVersionで装飾する必要があります。

[ApiVersion("1.0")]
[Route("api/home")]
public class HomeV1Controller : Controller
{
    [HttpGet]
    public string Get() => "Version 1";
}

[ApiVersion("2.0")]
[Route("api/home")]
public class HomeV2Controller : Controller
{
    [HttpGet]
    public string Get() => "Version 2";
}

ルートに配置することで、パスに実装することもできます。

[ApiVersion("1.0")]
[Route("api/{version:apiVersion}/home")]
public class HomeV1Controller : Controller
{
    [HttpGet]
    public string Get() => "Version 1";
}

[ApiVersion("2.0")]
[Route("api/{version:apiVersion}/home")]
public class HomeV2Controller : Controller
{
    [HttpGet]
    public string Get() => "Version 2";
}

Microsoftパッケージを介して実際に実装するこのメソッドを実行すると、バージョンを非推奨にしたり、バージョンを検出したり、HttpContextからバージョン番号に簡単にアクセスしたりすることができることも意味します。ルートにハードコードされています。

詳細情報(ヘッダーでの使用を含む):

21
MindingData

バージョンを制御するには、ルーティング属性を使用します。

つまり.

[Route("api/v1/[controller]")]
public class BookingV1Controller : Controller
{
  ....
}

[Route("api/v2/[controller]")]
public class BookingV2Controller : Controller
{
  ....
}

標準のWeb Apiおよび.NET Core ASP.NETからの移行に関する詳細については、以下を参照してください。 MSDN:Migrating from ASP.NET Web Api

8
toadflakz

そのためには、ASP.NET CoreアプリケーションにサービスAPIのバージョン管理を追加します

  public void ConfigureServices( IServiceCollection services )
    {
        services.AddMvc();
        services.AddApiVersioning();

        // remaining other stuff omitted for brevity
    }

QUERYSTRING PARAMETER VERSIONING

[ApiVersion( "2.0" )]
[Route( "api/helloworld" )]
public class HelloWorld2Controller : Controller {
    [HttpGet]
    public string Get() => "Hello world!";
}

つまり、これは、同じルートを持つ別のコントローラーで2.0を1.0よりも大きくすることを意味します。ここに行きます。

/api/helloworld?api-version=2.0

名前空間が異なる同じコントローラ名を持つことができます

URL PATHセグメントのバージョン

 [ApiVersion( "1.0" )]
 [Route( "api/v{version:apiVersion}/[controller]" )]
 public class HelloWorldController : Controller {
    public string Get() => "Hello world!";
 }
[ApiVersion( "2.0" )]
[ApiVersion( "3.0" )]
[Route( "api/v{version:apiVersion}/helloworld" )]
public class HelloWorld2Controller : Controller {
    [HttpGet]
    public string Get() => "Hello world v2!";

    [HttpGet, MapToApiVersion( "3.0" )]
    public string GetV3() => "Hello world v3!";
}

ヘッダーのバージョン管理

  public void ConfigureServices( IServiceCollection services )
    {
        services.AddMvc();
        services.AddApiVersioning(o => o.ApiVersionReader = new HeaderApiVersionReader("api-version"));
    }

HeaderApiVersioningを実行すると、ブラウザーでGETを実行するだけではできないため、Postmanを使用してヘッダーを追加します(または、Curl、WGet、PowerShell、または単体テストを使用できます)。

画像

参照してください https://www.hanselman.com/blog/ASPNETCoreRESTfulWebAPIVersioningMadeEasy.aspx

1
Sumesh Es