カスタム API でオープン型を使用する

カスタム API を使用して Microsoft Dataverse メッセージを作成するには、リクエスト パラメータとレスポンス プロパティのそれぞれの名前とデータ型を指定する必要があります。 データ型はオープンまたはクローズにすることができます。 クローズド型では、すべてのプロパティと型の値が分かっています。 Dataverse で定義されているすべての型は閉じています。 システムは閉じた型を認識しており、それらを検証できます。 間違った名前を使用したり、値を間違った型に設定したりすると、エラーが発生します。 ただし、閉じた型は動的ではありません。 複雑にネストされたプロパティは許可されません。 通常、特定の構造は良いことですが、ビジネス ロジックではより柔軟なアプローチが必要な場合があります。

密閉型と違い、オープン型は動的プロパティを持つことができます。 次の場合には、カスタム API でオープン型を使用するのが合理的です。

  • 構造化された動的データ の使用が必要です。 このデータはクラスで記述することができないため、シリアル化または逆シリアル化する必要はありません。
  • カスタム API でリクエスト パラメーターを受け入れたり、利用可能なオプション を使い表現できない複合型を持つレスポンス プロパティを返したりします。 その場合、カスタム密閉型 を使用する必要があります。

オープン型を正しく使用するために、カスタム API に適用されるシナリオを理解することが重要です。 まず、オープン型の使用方法を理解しましょう。

オープン型の使用方法

オープン型を使用するには、オープン型用に構成されたメッセージが必要です。 カスタム API では、リクエスト パラメーターまたはレスポンス プロパティは TypeEntity (3) に、または EntityCollection (4) を LogicalEntityName で指定せずに設定することで開かれます。

LogicalEntityName を指定しない場合、Dataverse にエンティティはテーブル定義に対して検証できないキー/値のペアのコレクションであると示すので、試行されません。 LogicalEntityName を持たない EntityCollection は、単なる エンティティ の配列です。

注意

関数として定義されたカスタム API は、オープン型をリクエスト パラメータとして使用できませんが、レスポンス プロパティとして使用することはできます。

Dataverse エンティティの使用

実際にはオープン型ではありませんが、複数のクローズド エンティティ型を表すパラメーターまたはレスポンス プロパティを含むカスタム API を使用できることに注意してください。 たとえば、Customer または Account エンティティ インスタンスを想定する Contact パラメータを含むカスタム API を作成できます。 Dataverse では、どのような エンティティ タイプも可能です。 プラグイン コードは、Entity.LogicalName 値をチェックして、それが期待するタイプであるかどうかを判断する必要があります。

エンティティを辞書として使用する

より一般的なケースは、エンティティを辞書として使用することです。 Entity.Attributes コレクションを使用して、キーと値のセットを指定します。 値は任意の .NET 型にすることができ、ネストすることもできます。 他の エンティティ クラスのプロパティは使用しないでください。

アプリケーションが Microsoft Graph から送受信されるデータを使用し、educationSchool リソース型 を表すとします。 次の例のように、オープン型を使用することもできます。

SDK でオープン型を使用するには、エンティティ名を指定せずにエンティティ クラスを使用し、キーとその値を含む Entity.Attributes コレクションを設定します。

var educationSchool = new Entity() {
    Attributes =
    {
        { "id", Guid.NewGuid() },
        { "displayName","Redmond STEM Academy" },
        { "phone", "555-1234" },
        { "address",  new Entity() //physicalAddress resource type
            {
            Attributes =
                {
                    { "city","Redmond" },
                    { "countryOrRegion","United States" },
                    { "postalCode","98008" },
                    { "state","Washington" },
                    { "street","123 Maple St" },
                }
            }
        }
    }
};

Dataverse タイプを使用する

基本的な .NET の型に加え、Dataverse で知られている型も使用することができます。 .NET 用 SDK には、Dataverse が知る多くのクラスの定義が含まれ、Web API には、これらの型は Web API 複合型の参照列挙型の参照 にリストされています。

SDK を使用する場合は、値を設定するだけで済みます。

Web API を使用する場合は、Web API の名前空間を使用して型を指定する必要があります: Microsoft.Dynamics.CRM。 次の例では、これらの Dataverse Web API 型を使用します。

{
  "@odata.type": "Microsoft.Dynamics.CRM.expando",
  "label@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
   "label": {      
      "Label": "Yes",
      "LanguageCode": 1033
   },
  "labelarray": [
    {
      "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
      "Label": "test",
      "LanguageCode": 1033
    },
    {
      "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
      "Label": "prøve",
      "LanguageCode": 1030
    }
  ],
  "labelarray@odata.type": "Collection(Microsoft.Dynamics.CRM.LocalizedLabel)",
  "enumarray": ["DateOnly"],
  "enumarray@odata.type": "Collection(Microsoft.Dynamics.CRM.DateTimeFormat)"
}

