- 创建一个action process,如下图,分别有两个inputparameter 和一个outputparameter
2.使用visual studio 2019编写一个plugin dll, 功能是根据电话,邮件,会员编号为查找条件查Contact表,然后更新某一个实体的记录,代码如下
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Linq;
namespace APM_ProContact_Plugin
{
public class ProContact_Process : IPlugin
{
#region Secure/Unsecure Configuration Setup
private string _secureConfig = null;
private string _unsecureConfig = null;
public ProContact_Process(string unsecureConfig, string secureConfig)
{
_secureConfig = secureConfig;
_unsecureConfig = unsecureConfig;
}
#endregion
public void Execute(IServiceProvider serviceProvider)
{
ITracingService tracer = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
try
{
// Entity entity = (Entity)context.InputParameters["Target"];
var Create_Num = 0;
string inputOne = context.InputParameters["InputOne"].ToString();
string inputTwo = context.InputParameters["InputTwo"].ToString();
string OutIdList = string.Empty;
var ProContactQuery = new QueryExpression("apm_procontact");
ProContactQuery.ColumnSet = new ColumnSet(true);
ProContactQuery.Criteria.AddCondition("apm_processed", ConditionOperator.NotEqual, true);
var queryEntity = service.RetrieveMultiple(ProContactQuery);
if (queryEntity.Entities.Count > 0)
{
foreach (Entity item in queryEntity.Entities)
{
var contactQuery = new QueryExpression("contact");
contactQuery.ColumnSet = new ColumnSet(true);
string phone = string.Empty;
string email = string.Empty;
string contact_no = string.Empty;
if(item.Attributes.Contains("_phone"))
{
phone = item.Attributes["_phone"].ToString();
contactQuery.Criteria.AddCondition("mobilephone", ConditionOperator.Equal, phone);
}
else if (item.Attributes.Contains("_email"))
{
email = item.Attributes["_email"].ToString();
contactQuery.Criteria.AddCondition("emailaddress1", ConditionOperator.Equal, email);
}
else if (item.Attributes.Contains("_contact_no"))
{
contact_no = item.Attributes["_contact_no"].ToString();
contactQuery.Criteria.AddCondition("thk_contact_no", ConditionOperator.Equal, contact_no);
}
else
{
continue;
}
var ContactEntity = service.RetrieveMultiple(contactQuery);
if (ContactEntity.Entities.Count > 0)
{
Entity selectEn = ContactEntity.Entities.FirstOrDefault();
if (selectEn.Attributes.Count > 0)
{
Entity updateEntity = service.Retrieve("_procontact", item.Id, new ColumnSet());
if (selectEn.Attributes.Contains("thk_howdoyouknowus"))
{
updateEntity.Attributes["_howdoyouknowus"] = selectEn.FormattedValues["thk_howdoyouknowus"];
}
updateEntity.Attributes["_contactid"] = new EntityReference("contact", selectEn.Id);
if (selectEn.Attributes.Contains("thk_contact_no"))
updateEntity.Attributes["_contact_no"] = selectEn.Attributes["thk_contact_no"];
if (selectEn.Attributes.Contains("new_localortourist"))
updateEntity.Attributes["_local_or_tourist"] = selectEn.FormattedValues["new_localortourist"];
if (selectEn.Attributes.Contains("new_countryid"))
{
EntityReference countryReference = (EntityReference)selectEn.Attributes["new_countryid"];
updateEntity.Attributes["_country"] = new EntityReference("new_country", countryReference.Id);
}
if (selectEn.Attributes.Contains("thk_city"))
updateEntity.Attributes["_city"] = selectEn["thk_city"];
if (selectEn.Attributes.Contains("thk_address"))
updateEntity.Attributes["_address"] = selectEn.Attributes["thk_address"];
if (selectEn.Attributes.Contains("thk_contact_type"))
updateEntity.Attributes["_contact_type"] = selectEn.FormattedValues["thk_contact_type"];
if (selectEn.Attributes.Contains("new_creationshop"))
updateEntity.Attributes["_creationshop"] = selectEn.Attributes["new_creationshop"];
if (selectEn.Attributes.Contains("_subscription"))
updateEntity.Attributes["_subscription"] = selectEn.FormattedValues["_subscription"];
if (selectEn.Attributes.Contains("new_ethnicity"))
updateEntity.Attributes["_ethnicity"] = selectEn.FormattedValues["new_ethnicity"];
if (selectEn.Attributes.Contains("fullname"))
updateEntity.Attributes["_fullname"] = selectEn["fullname"];
if (selectEn.Attributes.Contains("new_languageid"))
updateEntity.Attributes["_language"] = selectEn.FormattedValues["new_languageid"];
if (selectEn.Attributes.Contains("lastname"))
updateEntity.Attributes["_lastname"] = selectEn["lastname"];
if ((selectEn.Attributes.Contains("new_membercardid")))
updateEntity.Attributes["_membercard"] = selectEn.Attributes["new_membercardid"];
if (selectEn.Attributes.Contains("lastname"))
item.Attributes["_name"] = selectEn.Attributes["lastname"];
if (selectEn.Attributes.Contains("new_phoneareacode"))
updateEntity.Attributes["_phoneprefix"] = selectEn.Attributes["new_phoneareacode"];
if (selectEn.Attributes.Contains("new_datecreated"))
updateEntity.Attributes["_sourcecreatedate"] = selectEn.Attributes["new_datecreated"];
if (selectEn.Attributes.Contains("emailaddress1"))
updateEntity.Attributes["_email"] = selectEn.Attributes["emailaddress1"];
if (selectEn.Attributes.Contains("mobilephone"))
{
updateEntity.Attributes["_phone"] = selectEn.Attributes["mobilephone"];
}
if (selectEn.Attributes.Contains("thk_contact_no"))
{
updateEntity.Attributes["_contact_no"] = selectEn.Attributes["thk_contact_no"];
}
updateEntity.Attributes["_processed"] = true;
service.Update(updateEntity);
Create_Num++;
}
}
}
string res = $"{Create_Num.ToString()} records are created.";
context.OutputParameters["OutParameter"] = res;
}
//TODO: Do stuff
}
catch (Exception e)
{
throw new InvalidPluginExecutionException(e.Message);
}
}
}
}
-
使Plugin-registration tool注册插件,注册为全局的,在Primary Entity处填写none, Message处选择action的名字,要先激活action
-
测试,批量上传一些记录到表中,此时,上传到CRM后有很字段是没有值的,这就需要点一个按钮(处理数据)调action去更新能匹配到的记录,
-
关于前端如何批量上传记录到CRM,也是采用webapi批量操作,需拼body,相对容易出错,如下代码,
function BatchPostAccounts() {
this.apiUrl = "https://yoururl.crm5.dynamics.com" +
"/api/data/v9.1/";
this.uniqueId = "batch_" + (new Date().getTime());
this.batchItemHeader = "--" +
this.uniqueId +
"\nContent-Type: application/http\nContent-Transfer-Encoding:binary";
this.content = [];
}
BatchPostAccounts.prototype.addRequestItem = function (entity, entityname) {
this.content.push(this.batchItemHeader);
this.content.push("");
this.content.push("POST " + this.apiUrl + entityname + " HTTP/1.1");
this.content.push("Content-Type: application/json;type=entry");
this.content.push("");
this.content.push(JSON.stringify(entity));
}
BatchPostAccounts.prototype.sendRequest = function () {
this.content.push("");
this.content.push("--" + this.uniqueId + "--");
this.content.push(" ");
var xhr = new XMLHttpRequest();
xhr.open("POST", encodeURI(this.apiUrl + "$batch"));
xhr.setRequestHeader("Content-Type", "multipart/mixed;boundary=" + this.uniqueId);
xhr.setRequestHeader("Accept", "application/json");
xhr.setRequestHeader("OData-MaxVersion", "4.0");
xhr.setRequestHeader("OData-Version", "4.0");
xhr.addEventListener("load",
function () {
console.log("Batch request response code: " + xhr.status);
});
xhr.send(this.content.join("\n"));
alert(xhr.response);
alert(xhr.status);
alert(xhr.response.readAsBinaryString());
}
function ExecuteBatchRequest() {
var batchRequest = new BatchPostAccounts();
var entityname = "apm_procontacts";
for (var i = 0; i < jsondt.value.length; i++) {
var contact = Object.create(ContactInfo);
contact._contact_no = jsondt.value[i]["Contact No"];
contact._email = jsondt.value[i]["Email"];
contact._sourcetable = jsondt.value[i]["Source Table"];
contact._mobilephone = jsondt.value[i]["Mobile Phone"];
contact._fullname = jsondt.value[i]["Last Name"];
var anonymous_json = {};
anonymous_json["_email"] = contact._email;
anonymous_json["_name"] = contact._fullname;
anonymous_json["_phone"] = contact._mobilephone;
anonymous_json["_contact_no"] = contact._contact_no;
anonymous_json["_city"] = "广州";
anonymous_json["_contactid@odata.bind"] = "/contacts(0001efb9-2d3e-e911-a982-000d3aa04914)";
batchRequest.addRequestItem(JSON.stringify(anonymous_json), entityname);
}
batchRequest.sendRequest(); //调用方法批量上传数据
document.getElementById("upload_btn").disabled = true;
}
- 上传完毕数据后,然后前端webapi调用CRM的action实现更新操作,WebApi调用Action代码如下
function UpdateUploadInfo() {
var result = null;
var entity = new Object();
entity["InputOne"] = "parameter input one";
entity["InputTwo"] = "parameter input two";
var req = new XMLHttpRequest()
req.open("POST", "https://yourCRM.crm5.dynamics.com/api/data/v9.1/new_ProContact_Process", false);
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) {
result = req.responseText;
}
else if (this.status == 204) {
console.log("Request executed successfully with a response.");
}
else {
var error = JSON.parse(this.response).error;
alert(error.message);
}
}
};
if (entity) {
req.send(JSON.stringify(entity))
}
else {
req.send();
}
alert(result);
document.getElementById("process_btn").disabled = true;
}
-
点击“处理数据”按钮后,数据已被更新,输出参数显示6条记录已被更新,
-
再回来CRM看记录,很没有值的字段已被更新