カスタム API を使用して Microsoft Dataverse メッセージを作成する場合は、各要求パラメーターと応答プロパティの名前とデータ型を指定する必要があります。 データ型は、開いたり閉じたりすることができます。 閉じた型では、すべてのプロパティ名と型値が認識されます。 Dataverse で定義されているすべての型は閉じられます。 システムは閉じた型を認識し、それらを検証できます。 間違った名前を使用するか、値を間違った型に設定すると、エラーが発生します。 ただし、閉じた型は動的ではありません。 複雑な特性と入れ子になった特性は許可されていません。 通常、特定の構造は良いことですが、ビジネス ロジックでは、より柔軟なアプローチが必要な場合があります。
閉じた型とは異なり、 開いている型 は動的プロパティを持つことができます。 カスタム API でオープン型を使用することは、次の場合に理にかなっています。
- 構造化された動的データを使用する必要があります。 このデータはクラスで記述できないため、シリアル化または逆シリアル化する必要はありません。
- カスタム API で要求パラメーターを受け入れるか、 使用可能なオプションを使用して表現できない複合型を持つ応答プロパティを返す必要があります。 その場合は、 カスタムの閉じた型を使用する必要があります。
オープン型を正しく使用するには、カスタム API に適用されるシナリオを理解することが重要です。 最初にオープン型を使用する方法を理解しましょう。
開いている型を使用する方法
開いている型を使用するには、その型用に構成されたメッセージが必要です。 カスタム API では、Typeを Entity (3) または EntityCollection (4) に設定し、LogicalEntityName を指定せずに要求パラメーターまたは応答プロパティが開かれた状態になるように指定します。
LogicalEntityNameを指定しない場合、Dataverse に対して Entity はテーブル定義に対して検証できないキーと値のペアのコレクションであることを伝えています。そのため、Dataverse は検証を試みません。
のない LogicalEntityName は、Entity の配列にすぎません。
注
関数として定義されたカスタム API は、オープン型を要求パラメーターとして使用することはできませんが、応答プロパティとして使用できます。
Dataverse エンティティを使用する
実際にはオープン型ではありませんが、複数の閉じたエンティティ型を表すパラメーターまたは応答プロパティを持つカスタム API を使用できることに言及することをお勧めします。 たとえば、CustomerまたはAccountエンティティ インスタンスを想定するContact パラメーターを使用してカスタム API を作成できます。 Dataverse では 、任意の エンティティ型を使用できます。 プラグイン コードでは 、Entity.LogicalName 値を調べて、それが想定される型であるかどうかを判断する必要があります。
エンティティをディクショナリとして使用する
より一般的なケースは、 エンティティ をディクショナリとして使用することです。 Entity.Attributes コレクションを使用して、キーと値のセットを指定します。 値は任意の .NET 型にすることができ、入れ子にすることができます。 他の Entity クラス プロパティは使用しないでください。
たとえば、アプリケーションでは、Microsoft Graph から取得または Microsoft Graph に送信され、 educationSchool リソースの種類を表すデータが使用されるとします。 次の例のように、開いている型を使用できます。
SDK でオープン型を使用するには、エンティティ名を指定せずに Entity クラスを使用し、キーとその値を使用して 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 で知られている型を使用することもできます。 SDK for .NET には、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 を拡張するプラグインが構造化データの読み取りまたは変更を行う必要がある場合は、オープン型を使用します。
プラグインで操作できるように 、XDocument や JObject などのオブジェクトに文字列値を解析するのは、比較的コストのかかる操作です。 プラグイン、またはカスタム API のロジックを拡張する可能性があるその他のプラグインがデータを変更する場合は、オブジェクトを文字列に変換する必要があります。 オープン型を使用することで、このようなコストのかかる操作を回避できます。
オープン型では、カスタム API の呼び出し元は Entity クラスが提供する使い慣れたディクショナリ構造を使用できます。 プラグインは、他の 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 クラスから継承されるため、 EntityGetAttributeValue メソッドと SetAttributeValue メソッドを使用して、 Attributes コレクション内の値にアクセスできます。 このクラスは、プラグイン コードで使用し、ライブラリまたはドキュメントのサンプル コードのコンシューマーと共有できます。 その結果、使いやすく読みやすいコードが得られます。
Before:
var location = new Entity() {
Attributes =
{
{ "Latitude", 47.66132951804776 },
{ "Longitude", -122.11446844957624},
}
};
// OR
var location = new Entity();
location["Latitude"] = 47.66132951804776;
location["Longitude"] = -122.11446844957624;
After:
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'.",
}
}
このエラーは、クライアント アプリケーションが SDK for .NET を使用している場合や、カスタム API にプラグインが設定されていない場合には発生しません。
以下の [このページのフィードバック] ボタンを使用して、開いている種類に関する質問を送信します。