構造化された動的データ

構造化された動的データは、JSON、XML、YAML、HTML などの文字列として設定できるさまざまな形式を使用して定義できます。 この種のデータは、文字列パラメーターまたは応答プロパティを使用して簡単に設定できます。 では、なぜオープン型を使用するのでしょうか?

  • 構造化データがカスタム API を介して別のサービスに渡される場合、またはカスタム API を呼び出す別のアプリケーションによって文字列として消費される場合は、文字列を使用します。
  • カスタム API をサポートするプラグイン、またはカスタム API を拡張するプラグインが構造化データを読み取りまたは変更する必要がある場合は、オープン型を使用します。

文字列の値を XDocumentJObject などのオブジェクトに解析して、プラグインで操作できるようにするのは、比較的高価な作業です。 プラグイン、またはカスタム API のロジックを拡張する可能性のあるその他のプラグインがデータを変更する場合、オブジェクトを文字列に変換し直す必要があります。 オープン型を使用すると、これらの負荷の高い操作を回避できます。

オープン型を使用すると、カスタム API の呼び出し元は、エンティティ クラスが提供する使い慣れた辞書構造を使用できます。 プラグインは、他の Dataverse レコードを操作するのと同じ方法でそのレコードを操作できます。

文字列データをクラスにシリアル化または逆シリアル化している場合、データは動的ではありません。 次のセクションを確認してください。

カスタムのクローズド型

オープン型では、動的で非構造化データが可能になります。 ただし、API に本当に動的パラメーターがあるかどうか、または実際にカスタム型が必要かどうかを考慮する必要があります。

現在、Dataverse を認識するカスタム タイプを定義することはできません。 ただし、オープン型を使用すると、Dataverse オープン型として処理できるクローズド型のクラスを定義できます。 カスタム API を使用する開発者は、クラスを使用してエラーの可能性を減らし、より良く更に生産的なエクスペリエンスを得ることができます。

たとえば、カスタム API に緯度と経度の座標の配列を使用してコースを追跡するパラメーターが必要だとします。 Location クラスが必要です。

エンティティ クラスを継承して、必要なプロパティを含む Location クラスを作成することができます。 例:

using Microsoft.Xrm.Sdk;

namespace MyCompany
{
    /// <summary>
    /// Specifies a location for use with my_CustomAPI
    /// </summary>
    public class Location : Entity
    {
        // Gets or sets the latitude of the Location.
        [AttributeLogicalName("Latitude")]
        public double Latitude
        {
            get
            {
                return GetAttributeValue<double>("Latitude");
            }
            set
            {
                SetAttributeValue("Latitude", value);
            }
        }

        // Gets or sets the longitude of the Location.
        [AttributeLogicalName("Longitude")]
        public double Longitude
        {
            get
            {
                return GetAttributeValue<double>("Longitude");
            }
            set
            {
                SetAttributeValue("Longitude", value);
            }
        }
    }
}

この型は Entity クラスを継承しているため、Entity GetAttributeValueSetAttributeValue メソッドを使用し、Attributes コレクション内の値にアクセスできます。 このクラスをプラグイン コードで使用し、ライブラリまたはドキュメントのサンプル コードでコンシューマと共有できます。 その結果、コードが使いやすく、読みやすくなります。

変更前:

var location = new Entity() { 
   Attributes =
   {
      { "Latitude", 47.66132951804776 },
      { "Longitude", -122.11446844957624},            
   }            
};

// OR 

var location = new Entity();
location["Latitude"] = 47.66132951804776;
location["Longitude"] = -122.11446844957624;

変更後:

var location = new Location { 
   Latitude = 47.66132951804776,
   Longitude = -122.11446844957624
};

// OR 

var location = new Location()
location.Latitude = 47.66132951804776;
location.Longitude = -122.11446844957624;

既知の問題

Web API で配列データを使用する際のエラー

Web API を使用して配列を含むデータを送信する場合、カスタム API にプラグインがあると次のエラーが発生します。

{
  "error": {
    "code": "0x80040224",
    "message": "Element 'http://schemas.datacontract.org/2004/07/System.Collections.Generic:value' contains 
     data from a type that maps to the name 'System.Collections.Generic:List`1'. The deserializer has no 
     knowledge of any type that maps to this name. Consider changing the implementation of the ResolveName 
     method on your DataContractResolver to return a non-null value for name 'List`1' and namespace 
     'System.Collections.Generic'.",
  }
}

このエラーは、クライアント アプリケーションが .NET 用 SDK を使用している場合、またはカスタム API にプラグインが設定されていない場合には、発生しません。

オープン型に関するご質問は、下部の このページ への フィードバッ ボタンからお寄せください。

参照

カスタム API の作成と使用
Odata.org 高度なチュートリアル: オープン型