ASP.NET Web API 2.1 その 1
ASP.NET Web API 2.1 で追加された機能をみてみました。
概要
☆が付いているのは、クライアント側の HttpClient ライブラリにも関係する更新です。
- Global Error Handling
- 属性ベースルーティングの改善
- ヘルプページの機能追加
- IgnoreRoute のサポート
- BSON Media Type Formatter の追加(☆クライアント側も)
- フィルター属性の非同期対応
- クエリ文字列の解析と構築(☆クライアント側も)
- バグ修正
リリースノート:What's New in ASP.NET Web API 2.1 : The Official Microsoft ASP.NET Site
NuGet:Microsoft ASP.NET Web API 2.1 5.1.0
Global Error Handling
長くなったので ASP.NET Web API 2.1 その 2 ~Global Error Handling~ にて記載。
属性ベースルーティングの改善
属性ベースルーティングにてルート制約(IHttpRouteConstraint)を追加できるようになりました。これにより、ルーティングの条件にてヘッダーの値を参照するといったことが可能になりました。
ASP.NET Web API 2.1 と ASP.NET MVC 5.1 両方で更新された機能です。
サンプル では、ヘッダー「api-version」で API のバージョンを指定し、該当する ApiController にマッピングするといったことを行っています。
こんな感じ↓
[VersionedRoute("api/Customer", 1)] public class CustomerVersion1Controller : ApiController {} [VersionedRoute("api/Customer", 2)] public class CustomerVersion2Controller : ApiController { } // VersionedRoute 属性はサンプル内で実装されているクラス
利用するには、RouteFactoryAttribute クラスを継承した属性クラスを作成し、プロパティにルート制約(IHttpRouteContraint)を指定し、属性を付与する、といった流れになります。
RouteFactoryAttribute.cs には、DataToken や Defaults のプロパティがあるので、他にもいろいろ指定できるかもしれません。
今までは
今までは、↓“{id:int}”のようにパラメーターによる制約しか利用できませんでした。
[Route("users/{id:int}"] public User GetUserById(int id) { ... }
(ちなみにこの “int”といった文字列指定による制約は、カスタマイズ可能です。参照:ASP.NET Web API 2 – Route Constraints)
ヘルプページの機能追加
ヘルプページに次の2つの機能が追加されました。
- API のパラメーターと戻り値に定義される型の情報、型専用ページの追加。
- Data Annotations 属性の情報。
ヘルプページの NuGet パッケージは「Microsoft.AspNet.WebApi.HelpPage -Version 5.1.0」になります。
例として、↓のように Data Annotations 属性を付けた Book クラスと、戻り値・パラメーターがともに Book クラスであるAPI の場合を見てみます。
/// <summary> /// 本 /// </summary> public class Book { public int Id { get; set; } /// <summary> /// タイトル /// </summary> [Required] public string Title { get; set; } /// <summary> /// 番号 /// </summary> [Range(1, 100)] public int Number { get; set; } /// <summary> /// ノート /// </summary> [StringLength(100, MinimumLength = 3)] public string Note { get; set; } }
public class BooksController : ApiController { public Book PostBook(Book book); }
Book クラスのドキュメントページが新たに追加され、API ページにはそのリンクと、型や Data Annotations 属性の情報と共に、パラメーターと戻り値の説明が表示されます。
(↓の左は以前のバージョンのものです。)
プロパティが複合型の場合は、その型専用ページへのリンクが貼ってあります。Enum も対応。
今回の更新により、クエリ文字列を↓のように [FromUri] を付けてクラスで定義した場合でも、どのようなクエリ文字のキーでリクエストすれば良いか分かるようになりました。
public ItemDetails GetBooks([FromUri]Book parameter);
ヘルプページ作成のために使用されるクラスは、以前と同様にプロジェクト内に含まれるため、カスタマイズは可能です。独自の検証属性への対応も簡単そうです。
IgnoreRoute のサポート
ASP.NET MVC と同じように、ルーティングの設定にて特定のルートを無視する設定ができるようになりました。↓のように、IgnoreRoute メソッドで無視したい URL パターンを定義します。
public static class WebApiConfig { public static void Register(HttpConfiguration config) { //↓無視ルート追加 api/values は無視するように設定。 config.Routes.IgnoreRoute( routeName: "IgnoreRoute", routeTemplate: "api/values"); // ↓デフォルトのルート config.Routes.MapHttpRoute( name: "DefaultApi", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional } ); } }
この例の場合、「api/values」でアクセスすると 404 Not Found を返します。
これまでと同様に記述する順番に注意。(例の場合、デフォルトのルートの後に IgnoreRoute(…) を記述すると、「api/values」はデフォルトのルートの方にマッチします。)
BSON Media Type Formatter の追加
System.Net.Http.Formatting ライブラリに、コンテンツタイプ「application/bson」に対応する BsonMediaTypeFormatter クラスが追加されました。クライアント(HttpClient)とサーバー側双方での対応になります。
サーバー側で対応する場合は、↓のように Media Type Formatter を追加する必要があります。
using System.Net.Http.Formatting; using System.Web.Http; namespace WebApplication39 { public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Formatters.Add(new BsonMediaTypeFormatter()); …
公式にてサンプルが用意されています。:BSONSample
BSON についてはこちら:http://bsonspec.org/
フィルター属性の非同期対応
既存の3つのフィルター属性にて非同期がサポートされました。
- AuthorizationFilterAttribute
- ActionFilterAttribute
- ExceptionFilterAttribute
(ASP.NET Web API 2.0 で追加された IAuthenticationFilter は非同期対応で、もともと同期で処理する実装クラスが用意されてません。)
今までは、OnActionExecuting メソッド等に処理を記述していましたが、新たに用意された On*Async メソッドをオーバーライドすることで、非同期に処理することができます。
例えば、ActionFilterAttribute クラスを継承してカスタム属性を作成する場合、以下の4つのメソッドをオーバーライドすることができます。
using System.Web.Http.Controllers; using System.Web.Http.Filters; using System.Threading; using System.Threading.Tasks; namespace WebApplication39.Models { public class MyFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(HttpActionContext actionContext) { } public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext) { } public override async Task OnActionExecutingAsync(HttpActionContext actionContext, CancellationToken cancellationToken) { //await Task.Delay(1000); } public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken) { //await Task.Delay(1000); } } }
後半の 2 つの On*Async が新たに用意されたメソッドです。他のフィルター属性でも、既存の同期用メソッドに対応して、非同期用のメソッドが新たに用意されています。
同期と非同期の両方をオーバーライドしてコードを書いたらどうなるの?と気になるところです。On*Async をオーバーライドした場合、同期の方のメソッドである On* メソッドは実行されません。(On*Async をオーバーライドせずに On* メソッドを記述すると、On* メソッドは実行されます。)
また、もともと Web API のフィルター属性は非同期設計されているので、2.1 にしなくともActionFilterAttribute クラスのように自前で実装すれば実現できます。
クエリ文字列の解析と構築
これは、クライアント側の Portable Class Library の更新になります。System.Net.Http.Formatting ライブラリにて、クエリ文字列の解析・構築用の HttpValueCollection クラスが公開されます。
(ASP.NET Web API プロジェクトでは利用できない?)
内容は、リリースノートにあるサンプルコードを見たほうが早いです。
Query parsing support for the client formatting library
NuGet : Microsoft ASP.NET Web API 2.1 Client Libraries 5.1.0
HttpValueCollection クラス(System.Net.Http.Formatting)