Dataverse Web API — práce s metadaty (Deep Research)
Zdroj: oficiální Microsoft Learn dokumentace pro Dynamics 365 / Microsoft Dataverse Web API v9.2. Cílem dokumentu je být referenční příručkou pro typický workflow: zjistit, zda něco existuje → stáhnout metadata → doplnit chybějící prvky → propagovat do solution → publikovat.
1. Základní koncepty
Dataverse Web API je RESTful endpoint, který kromě běžných datových operací umožňuje kompletní správu schématu (metadat) — tabulek (entit), sloupců (atributů), vztahů a globálních choices (optionsetů).
1.1 Endpoint pro metadata
Web API vystavuje čtyři hlavní entity sety pro práci se schématem:
| Entity Set Path | Obsah |
|---|---|
/api/data/v9.2/EntityDefinitions |
Kolekce EntityMetadata (tabulky) |
/api/data/v9.2/RelationshipDefinitions |
OneToManyRelationshipMetadata a ManyToManyRelationshipMetadata (oboje dědí z RelationshipMetadataBase) |
/api/data/v9.2/GlobalOptionSetDefinitions |
Globální choices — OptionSetMetadata a BooleanOptionSetMetadata |
/api/data/v9.2/ManagedPropertyDefinitions |
Pouze pro interní použití |
Sloupce (atributy) nejsou samostatný entity set — pracuje se s nimi přes navigation property Attributes v kontextu tabulky:
/api/data/v9.2/EntityDefinitions(LogicalName='account')/Attributes
1.2 Klíčové vlastnosti všech metadat
- Každý prvek metadat (tabulka, sloupec, vztah, optionset) má primární klíč
MetadataId(GUID), který dědí zMetadataBase. - Většina prvků má alternativní klíč — viz tabulka v sekci 2.1.
- Pro práci s konkrétními typy atributů (např.
PicklistAttributeMetadata,MoneyAttributeMetadata) musíte v URL použít cast expression:/Microsoft.Dynamics.CRM.<TypeName>.
1.3 CSDL $metadata dokument
Pro úplnou definici celého schématu prostředí použijte:
GET https://yourorg.api.crm.dynamics.com/api/data/v9.2/$metadata
S anotacemi (description, computed, permissions):
GET https://yourorg.api.crm.dynamics.com/api/data/v9.2/$metadata?annotations=true
Tento XML dokument je zdroj pravdy pro všechny EntityType, Action, Function, ComplexType a EnumType ve vašem prostředí. Názvy jsou case-sensitive.
1.4 HTTP metody pro schéma
| Operace | Metoda | Poznámka |
|---|---|---|
| Read | GET |
|
| Create | POST |
Endpoint vrací URI nového objektu v hlavičce OData-EntityId |
| Update | PUT (NE PATCH) |
Nahrazuje celou definici — musíte poslat všechny vlastnosti, které nechcete změnit |
| Delete | DELETE |
⚠️ Schémové entity nepodporují
PATCH. VždyPUTs kompletní definicí — to je zásadní rozdíl oproti business datům.
1.5 Důležité hlavičky
| Hlavička | Účel |
|---|---|
MSCRM.SolutionUniqueName |
Přidá vytvářený/aktualizovaný prvek do uvedené solution |
MSCRM.MergeLabels: true |
Při update zachová existující lokalizované labely v jazycích, které nepřepisujete |
Consistency: Strong |
Doporučeno pro čtení metadat |
OData-MaxVersion: 4.0, OData-Version: 4.0 |
Povinné |
2. Stažení metadat — různé typy dotazů
2.1 Retrieve podle alternativního klíče (nejrychlejší)
| Definiční prvek | Alternativní klíč | Příklad |
|---|---|---|
| Tabulka | LogicalName |
GET /api/data/v9.2/EntityDefinitions(LogicalName='account') |
| Sloupec | LogicalName |
GET /api/data/v9.2/EntityDefinitions(LogicalName='account')/Attributes(LogicalName='emailaddress1') |
| Vztah | SchemaName |
GET /api/data/v9.2/RelationshipDefinitions(SchemaName='Account_Tasks') |
| Global Choice | Name |
GET /api/data/v9.2/GlobalOptionSetDefinitions(Name='metric_goaltype') |
2.2 Retrieve podle MetadataId (primární klíč)
GET /api/data/v9.2/EntityDefinitions(70816501-edb9-4740-a16c-6a5efbc05d84)
GET /api/data/v9.2/EntityDefinitions(<EntityId>)/Attributes(<AttributeId>)
2.3 Selektivní stažení (vždy používejte $select)
EntityMetadata je velmi rozsáhlá entita — bez $select dostanete obrovský payload. Příklad:
GET /api/data/v9.2/EntityDefinitions(LogicalName='account')
?$select=DisplayName,IsKnowledgeManagementEnabled,EntitySetName
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0
MetadataId je vrácen vždy, bez ohledu na $select.
2.4 Expand atributů s castováním na konkrétní typ
Atributy obsahují polymorfní typy. Pokud potřebujete vlastnosti specifické pro daný typ (např. OptionSet u picklistu, Precision u money), musíte castovat:
GET /api/data/v9.2/EntityDefinitions(LogicalName='account')/Attributes/Microsoft.Dynamics.CRM.PicklistAttributeMetadata
?$select=LogicalName
&$expand=OptionSet,GlobalOptionSet
Filtrování atributů podle typu v expandu:
GET /api/data/v9.2/EntityDefinitions(LogicalName='account')
?$select=LogicalName
&$expand=Attributes($select=LogicalName;$filter=AttributeType eq Microsoft.Dynamics.CRM.AttributeTypeCode'Picklist')
2.5 Filtrování přes komplexní vlastnosti
RequiredLevel je komplexní typ — pro filtrování použijte tečkovou notaci a enum:
GET /api/data/v9.2/EntityDefinitions(LogicalName='account')/Attributes
?$select=SchemaName
&$filter=RequiredLevel/Value eq Microsoft.Dynamics.CRM.AttributeRequiredLevel'ApplicationRequired'
2.6 Získání optionset hodnot pro Picklist
GET /api/data/v9.2/EntityDefinitions(LogicalName='account')
/Attributes(LogicalName='accountcategorycode')
/Microsoft.Dynamics.CRM.PicklistAttributeMetadata
?$select=LogicalName
&$expand=OptionSet($select=Options),GlobalOptionSet($select=Options)
Pokud používá lokální optionset, GlobalOptionSet bude null, a naopak. Proto je dobré expandovat oba a vyhodnotit, který je naplněn.
2.7 Žádný paging
Pozor — dotazy na metadata nemají stránkování. Vrátí všechno najednou. Proto vždy filtrujte a selektujte.
2.8 Mass retrieve přes RetrieveMetadataChanges
Pro velký objem metadat nebo pro inkrementální synchronizaci existuje funkce RetrieveMetadataChanges. Vrací ServerVersionStamp, který lze v dalším volání předat jako ClientVersionStamp — server pak vrátí jen změny od minulého stažení (včetně DeletedMetadata).
3. Typický workflow — „Check & Create“
Toto je hlavní use case dotazu. Skládá se ze dvou rozhodovacích bodů: (A) existuje tabulka? a (B) existuje na ní daný atribut?.
3.1 Strategie pro „existuje?“ check
Existují dva přístupy:
Přístup 1 — HTTP status code
Pošlete GET s alternativním klíčem a očekávejte:
- 200 OK → existuje (a v body máte rovnou metadata)
- 404 Not Found → neexistuje
GET /api/data/v9.2/EntityDefinitions(LogicalName='new_bankaccount')?$select=MetadataId,LogicalName
Přístup 2 — filter query, kontrola počtu výsledků
GET /api/data/v9.2/EntityDefinitions
?$select=MetadataId,LogicalName
&$filter=LogicalName eq 'new_bankaccount'
Vrátí 200 OK vždy; v value je pole 0 nebo 1 prvek. Vhodné, pokud nechcete řešit výjimky.
3.2 Pseudokód celého workflow
1. GET EntityDefinitions(LogicalName='new_bankaccount')?$select=MetadataId
├─ 200 → tabulka existuje, máš MetadataId
└─ 404 → POST EntityDefinitions { ...full definition with primary name attribute... }
použij hlavičku MSCRM.SolutionUniqueName: <yourSolution>
2. GET EntityDefinitions(LogicalName='new_bankaccount')/Attributes(LogicalName='new_iban')?$select=MetadataId
├─ 200 → atribut existuje, případně PUT pro update
└─ 404 → POST EntityDefinitions(LogicalName='new_bankaccount')/Attributes
{ ...definition of new attribute with @odata.type... }
použij hlavičku MSCRM.SolutionUniqueName: <yourSolution>
3. POST PublishXml { "ParameterXml": "<importexportxml><entities><entity>new_bankaccount</entity></entities></importexportxml>" }
3.3 Klíčové pravidlo pro solution
Když na POST/PUT/DELETE pošlete hlavičku MSCRM.SolutionUniqueName: <unique_name>:
- Komponenta je vytvořena/aktualizována primárně v default solution,
- a zároveň je přidána do uvedené unmanaged solution.
Tím jednou request pokryjete oba kroky (create + addToSolution). To je doporučený způsob — bez nutnosti samostatného volání AddSolutionComponent.
4. Vytváření tabulky (EntityDefinitions)
4.1 Povinné vlastnosti
Tabulka musí mít definovaný primární name atribut v poli Attributes (přesně jeden StringAttributeMetadata s IsPrimaryName: true).
| EntityMetadata property | Hodnota |
|---|---|
SchemaName |
např. new_BankAccount — používejte prefix vašeho publishera |
DisplayName |
Label (lokalizovaný) |
DisplayCollectionName |
Plural label |
Description |
Popis (doporučeno) |
OwnershipType |
UserOwned nebo OrganizationOwned |
IsActivity |
true/false |
HasActivities |
true/false |
HasNotes |
true/false |
4.2 Plný příklad POST
POST [Organization URI]/api/data/v9.2/EntityDefinitions HTTP/1.1
MSCRM.SolutionUniqueName: examplesolution
Accept: application/json
Content-Type: application/json; charset=utf-8
OData-MaxVersion: 4.0
OData-Version: 4.0
{
"@odata.type": "Microsoft.Dynamics.CRM.EntityMetadata",
"SchemaName": "new_BankAccount",
"OwnershipType": "UserOwned",
"IsActivity": false,
"HasActivities": false,
"HasNotes": false,
"DisplayName": {
"@odata.type": "Microsoft.Dynamics.CRM.Label",
"LocalizedLabels": [
{
"@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
"Label": "Bank Account",
"LanguageCode": 1033
}
]
},
"DisplayCollectionName": {
"@odata.type": "Microsoft.Dynamics.CRM.Label",
"LocalizedLabels": [
{
"@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
"Label": "Bank Accounts",
"LanguageCode": 1033
}
]
},
"Description": {
"@odata.type": "Microsoft.Dynamics.CRM.Label",
"LocalizedLabels": [
{
"@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
"Label": "An entity to store information about customer bank accounts",
"LanguageCode": 1033
}
]
},
"Attributes": [
{
"@odata.type": "Microsoft.Dynamics.CRM.StringAttributeMetadata",
"AttributeType": "String",
"AttributeTypeName": { "Value": "StringType" },
"SchemaName": "new_AccountName",
"IsPrimaryName": true,
"FormatName": { "Value": "Text" },
"MaxLength": 100,
"RequiredLevel": {
"Value": "None",
"CanBeChanged": true,
"ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings"
},
"DisplayName": {
"@odata.type": "Microsoft.Dynamics.CRM.Label",
"LocalizedLabels": [
{
"@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
"Label": "Account Name",
"LanguageCode": 1033
}
]
},
"Description": {
"@odata.type": "Microsoft.Dynamics.CRM.Label",
"LocalizedLabels": [
{
"@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel",
"Label": "Type the name of the bank account",
"LanguageCode": 1033
}
]
}
}
]
}
Response:
HTTP/1.1 204 No Content
OData-Version: 4.0
OData-EntityId: [Organization URI]/api/data/v9.2/EntityDefinitions(00aa00aa-bb11-cc22-dd33-44ee44ee44ee)
4.3 Elastic table
Identické jako standardní tabulka, jen přidáte:
"TableType": "Elastic"
4.4 Update tabulky
PUT na EntityDefinitions(<id>) s kompletním JSON (viz oficiální docs — výstup obsahuje desítky vlastností typu IsAuditEnabled, IsCustomizable, Privileges[] atd.). Doporučený postup:
GETtabulku se všemi properties.- Modifikujte jen to, co chcete změnit.
- Pošlete
PUTs upraveným payloadem. - Přidejte hlavičku
MSCRM.MergeLabels: true, abyste si nepřepsali existující lokalizace v jiných jazycích.
5. Vytváření sloupců (Attributes)
5.1 Společný pattern
Endpoint:
POST /api/data/v9.2/EntityDefinitions(LogicalName='<entitylogicalname>')/Attributes
Každý sloupec musí mít:
- @odata.type — fully-qualified název typu (např. Microsoft.Dynamics.CRM.StringAttributeMetadata)
- AttributeType — enum hodnota (např. "String")
- AttributeTypeName.Value — string typ (např. "StringType") — JE ROZDÍL mezi AttributeType a AttributeTypeName
- SchemaName (s publisher prefixem)
- DisplayName, Description jako Label s LocalizedLabels
- RequiredLevel jako objekt s Value, CanBeChanged, ManagedPropertyLogicalName
5.2 Tabulka typů sloupců
| Typ sloupce | @odata.type |
AttributeType |
AttributeTypeName.Value |
Klíčové vlastnosti |
|---|---|---|---|---|
| String | StringAttributeMetadata |
String |
StringType |
FormatName (Text, Email, Url, Phone, TextArea, …), MaxLength |
| Memo (multi-line text) | MemoAttributeMetadata |
Memo |
MemoType |
Format (Text/TextArea/Email/Json/RichText), MaxLength, ImeMode |
| Integer (Whole Number) | IntegerAttributeMetadata |
Integer |
IntegerType |
MinValue, MaxValue, Format (None/Duration/TimeZone/Language) |
| BigInt | BigIntAttributeMetadata |
BigInt |
BigIntType |
|
| Decimal | DecimalAttributeMetadata |
Decimal |
DecimalType |
MinValue, MaxValue, Precision |
| Money | MoneyAttributeMetadata |
Money |
MoneyType |
PrecisionSource (0=fixed, 1=org default, 2=record's transaction currency) |
| DateTime | DateTimeAttributeMetadata |
DateTime |
DateTimeType |
Format (DateOnly/DateAndTime), DateTimeBehavior |
| Boolean | BooleanAttributeMetadata |
Boolean |
BooleanType |
OptionSet.TrueOption, OptionSet.FalseOption, DefaultValue |
| Picklist (Choice) — lokální | PicklistAttributeMetadata |
Picklist |
PicklistType |
OptionSet.Options[], OptionSet.IsGlobal: false |
| Picklist — globální | PicklistAttributeMetadata |
Picklist |
PicklistType |
GlobalOptionSet@odata.bind |
| MultiSelect Choice | MultiSelectPicklistAttributeMetadata |
Virtual |
MultiSelectPicklistType |
OptionSet.Options[] |
| Lookup (běžný) | LookupAttributeMetadata |
Lookup |
LookupType |
Vytváří se přes 1:N relationship, viz sekce 7 |
| Customer Lookup | ComplexLookupAttributeMetadata |
Lookup |
LookupType |
Speciální action CreateCustomerRelationships |
5.3 String sloupec
POST /api/data/v9.2/EntityDefinitions(LogicalName='sample_bankaccount')/Attributes
MSCRM.SolutionUniqueName: examplesolution
Content-Type: application/json; charset=utf-8
{
"@odata.type": "Microsoft.Dynamics.CRM.StringAttributeMetadata",
"AttributeType": "String",
"AttributeTypeName": { "Value": "StringType" },
"SchemaName": "new_BankName",
"FormatName": { "Value": "Text" },
"MaxLength": 100,
"RequiredLevel": {
"Value": "None",
"CanBeChanged": true,
"ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings"
},
"DisplayName": {
"@odata.type": "Microsoft.Dynamics.CRM.Label",
"LocalizedLabels": [
{ "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Bank Name", "LanguageCode": 1033 }
]
},
"Description": {
"@odata.type": "Microsoft.Dynamics.CRM.Label",
"LocalizedLabels": [
{ "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Type the name of the bank", "LanguageCode": 1033 }
]
}
}
5.4 Money sloupec
{
"@odata.type": "Microsoft.Dynamics.CRM.MoneyAttributeMetadata",
"AttributeType": "Money",
"AttributeTypeName": { "Value": "MoneyType" },
"SchemaName": "new_Balance",
"PrecisionSource": 2,
"RequiredLevel": { "Value": "None", "CanBeChanged": true, "ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings" },
"DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Balance", "LanguageCode": 1033 } ] },
"Description": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Enter the balance amount", "LanguageCode": 1033 } ] }
}
PrecisionSource: 2 znamená, že precision se odvozuje z transakční měny záznamu.
5.5 DateTime sloupec
{
"@odata.type": "Microsoft.Dynamics.CRM.DateTimeAttributeMetadata",
"AttributeType": "DateTime",
"AttributeTypeName": { "Value": "DateTimeType" },
"SchemaName": "new_Checkeddate",
"Format": "DateOnly",
"RequiredLevel": { "Value": "None", "CanBeChanged": true, "ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings" },
"DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Date", "LanguageCode": 1033 } ] }
}
5.6 Boolean sloupec
{
"@odata.type": "Microsoft.Dynamics.CRM.BooleanAttributeMetadata",
"AttributeType": "Boolean",
"AttributeTypeName": { "Value": "BooleanType" },
"SchemaName": "new_Boolean",
"DefaultValue": false,
"OptionSet": {
"OptionSetType": "Boolean",
"TrueOption": {
"Value": 1,
"Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "True", "LanguageCode": 1033 } ] }
},
"FalseOption": {
"Value": 0,
"Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "False", "LanguageCode": 1033 } ] }
}
},
"RequiredLevel": { "Value": "None", "CanBeChanged": false, "ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings" },
"DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Sample Boolean", "LanguageCode": 1033 } ] }
}
5.7 Picklist — lokální optionset
{
"@odata.type": "Microsoft.Dynamics.CRM.PicklistAttributeMetadata",
"AttributeType": "Picklist",
"AttributeTypeName": { "Value": "PicklistType" },
"SchemaName": "sample_Choice",
"OptionSet": {
"@odata.type": "Microsoft.Dynamics.CRM.OptionSetMetadata",
"IsGlobal": false,
"OptionSetType": "Picklist",
"Options": [
{
"Value": 727000000,
"Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Bravo", "LanguageCode": 1033 } ] }
},
{
"Value": 727000001,
"Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Delta", "LanguageCode": 1033 } ] }
}
]
},
"RequiredLevel": { "Value": "None", "CanBeChanged": false, "ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings" },
"DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Sample Choice", "LanguageCode": 1033 } ] }
}
Doporučení: pokud necháte
Valuejakonull, systém doplní hodnotu s prefixem definovaným publisherem (customizationoptionvalueprefix). To je výhodné pro správu duplicit napříč prostředími.
5.8 Multi-select picklist
Téměř identický s Picklist, ale @odata.type je MultiSelectPicklistAttributeMetadata, AttributeType je Virtual a AttributeTypeName.Value je MultiSelectPicklistType.
5.9 Customer Lookup (speciální action)
Customer lookup není standardní lookup — má relace na account i contact současně. Vytváří se přes CreateCustomerRelationships Action:
POST /api/data/v9.2/CreateCustomerRelationships HTTP/1.1
MSCRM.SolutionUniqueName: examplesolution
{
"OneToManyRelationships": [
{ "SchemaName": "new_bankaccount_customer_account", "ReferencedEntity": "account", "ReferencingEntity": "new_bankaccount" },
{ "SchemaName": "new_bankaccount_customer_contact", "ReferencedEntity": "contact", "ReferencingEntity": "new_bankaccount" }
],
"Lookup": {
"@odata.type": "Microsoft.Dynamics.CRM.ComplexLookupAttributeMetadata",
"AttributeType": "Lookup",
"AttributeTypeName": { "Value": "LookupType" },
"SchemaName": "new_CustomerId",
"DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Customer", "LanguageCode": 1033 } ] },
"Description": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Sample Customer Lookup Attribute", "LanguageCode": 1033 } ] }
}
}
Response obsahuje RelationshipIds (pole se dvěma GUID) a AttributeId.
5.10 Update sloupce
Stejný princip jako u tabulky — vytáhněte plnou definici typu, modifikujte, pošlete PUT:
PUT /api/data/v9.2/EntityDefinitions(LogicalName='new_bankaccount')/Attributes(LogicalName='new_boolean') HTTP/1.1
MSCRM.SolutionUniqueName: examplesolution
MSCRM.MergeLabels: true
Content-Type: application/json; charset=utf-8
{ ...kompletní BooleanAttributeMetadata s upravenými hodnotami... }
⚠️ Pro úpravu options v Picklistu/Boolean se
PUTnepoužívá — existují samostatné akce:InsertOptionValue,UpdateOptionValue,DeleteOptionValue,OrderOption,InsertStatusValue,UpdateStateValue.
6. Globální choices (GlobalOptionSetDefinitions)
6.1 Vytvoření globálního optionsetu
POST /api/data/v9.2/GlobalOptionSetDefinitions HTTP/1.1
MSCRM.SolutionUniqueName: examplesolution
{
"@odata.type": "Microsoft.Dynamics.CRM.OptionSetMetadata",
"Name": "sample_colors",
"OptionSetType": "Picklist",
"IsGlobal": true,
"DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Colors", "LanguageCode": 1033 } ] },
"Description": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Color Choice", "LanguageCode": 1033 } ] },
"Options": [
{ "Value": 727000000, "Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Red", "LanguageCode": 1033 } ] } },
{ "Value": 727000001, "Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Yellow", "LanguageCode": 1033 } ] } },
{ "Value": 727000002, "Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Green", "LanguageCode": 1033 } ] } }
]
}
6.2 Vytvoření Picklist sloupce navázaného na globální optionset
{
"@odata.type": "Microsoft.Dynamics.CRM.PicklistAttributeMetadata",
"AttributeType": "Picklist",
"AttributeTypeName": { "Value": "PicklistType" },
"SchemaName": "sample_Colors",
"GlobalOptionSet@odata.bind": "/GlobalOptionSetDefinitions(Name='sample_colors')",
"RequiredLevel": { "Value": "None", "CanBeChanged": false, "ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings" },
"DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Sample Colors", "LanguageCode": 1033 } ] }
}
@odata.bind může používat alternativní klíč Name nebo MetadataId.
6.3 Operace nad options
| Akce | Účel | URL |
|---|---|---|
InsertOptionValue |
Přidat option do optionsetu | POST /api/data/v9.2/InsertOptionValue |
UpdateOptionValue |
Změnit label/popis option | POST /api/data/v9.2/UpdateOptionValue |
DeleteOptionValue |
Odstranit option | POST /api/data/v9.2/DeleteOptionValue |
OrderOption |
Změnit pořadí options | POST /api/data/v9.2/OrderOption |
InsertStatusValue |
Přidat status do statecode sloupce | POST /api/data/v9.2/InsertStatusValue |
UpdateStateValue |
Update statecode option | POST /api/data/v9.2/UpdateStateValue |
Všechny akce přijímají parametr SolutionUniqueName v body — díky tomu se změny propagují do uvedené solution.
Příklad DeleteOptionValue (rozlišení globální vs. lokální):
- Globální: použijte parametr OptionSetName
- Lokální (na sloupci): použijte parametry EntityLogicalName a AttributeLogicalName
6.4 Update samotného optionsetu
PUT /api/data/v9.2/GlobalOptionSetDefinitions(<id>) s OptionSetMetadataBase — ale pouze meta vlastnosti (DisplayName, Description). Options se mění výhradně přes akce výše.
7. Vztahy (RelationshipDefinitions)
7.1 Kontrola eligibility (před vytvořením)
| Action / Function | Co dělá |
|---|---|
CanBeReferenced |
Může být primární (1) v 1:N relaci? |
CanBeReferencing |
Může být referencing (N) v 1:N relaci? |
CanManyToMany |
Může se účastnit N:N? |
GetValidReferencedEntities |
Které entity může referencovat? |
GetValidReferencingEntities |
Které entity ji mohou referencovat? |
GetValidManyToMany |
Které entity podporují N:N? |
Příklad:
GET /api/data/v9.2/GetValidReferencingEntities(ReferencedEntityName='sample_bankaccount')
POST /api/data/v9.2/CanManyToMany
{ "EntityName": "contact" }
7.2 Vytvoření 1:N relace (zároveň vytvoří lookup column)
POST /api/data/v9.2/RelationshipDefinitions HTTP/1.1
MSCRM.SolutionUniqueName: examplesolution
Content-Type: application/json; charset=utf-8
{
"@odata.type": "Microsoft.Dynamics.CRM.OneToManyRelationshipMetadata",
"SchemaName": "new_contact_new_bankaccount",
"ReferencedEntity": "contact",
"ReferencingEntity": "new_bankaccount",
"ReferencedAttribute": "contactid",
"AssociatedMenuConfiguration": {
"Behavior": "UseCollectionName",
"Group": "Details",
"Order": 10000,
"Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Bank Accounts", "LanguageCode": 1033 } ] }
},
"CascadeConfiguration": {
"Assign": "Cascade", "Delete": "Cascade", "Merge": "Cascade",
"Reparent": "Cascade", "Share": "Cascade", "Unshare": "Cascade"
},
"Lookup": {
"@odata.type": "Microsoft.Dynamics.CRM.LookupAttributeMetadata",
"AttributeType": "Lookup",
"AttributeTypeName": { "Value": "LookupType" },
"SchemaName": "new_AccountOwner",
"RequiredLevel": { "Value": "ApplicationRequired", "CanBeChanged": true, "ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings" },
"DisplayName": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Account Owner", "LanguageCode": 1033 } ] },
"Description": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "The owner of the account", "LanguageCode": 1033 } ] }
}
}
Toto je deep insert — lookup column je definovaný uvnitř relace a oba vznikají v jedné operaci.
7.3 Vytvoření N:N relace
POST /api/data/v9.2/RelationshipDefinitions HTTP/1.1
MSCRM.SolutionUniqueName: examplesolution
{
"@odata.type": "Microsoft.Dynamics.CRM.ManyToManyRelationshipMetadata",
"SchemaName": "new_accounts_campaigns",
"Entity1LogicalName": "account",
"Entity2LogicalName": "campaign",
"IntersectEntityName": "new_accounts_campaigns",
"Entity1AssociatedMenuConfiguration": { "Behavior": "UseLabel", "Group": "Details", "Order": 10000, "Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Account", "LanguageCode": 1033 } ] } },
"Entity2AssociatedMenuConfiguration": { "Behavior": "UseLabel", "Group": "Details", "Order": 10000, "Label": { "@odata.type": "Microsoft.Dynamics.CRM.Label", "LocalizedLabels": [ { "@odata.type": "Microsoft.Dynamics.CRM.LocalizedLabel", "Label": "Campaign", "LanguageCode": 1033 } ] } }
}
7.4 Retrieve relace s castem
GET /api/data/v9.2/RelationshipDefinitions(<id>)/Microsoft.Dynamics.CRM.OneToManyRelationshipMetadata
GET /api/data/v9.2/RelationshipDefinitions(<id>)/Microsoft.Dynamics.CRM.ManyToManyRelationshipMetadata
GET /api/data/v9.2/RelationshipDefinitions(SchemaName='Account_Tasks')/Microsoft.Dynamics.CRM.OneToManyRelationshipMetadata
Bez castu dostanete jen společné properties z RelationshipMetadataBase.
7.5 Update / Delete relace
- Update:
PUTnaRelationshipDefinitions(<id>)s kompletní definicí - Delete:
DELETE /api/data/v9.2/RelationshipDefinitions(<id>)
8. Propagace do solution
8.1 Doporučená cesta — MSCRM.SolutionUniqueName hlavička
Pokaždé, když děláte POST (create) nebo PUT (update) na schema endpoint a chcete prvek umístit do konkrétní solution, přidejte:
MSCRM.SolutionUniqueName: yoursolutionuniquename
Funguje pro:
- EntityDefinitions (POST/PUT/DELETE)
- EntityDefinitions(...)/Attributes (POST/PUT/DELETE)
- RelationshipDefinitions (POST/PUT/DELETE)
- GlobalOptionSetDefinitions (POST/PUT/DELETE)
- Akce pro options: InsertOptionValue, UpdateOptionValue, DeleteOptionValue, OrderOption, InsertStatusValue (předává se jako parametr SolutionUniqueName v body, ne jako hlavička)
- CreateCustomerRelationships
8.2 Alternativa — AddSolutionComponent action
Pokud už komponenta existuje (např. system entity account) a potřebujete ji jen přidat do solution, použijte action AddSolutionComponent:
POST /api/data/v9.2/AddSolutionComponent HTTP/1.1
Content-Type: application/json; charset=utf-8
{
"ComponentId": "70816501-edb9-4740-a16c-6a5efbc05d84",
"ComponentType": 1,
"SolutionUniqueName": "yoursolutionuniquename",
"AddRequiredComponents": false,
"DoNotIncludeSubcomponents": false
}
Klíčové ComponentType hodnoty (z globální choice componenttype):
| Value | Component |
|---|---|
| 1 | Entity (tabulka) |
| 2 | Attribute (sloupec) |
| 9 | OptionSet |
| 10 | EntityRelationship |
| 60 | SystemForm |
| 61 | WebResource |
| 300 | Canvas App |
| 380 | Environment Variable Definition |
| 381 | Environment Variable Value |
⚠️
AddSolutionComponentpoužijte jen tehdy, když znáte správnýComponentType. U novějších komponent (které ještě nejsou vcomponenttypechoice) preferujteMSCRM.SolutionUniqueNamehlavičku.
8.3 Vytvoření samotné solution přes Web API
Solution je standardní business entita. Vytvoříte přes POST /api/data/v9.2/solutions se vztahem na publishera:
POST /api/data/v9.2/solutions HTTP/1.1
Content-Type: application/json; charset=utf-8
{
"uniquename": "examplesolution",
"friendlyname": "Example Solution",
"version": "1.0.0.0",
"publisherid@odata.bind": "/publishers(<publisherId GUID>)"
}
Publisher musí existovat předem — POST /api/data/v9.2/publishers s uniquename, friendlyname a customizationprefix.
8.4 Co se stane s default solution
Když přidáte komponentu pomocí MSCRM.SolutionUniqueName, dojde k tomu, že:
1. Komponenta vznikne v default (active) solution — to platí vždy.
2. Zároveň je přidána i do vaší explicitní unmanaged solution.
Pokud hlavičku vynecháte, komponenta skončí jen v default solution a musíte ji následně přidat pomocí AddSolutionComponent.
9. Publikování změn
Bez publikování se některé změny schématu neprojeví v UI ani se neexportují se solution. Publikování je nutné po každém update (vytváření nových komponent ho vyžaduje méně často, protože nové komponenty se publikují automaticky).
9.1 PublishAllXml — publikuje vše
POST /api/data/v9.2/PublishAllXml HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
Accept: application/json
Bez body. Vrací 204 No Content. Pozor — v produkci to může na chvíli zatížit prostředí.
9.2 PublishXml — selektivní
POST /api/data/v9.2/PublishXml HTTP/1.1
Content-Type: application/json; charset=utf-8
{
"ParameterXml": "<importexportxml><entities><entity>new_bankaccount</entity><entity>account</entity></entities></importexportxml>"
}
ParameterXml musí splňovat Publish Request Schema. Dovolené sekce uvnitř <importexportxml>:
- <entities> — seznam tabulek (<entity>logicalname</entity>)
- <ribbons> — <ribbon></ribbon> (publikuje application ribbon)
- <entitymaps/>, <entityrelationships>, <optionsets>, <dashboards>, <webresources>, <sitemaps>
Příklad pro více typů komponent:
<importexportxml>
<entities>
<entity>new_bankaccount</entity>
</entities>
<optionsets>
<optionset>sample_colors</optionset>
</optionsets>
<webresources>
<webresource>{a7d261bc-3580-e611-80d7-00155d2a68de}</webresource>
</webresources>
</importexportxml>
9.3 Kdy publikovat
| Akce | Auto-publish | Nutné publish |
|---|---|---|
| Vytvoření nové tabulky/sloupce | Ano | Ne |
| Smazání komponenty | Ano | Ne |
| Update tabulky/sloupce | Ne | Ano |
| Update labelů, optionsetů | Ne | Ano |
Změna IsAuditEnabled, RequiredLevel apod. |
Ne | Ano |
| Před exportem solution | — | Ano vždy |
10. Kompletní příklad workflow
Scénář: Skript, který v solution MyExtensions zajistí existenci tabulky new_bankaccount se sloupcem new_iban (string, max 34) a sloupcem new_balance (money).
# 1) Existuje tabulka?
GET /api/data/v9.2/EntityDefinitions(LogicalName='new_bankaccount')?$select=MetadataId,LogicalName
└─ 404 → vytvořit:
POST /api/data/v9.2/EntityDefinitions
Headers:
MSCRM.SolutionUniqueName: MyExtensions
Body: viz sekce 4.2 (BankAccount s primárním atributem new_AccountName)
└─ 200 → pokračovat, máme MetadataId
# 2) Existuje sloupec new_iban?
GET /api/data/v9.2/EntityDefinitions(LogicalName='new_bankaccount')
/Attributes(LogicalName='new_iban')?$select=MetadataId
└─ 404 → vytvořit:
POST /api/data/v9.2/EntityDefinitions(LogicalName='new_bankaccount')/Attributes
Headers:
MSCRM.SolutionUniqueName: MyExtensions
Body:
{
"@odata.type": "Microsoft.Dynamics.CRM.StringAttributeMetadata",
"AttributeType": "String",
"AttributeTypeName": { "Value": "StringType" },
"SchemaName": "new_IBAN",
"FormatName": { "Value": "Text" },
"MaxLength": 34,
"RequiredLevel": { "Value": "Recommended", "CanBeChanged": true, "ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings" },
"DisplayName": { "@odata.type":"Microsoft.Dynamics.CRM.Label","LocalizedLabels":[{"@odata.type":"Microsoft.Dynamics.CRM.LocalizedLabel","Label":"IBAN","LanguageCode":1033}] },
"Description": { "@odata.type":"Microsoft.Dynamics.CRM.Label","LocalizedLabels":[{"@odata.type":"Microsoft.Dynamics.CRM.LocalizedLabel","Label":"Bank account international number","LanguageCode":1033}] }
}
# 3) Existuje sloupec new_balance?
GET /api/data/v9.2/EntityDefinitions(LogicalName='new_bankaccount')
/Attributes(LogicalName='new_balance')?$select=MetadataId
└─ 404 → vytvořit:
POST /api/data/v9.2/EntityDefinitions(LogicalName='new_bankaccount')/Attributes
Headers:
MSCRM.SolutionUniqueName: MyExtensions
Body:
{
"@odata.type": "Microsoft.Dynamics.CRM.MoneyAttributeMetadata",
"AttributeType": "Money",
"AttributeTypeName": { "Value": "MoneyType" },
"SchemaName": "new_Balance",
"PrecisionSource": 2,
"RequiredLevel": { "Value": "None", "CanBeChanged": true, "ManagedPropertyLogicalName": "canmodifyrequirementlevelsettings" },
"DisplayName": { "@odata.type":"Microsoft.Dynamics.CRM.Label","LocalizedLabels":[{"@odata.type":"Microsoft.Dynamics.CRM.LocalizedLabel","Label":"Balance","LanguageCode":1033}] }
}
# 4) Publikovat změny
POST /api/data/v9.2/PublishXml
{
"ParameterXml": "<importexportxml><entities><entity>new_bankaccount</entity></entities></importexportxml>"
}
Pseudokód v C# (HttpClient styl)
async Task EnsureAttributeAsync(HttpClient http, string solution, string entityLogicalName, string attrLogicalName, object attributeDefinition)
{
var getResp = await http.GetAsync(
$"api/data/v9.2/EntityDefinitions(LogicalName='{entityLogicalName}')" +
$"/Attributes(LogicalName='{attrLogicalName}')?$select=MetadataId");
if (getResp.StatusCode == HttpStatusCode.OK)
return; // attribute exists
if (getResp.StatusCode != HttpStatusCode.NotFound)
getResp.EnsureSuccessStatusCode();
var req = new HttpRequestMessage(HttpMethod.Post,
$"api/data/v9.2/EntityDefinitions(LogicalName='{entityLogicalName}')/Attributes")
{
Content = JsonContent.Create(attributeDefinition)
};
req.Headers.Add("MSCRM.SolutionUniqueName", solution);
req.Headers.Add("OData-MaxVersion", "4.0");
req.Headers.Add("OData-Version", "4.0");
var postResp = await http.SendAsync(req);
postResp.EnsureSuccessStatusCode();
}
11. Best practices a úskalí
- Vždy používejte
$selectpři čtení metadat —EntityMetadatamá desítky vlastností. - Cast expressions jsou case-sensitive a používají fully-qualified namespace
Microsoft.Dynamics.CRM.<TypeName>. - Update = PUT s celou definicí, ne PATCH. Vždy nejprve GET, modify, PUT.
- Při update labelů používejte
MSCRM.MergeLabels: true, jinak smažete lokalizace v jiných jazycích. - Hlavička
MSCRM.SolutionUniqueNamemá přednost předAddSolutionComponent— preferujte ji. - Vždy publikujte po update (vytvoření obvykle ne, update vždy).
- Před exportem solution publikujte všechno —
PublishAllXml. - U
Optionsv Picklistu nechteValue: null, ať systém přiřadí prefix publishera — zabráníte kolizím při merge solution. - Pro retrieve metadat preferujte
Consistency: Stronghlavičku. - Atributy nelze dotazovat samostatně — vždy v kontextu tabulky.
- Žádné stránkování u metadat — používejte filter + select.
- Pro velký objem nebo cache schématu používejte
RetrieveMetadataChangessClientVersionStamp. - Eligibility check před vytvořením relace — ne všechny entity podporují všechny typy relací.
AttributeTypevs.AttributeTypeName— obojí musíte poslat, jinak request selže s nečitelnou chybou.- DisplayName / Description / Label vždy musí mít
@odata.type"Microsoft.Dynamics.CRM.Label" a uvnitřLocalizedLabelsLanguageCode.
12. Reference
Oficiální dokumentace: - Use the Web API with table definitions — přehled - Query Table Definitions Using the Web API — čtení metadat - Retrieve table definitions by name or MetadataId — retrieve podle klíče - Create and update table definitions using the Web API — tabulky - Create and update column definitions using the Web API — sloupce - Create and update choices (option sets) using the Web API — globální choices - Create and update table relationships using the Web API — vztahy - Use optional parameters — Associate a solution component with a solution - Publish customizations - Web API table schema operations sample — end-to-end sample - Web API table schema operations sample (PowerShell) - Web API service documents (CSDL $metadata)
Reference entity types (kompletní property listy):
- EntityMetadata EntityType
- AttributeMetadata EntityType (a všechny derived: StringAttributeMetadata, IntegerAttributeMetadata, DecimalAttributeMetadata, MoneyAttributeMetadata, MemoAttributeMetadata, DateTimeAttributeMetadata, BooleanAttributeMetadata, PicklistAttributeMetadata, MultiSelectPicklistAttributeMetadata, LookupAttributeMetadata, BigIntAttributeMetadata, ImageAttributeMetadata, FileAttributeMetadata, atd.)
- OneToManyRelationshipMetadata / ManyToManyRelationshipMetadata
- OptionSetMetadata / BooleanOptionSetMetadata
- PublishXml Action / PublishAllXml Action
- AddSolutionComponent Action
- CreateCustomerRelationships Action
- RetrieveMetadataChanges Function