とりあえず、個人的によく使うと思ったOrderByとTopとSkipだけ。
using Microsoft.Data.OData.Query; using System.Collections.Generic; using System.Linq; using System.Web.Http.OData; using System.Web.Http.OData.Query; namespace MvcApplication5.Controllers { public class ProductsController : EntitySetController<Product, int> { private static readonly List<Product> Source = Enumerable .Range(1, 100) .Select(i => new Product { Id = i, Name = "Product" + i }) .ToList(); public override IQueryable<Product> Get() { var query = Source.AsQueryable(); if (this.QueryOptions.OrderBy != null) { // ポイント。プロパティに対してorderbyしたときはOrderByPropertyNodeという型になる foreach (var node in this.QueryOptions.OrderBy.OrderByNodes.OfType<OrderByPropertyNode>()) { // とりあえずNameプロパティのみソートに応じる方向で if (node.Property.Name == "Name") { query = node.Direction == OrderByDirection.Ascending ? query.OrderBy(p => p.Name) : query.OrderByDescending(p => p.Name); } } } // Skip if (this.QueryOptions.Skip != null) { query = query.Skip(this.QueryOptions.Skip.Value); } // Top if (this.QueryOptions.Top != null) { query = query.Take(this.QueryOptions.Top.Value); } // 結果返す return query.ToArray().AsQueryable(); } protected override Product GetEntityByKey(int key) { return Source.FirstOrDefault(p => p.Id == key); } } public class Product { public int Id { get; set; } public string Name { get; set; } } }
WebApiConfigには以下のようにODataサポートするようなルートを定義しておく。
var builder = new ODataConventionModelBuilder(); builder.EntitySet<Product>("Products"); var model = builder.GetEdmModel(); config.Routes.MapODataRoute("OData", "odata", model);
ODataのクエリを受け取って、自分でパラメータを好きに解釈してやれるってのは、結構自由度高いんじゃないんだろうかと思う今日この頃。でも更新系やリンクとか入ってくるとつらいのでシンプルなエンテティの読み取り以上のことをしようとすると…。