Sitecore EntityService を作ってみる

samatsu 5/1/2017 2109 N/A Sitecore Programming

Sitecore Services Client (SSC)で提供される Webサービスとして、 ItemService と EntityService があります。今回は、 EntityServiceを作成して簡単に動作確認してみます。

今回使用した環境は次の通りです

  • Sitecore 8.2 Update3
  • Visual Studio 2015 Community

SSC で提供されるサービスは ItemService と EntityService です。ItemServiceはSitecoreのアイテムを利用するため、いきなりJavascriptやREST APIを使用して利用できますが、 EntityServiceは任意のビジネスオブジェクトをクライアントに提供できるようにするため、少しだけ準備が必要です。

今回はシンプルなEntityServiceを作成してみます。実際の細かい手順は、次のURLを参照して下さい。

Create an EntityService
https://doc.sitecore.net/sitecore_experience_platform/developing/developing_with_sitecore/sitecoreservicesclient/create_an_entityservice

1. 必要なDLLへの参照の追加

EntityServiceを作成するにあたり、必要なDLLをNuGetパッケージから追加します。

まず、Sitecoreの次のdllをプロジェクトの参照に追加してください。

  • Sitecore.Services.Core.dll
  • Sitecore.Services.Infrastructure.Sitecore.dll
  • Sitecore.Services.Infrastructure.dll

SitecoreがインストールされているWebsiteフォルダー配下のbinフォルダーの中の dll を使ってもいいですし、下図のようにSitecoreが提供しているNuGetのリポジトリからdllへの参照を追加してもどちらでも構いません。

ASP.NET Web API 用のNuGetパッケージへの参照がプロジェクトに追加されていない場合は、Web API用のNuGetパッケージの参照も追加してください。

2. サンプルEntityService の実装

必要なdllの参照が準備できたので、EntityServiceを作成してみます。製品情報を操作するAPIを提供する EntityServiceを作成してみます。作成手順は、冒頭で紹介した Sitecoreのドキュメントのサイトの説明に従います。

まずは ProductData モデル (ビジネスオブジェクト) を定義します。モデルクラスは、EntityIdentityを継承して定義します。モデルの定義を見てわかる通り、EntityServiceで公開するデータは必ずしも Item と関連する必要はありません。

namespace SitecoreSample.Areas.SSC.Models
{
    /// <summary>
    /// ビジネスオブジェクトの定義
    /// Sitecore.Services.Core.Model.EntityIdentity を継承して定義
    /// </summary>
    public class ProductData : EntityIdentity
    {
        public string ProductId { get; set; }
        public string ProductName { get; set; }
        public string Description { get; set; }
        public DateTime ReleaseDate { get; set; }
    }
}

次に、ProductData用のリポジトリを定義します。リポジトリは、 IRepository<T>インタフェースを実装します。

namespace SitecoreSample.Areas.SSC.Models
{
    public class ProductRepository : IRepository<ProductData>
    {
        IList<ProductData> _products = new List<ProductData>
        {
            new ProductData { Id = "ID1",  ProductId = "ID001", ProductName = "Chair", Description="Chair Description", ReleaseDate=DateTime.Now },
            new ProductData { Id = "ID2", ProductId = "ID002", ProductName = "Desk", Description="Desk Description", ReleaseDate=DateTime.Now },
            new ProductData { Id = "ID3", ProductId = "ID003", ProductName = "Light", Description="Light Description", ReleaseDate=DateTime.Now },
        };

        public void Add(ProductData entity)
        {
            if (!_products.Any(x => x.Id == entity.Id))
            {
                _products.Add(entity);
            }
        }

        public void Delete(ProductData entity)
        {
            var product = _products.FirstOrDefault(x => x.ProductId == entity.ProductId);
            if (product != null)
            {
                _products.Remove(product);
            }
        }

        public bool Exists(ProductData entity)
        {
            return _products.Any(x => x.ProductId == entity.ProductId);
        }

        public ProductData FindById(string id)
        {
            var product = _products.FirstOrDefault(x => x.Id == id);
            return product;
        }

        public IQueryable<ProductData> GetAll()
        {
            return _products.AsQueryable();
        }

        public void Update(ProductData entity)
        {
            var product = _products.FirstOrDefault(x => x.ProductId == entity.ProductId);
            if (product != null)
            {
                product.ProductName = entity.ProductName;
                product.Description = entity.Description;
                product.ReleaseDate = entity.ReleaseDate;
            }
        }
    }
}

あとは、コントローラーを作成します。今回は、 コントローラーは EntityService<T> を継承して実装します。ServiceController 属性をクラスに付与します。コントローラーの定義はとてもシンプルです。今回はせっかくなので CustomActionというカスタムアクションをおまけで定義しています。EntityServiceの標準の機能だけでよい場合はこのメソッドは必要はりません。最低限必要なのはコンストラクターを定義することだけです。

namespace SitecoreSample.Areas.SSC.Controllers
{
    [ServicesController]
    public class ProductServiceController : EntityService<ProductData>
    {
        public ProductServiceController(IRepository<ProductData> entityRepository) : base(entityRepository) { }

        public ProductServiceController() : this(new ProductRepository()) {  }

        /// <summary>
        /// カスタムアクション
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual ProductData CustomAction(string id)
        {
            var product = new ProductData() { Id = "IDCUSTOM", ProductId = "IDXXX", ProductName = "Custom Name", Description = "Custom Description" };
            // GetEntityUrlを使う場合は、Sitecore.Services.Infrastructure.Net.Http 名前空間の参照が必要
            product.Url = this.Request.GetEntityUrl(product);
            return product;
        }
    }
}

ビルドして配置してあげてください。

これで準備OKです。

3.動作確認

Postmanを使って、ローカルの環境から、REST形式でAPIを呼び出してみます。HTTPのメソッドを OPTIONSにして、リクエストします。作成したエンティティサービスのエンドポイントは、http://<sitecoreインスタンス>/sitecore/api/ssc/{名前空間}/{コントローラー} です。今回は、v82u3という名前でサイトをセットアップしたので、エンドポイントは次のようになります。名前空間のドット(.)はハイフン(-)に置き換わるので注意してください。

http://v82u3/Sitecore/api/ssc/SitecoreSample-Areas-SSC-Controllers/ProductService 

実行結果は下図の通りです。メタデータの情報を取得できました。

EntityServiceを作成した際のHTTPのメソッドに対応するEntityServiceのメソッドにマッピングは次のURLを参照してください。

Using the RESTful API for the EntityService
https://doc.sitecore.net/sitecore_experience_platform/developing/developing_with_sitecore/sitecoreservicesclient/use_the_restful_api_for_the_entityservice

FetchEntityメソッドを呼び出したい場合は、今回の環境では次のようなURLをGETでリクエストします。

http://v82u3/Sitecore/api/ssc/SitecoreSample-Areas-SSC-Controllers/ProductService/ID2/

FetchEntitiesメソッドを呼び出したい場合は、次のURLをGETでリクエストします。

http://v82u3/Sitecore/api/ssc/SitecoreSample-Areas-SSC-Controllers/ProductService/

サンプルで作成したカスタムアクションを呼び出したい場合は、 /controller/id/action というURLのパターンになりますので、例えば次のようなURLを作成して、POSTメソッドでリクエストします。

http://v82u3/Sitecore/api/ssc/SitecoreSample-Areas-SSC-Controllers/ProductService/ID2/CustomAction

簡単な動作確認のみ行いましたが、適切に動作していることがわかります。

JavascriptからEntityServiceを呼び出したい場合は、 docのサイトのUsing the EntityService from JavaScriptを参照してください。