归志宁无五亩园,读书本意在元元。这篇文章主要讲述使用EntityCollection类型和Entity类型的输出参数实例相关的知识,希望能为你提供帮助。
我是微软Dynamics 365 &
Power Platform方面的工程师/顾问罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复453或者20210811可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!
当我们使用Customer API或者Action要输出集合的话怎么办?我尝试了一下EntityCollection类型的输出参数是个不错的选择。
关于Custom API的介绍请参考我的博文:Dynamics 365的Custom API介绍 ,通过Web API调用函数请参考我的博文:Dynamics CRM 2015/2016新特性之二十三:使用Web API执行函数 。
为了方便演示,我做个绑定类型的Custom API (用Action也是一样),根据一个Account,返回它所有的有效的Contacts,还返回Contact的数量。
【使用EntityCollection类型和Entity类型的输出参数实例】我新建的Custom API截图如下,我将Binding Type设置为了Entity, Bound Entity Logical Name设置为了account,Is Function设置为了Yes。
文章图片
为它定义了两个输出参数,第一个整数类型的输出参数没啥说的,如下截图所示:
文章图片
另外一个参数就是我们要讲的EntityCollection类型的参数,如下:
文章图片
我这个Custom API用到的服务器端代码如下:
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
namespace D365.Plugins
{
public class CustomAPIGetContactsByAccountId : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
tracingService.Trace($"Enter CustomAPIGetContactsByAccountId on {DateTime.UtcNow.ToString()}");
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService adminOrgSvc = serviceFactory.CreateOrganizationService(null);
string fetchXml = string.Format(@"<
fetch version=\'1.0\' mapping=\'logical\' distinct=\'false\'>
<
entity name=\'contact\'>
<
attribute name=\'fullname\' />
<
attribute name=\'telephone1\' />
<
attribute name=\'contactid\' />
<
order attribute=\'fullname\' descending=\'false\' />
<
filter type=\'and\'>
<
condition attribute=\'parentcustomerid\' operator=\'eq\' value=https://www.songbingjia.com/'{0}\' />
<
condition attribute=\'statecode\' operator=\'eq\' value=https://www.songbingjia.com/'0\' />
<
/filter>
<
/entity>
<
/fetch>
", context.PrimaryEntityId);
context.OutputParameters["ly_contacts"] = adminOrgSvc.RetrieveMultiple(new FetchExpression(fetchXml));
var contactEc = adminOrgSvc.RetrieveMultiple(new FetchExpression(fetchXml));
context.OutputParameters["ly_contacts"] = contactEc;
context.OutputParameters["ly_countofcontact"] = contactEc.Entities.Count;
}
}
}
我使用javascript通过Web API调用它的代码如下:
var clientUrl = Xrm.Utility.getGlobalContext().getClientUrl();
var req = new XMLHttpRequest()
req.open("GET", clientUrl + "/api/data/v9.2/accounts(7076d7bb-3aa3-eb11-b1ac-00224816920b)/Microsoft.Dynamics.CRM.ly_GetContactsByAccountId()", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json;
charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4) {
req.onreadystatechange = null;
if (this.status == 200) {
var responseJSON = JSON.parse(this.responseText);
console.log(responseJSON);
responseJSON.ly_contacts.forEach(element =>
console.log(element.fullname));
}
}
}
req.send();
返回的内容如下,可以看到返回的EntityCollection类型的输出参数的值是一个数组,包括了其中实体查询出来的元素值。
{
"@odata.context":"https://luoyongdemo.crm5.dynamics.com/api/data/v9.2/$metadata#Microsoft.Dynamics.CRM.ly_GetContactsByAccountIdResponse",
"ly_countofcontact":7,
"ly_contacts":[
{
"@odata.type":"#Microsoft.Dynamics.CRM.contact",
"@odata.etag":"W/\\"11141859\\"",
"fullname":"Nancy Anderson (sample)",
"telephone1":"555-0102",
"contactid":"ca76d7bb-3aa3-eb11-b1ac-00224816920b"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.contact",
"@odata.etag":"W/\\"11141864\\"",
"fullname":"Patrick Sands (sample)",
"telephone1":"555-0110",
"contactid":"da76d7bb-3aa3-eb11-b1ac-00224816920b"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.contact",
"@odata.etag":"W/\\"11141862\\"",
"fullname":"Paul Cannon (sample)",
"telephone1":"555-0107",
"contactid":"d476d7bb-3aa3-eb11-b1ac-00224816920b"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.contact",
"@odata.etag":"W/\\"11141863\\"",
"fullname":"Rene Valdes (sample)",
"telephone1":"555-0108",
"contactid":"d676d7bb-3aa3-eb11-b1ac-00224816920b"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.contact",
"@odata.etag":"W/\\"11141861\\"",
"fullname":"Scott Konersmann (sample)",
"telephone1":"555-0105",
"contactid":"d076d7bb-3aa3-eb11-b1ac-00224816920b"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.contact",
"@odata.etag":"W/\\"11141860\\"",
"fullname":"Sidney Higa (sample)",
"telephone1":"555-0104",
"contactid":"ce76d7bb-3aa3-eb11-b1ac-00224816920b"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.contact",
"@odata.etag":"W/\\"11141865\\"",
"fullname":"Susan Burk (sample)",
"telephone1":"555-0111",
"contactid":"dc76d7bb-3aa3-eb11-b1ac-00224816920b"
}
]
}
你可能会问,如果我要返回的多个实体组合的数据怎么办?比如Contact实体没有的字段怎么办?我的想法是返回的EntityCollection中的Entity的属性我自己定,这个属性不存在也可以,这个可以做到嘛?我尝试了一下,是可以的,我将代码改成如下即可,主要变化是EntityCollection中的Entity不要指定逻辑名称,直接用new Entity()这个没有输入参数的构造函数进行初始化即可。
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
namespace D365.Plugins
{
public class CustomAPIGetContactsByAccountId : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
EntityCollection returnVal = new EntityCollection();
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
tracingService.Trace($"Enter CustomAPIGetContactsByAccountId on {DateTime.UtcNow.ToString()}");
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService adminOrgSvc = serviceFactory.CreateOrganizationService(null);
string fetchXml = string.Format(@"<
fetch version=\'1.0\' mapping=\'logical\' distinct=\'false\'>
<
entity name=\'contact\'>
<
attribute name=\'fullname\' />
<
attribute name=\'telephone1\' />
<
attribute name=\'contactid\' />
<
order attribute=\'fullname\' descending=\'false\' />
<
filter type=\'and\'>
<
condition attribute=\'parentcustomerid\' operator=\'eq\' value=https://www.songbingjia.com/'{0}\' />
<
condition attribute=\'statecode\' operator=\'eq\' value=https://www.songbingjia.com/'0\' />
<
/filter>
<
/entity>
<
/fetch>
", context.PrimaryEntityId);
context.OutputParameters["ly_contacts"] = adminOrgSvc.RetrieveMultiple(new FetchExpression(fetchXml));
var contactEc = adminOrgSvc.RetrieveMultiple(new FetchExpression(fetchXml));
context.OutputParameters["ly_countofcontact"] = contactEc.Entities.Count;
Entity entity;
foreach (var item in contactEc.Entities)
{
//entity = new Entity("contact",item.Id);
//如果要自己定义属性,不要指定实体逻辑名称,用下面这行代码即可
entity = new Entity();
entity["fullname"] = item.GetAttributeValue<
string>
("fullname");
entity["telephone1"] = item.GetAttributeValue<
string>
("telephone1");
entity["notExistStringAttribute"] = DateTime.Now.ToString();
entity["notExistDateAttribute"] = DateTime.UtcNow;
returnVal.Entities.Add(entity);
}
context.OutputParameters["ly_contacts"] = returnVal;
}
}
}
返回的JSON如下,可以看到有自己定义的属性了:
{
"@odata.context":"https://luoweidemo.crm5.dynamics.com/api/data/v9.2/$metadata#Microsoft.Dynamics.CRM.ly_GetContactsByAccountIdResponse",
"ly_countofcontact":7,
"ly_contacts":[
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Nancy Anderson (sample)",
"telephone1":"555-0102",
"notExistStringAttribute":"8/11/2021 2:10:27 PM",
"notExistDateAttribute":"2021-08-11T14:10:27.8542352Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Patrick Sands (sample)",
"telephone1":"555-0110",
"notExistStringAttribute":"8/11/2021 2:10:27 PM",
"notExistDateAttribute":"2021-08-11T14:10:27.8542352Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Paul Cannon (sample)",
"telephone1":"555-0107",
"notExistStringAttribute":"8/11/2021 2:10:27 PM",
"notExistDateAttribute":"2021-08-11T14:10:27.8542352Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Rene Valdes (sample)",
"telephone1":"555-0108",
"notExistStringAttribute":"8/11/2021 2:10:27 PM",
"notExistDateAttribute":"2021-08-11T14:10:27.8542352Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Scott Konersmann (sample)",
"telephone1":"555-0105",
"notExistStringAttribute":"8/11/2021 2:10:27 PM",
"notExistDateAttribute":"2021-08-11T14:10:27.8542352Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Sidney Higa (sample)",
"telephone1":"555-0104",
"notExistStringAttribute":"8/11/2021 2:10:27 PM",
"notExistDateAttribute":"2021-08-11T14:10:27.8542352Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Susan Burk (sample)",
"telephone1":"555-0111",
"notExistStringAttribute":"8/11/2021 2:10:27 PM",
"notExistDateAttribute":"2021-08-11T14:10:27.8542352Z"
}
]
}
如果该Custom API只有一个EntityCollection类型的输出参数,它返回的JSON就会没有输出参数的名称,效果相当于输出参数的名称换成了value,示例如下:
{
"@odata.context":"https://luoweidemo.crm5.dynamics.com/api/data/v9.2/$metadata#expando",
"value":[
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Nancy Anderson (sample)",
"telephone1":"555-0102",
"notExistStringAttribute":"8/11/2021 2:47:26 PM",
"notExistDateAttribute":"2021-08-11T14:47:26.1280783Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Patrick Sands (sample)",
"telephone1":"555-0110",
"notExistStringAttribute":"8/11/2021 2:47:26 PM",
"notExistDateAttribute":"2021-08-11T14:47:26.1280783Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Paul Cannon (sample)",
"telephone1":"555-0107",
"notExistStringAttribute":"8/11/2021 2:47:26 PM",
"notExistDateAttribute":"2021-08-11T14:47:26.1280783Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Rene Valdes (sample)",
"telephone1":"555-0108",
"notExistStringAttribute":"8/11/2021 2:47:26 PM",
"notExistDateAttribute":"2021-08-11T14:47:26.1280783Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Scott Konersmann (sample)",
"telephone1":"555-0105",
"notExistStringAttribute":"8/11/2021 2:47:26 PM",
"notExistDateAttribute":"2021-08-11T14:47:26.1280783Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Sidney Higa (sample)",
"telephone1":"555-0104",
"notExistStringAttribute":"8/11/2021 2:47:26 PM",
"notExistDateAttribute":"2021-08-11T14:47:26.1280783Z"
},
{
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"fullname":"Susan Burk (sample)",
"telephone1":"555-0111",
"notExistStringAttribute":"8/11/2021 2:47:26 PM",
"notExistDateAttribute":"2021-08-11T14:47:26.1280783Z"
}
]
}
再来看看Entity类型的参数,我这里定义一个Entity类型的输出参数如下,且这个Custom Action只有这个输出参数:
文章图片
我使用的服务器端代码如下:
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Linq;
namespace D365.Plugins
{
public class CustomAPIGetTop1EntityByMainPhone : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService adminOrgSvc = serviceFactory.CreateOrganizationService(null);
string fetchXml = string.Format(@"<
fetch version=\'1.0\' mapping=\'logical\' distinct=\'false\' top=\'1\'>
<
entity name=\'account\'>
<
attribute name=\'name\' />
<
attribute name=\'accountid\' />
<
attribute name=\'primarycontactid\' />
<
filter type=\'and\'>
<
condition attribute=\'telephone1\' operator=\'eq\' value=https://www.songbingjia.com/'{0}\' />
<
/filter>
<
/entity>
<
/fetch>
", context.InputParameters["ly_mainphone"]);
var accountEc = adminOrgSvc.RetrieveMultiple(new FetchExpression(fetchXml));
Entity entity = new Entity();
if (accountEc.Entities.Any())
{
entity["name"] = accountEc.Entities[0].GetAttributeValue<
string>
("name");
entity["primarycontactid"] = accountEc.Entities[0].GetAttributeValue<
EntityReference>
("primarycontactid");
entity["notExistStringAttribute"] = DateTime.Now.ToString();
entity["notExistDateAttribute"] = DateTime.UtcNow;
}
context.OutputParameters["ly_entity"] = entity;
}
}
}
我是用的调用代码如下:
var clientUrl = Xrm.Utility.getGlobalContext().getClientUrl();
var req = new XMLHttpRequest()
req.open("GET", clientUrl + "/api/data/v9.2/ly_GetTop1EntityByMainPhone(ly_mainphone=@p1)?@p1=\'555-0158\'", true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json;
charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function () {
if (this.readyState == 4) {
req.onreadystatechange = null;
if (this.status == 200) {
var responseJSON = JSON.parse(this.responseText);
console.log(responseJSON);
}
}
}
req.send();
返回的内容如下,可以看到自定义的不存在的属性也是可以返回。如果只有Entity类型参数的话,Entity的属性就是一级元素了,这个输出参数的名称在返回的JSON中看不到。
{
"@odata.context":"https://luoweidemo.crm5.dynamics.com/api/data/v9.2/$metadata#expando/$entity",
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"name":"A. Datum\'&
+ Corporation (sample)",
"notExistStringAttribute":"8/11/2021 2:39:11 PM",
"notExistDateAttribute":"2021-08-11T14:39:11.8301173Z",
"primarycontactid":{
"@odata.type":"#Microsoft.Dynamics.CRM.contact",
"contact":"49a0e5b9-88df-e311-b8e5-6c3be5a8b200",
"__DisplayName__":"Adrian Dumitrascu"
}
}
你可能还会问,如果我要返回的Entity的某个元素需要是数组怎么办?比如说,就是子网格的记录的主属性拼凑的数组,可以用数组来做,类似服务器端如下:
entity["lstStrings"] = new string[] { "111","2222","33333" };
然后返回的效果类似如下,可以额外多出一个以@data.type结尾的元素,这里是 lstStrings@data.type这个元素。
{
"@odata.context":"https://luoweidemo.crm5.dynamics.com/api/data/v9.2/$metadata#expando/$entity",
"@odata.type":"#Microsoft.Dynamics.CRM.expando",
"name":"A. Datum\'&
+ Corporation (sample)",
"lstStrings@odata.type":"#Collection(String)",
"lstStrings":[
"111",
"2222",
"33333"
],
"notExistStringAttribute":"8/11/2021 3:11:58 PM",
"notExistDateAttribute":"2021-08-11T15:11:58.6726534Z",
"primarycontactid":{
"@odata.type":"#Microsoft.Dynamics.CRM.contact",
"contact":"49a0e5b9-88df-e311-b8e5-6c3be5a8b200",
"__DisplayName__":"Adrian Dumitrascu"
}
}
推荐阅读
- Dynamics 365中表的File数据类型列介绍
- 获取用户/团队对某条记录的权限,共享某条记录的某些权限给指定用户/团队的方法
- Dynamics CRM项目实例之十(CRM 2015的捆绑销售在订单中的效果)
- 基本命令学习 -查看文件内容的六种方法
- 介绍Command Checker及重新生成Ribbon元数据的方法
- Linux内核浅入浅出
- windows server 2012R2安装RD服务并发布remoteapp应用
- 审计 Linux 系统的操作行为的 5 种方案对比
- 基于 Ubuntu 21.04BPF 开发环境全攻略