使用BypassCustomPluginExecution参数忽略插件逻辑

少年辛苦终身事,莫向光阴惰寸功。这篇文章主要讲述使用BypassCustomPluginExecution参数忽略插件逻辑相关的知识,希望能为你提供帮助。
我是微软Dynamics 365 & Power Platform方面的工程师/顾问罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面的微软最有价值专家(Microsoft MVP),欢迎关注我的微信公众号 MSFTDynamics365erLuoYong ,回复467或者20220414可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!
在做项目的时候有时候有这种临时需求,使用管理员来做部分操作的时候希望跳过自己注册的插件/实时工作流逻辑,可能你想到的办法是先暂停这些插件/实时工作流,等处理完毕后再启用起来。我今天的博文介绍一种新的方法,官方文档请参考  ??Bypass Custom Business Logic?? 。
为了演示效果,我先用如下代码注册一个插件:

using Microsoft.Xrm.Sdk;
using System;

namespace D365.Plugins

public class AccountPreUpdate : IPlugin

public void Execute(IServiceProvider serviceProvider)

ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
tracingService.Trace($"Enter AccountPreUpdate on DateTime.UtcNow.ToString()");
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
if (context.InputParameters.Contains("Target") & & context.InputParameters["Target"] is Entity)

//插件针对的当前实体记录,对于Pre Update来讲,该对象包括了所有更改的字段值,若字段值没有更改,则不会存在targetEntity中
Entity targetEntity = (Entity)context.InputParameters["Target"];
if (targetEntity.Contains("telephone1"))

var telephone1 = targetEntity.GetAttributeValue< string> ("telephone1");
if (string.IsNullOrEmpty(telephone1))

throw new InvalidPluginExecutionException("主要电话不能为空!");

else if (telephone1.Length < 8)

throw new InvalidPluginExecutionException("主要电话不能少于8个字符!");







注册在account实体的Update消息的Pre Operation阶段,监控telephone1字段,如下:



然后如果我在界面上将主要电话设置为7个字符会报错如下:



但是我如果用下面的代码来更新的话,你会看到更新成功:
和普通的??更新记录的代码??的差别就是在RequestHeader中加了一个参数MSCRM.BypassCustomPluginExecution,并将其值设置为true。
var entity = ;
entity.telephone1 = 1234567;
var clientUrl = Xrm.Utility.getGlobalContext().getClientUrl();
var req = new XMLHttpRequest();
req.open("PATCH", `$clientUrl/api/data/v9.2/accounts($Xrm.Page.data.entity.getId().replace(,).replace(,))`);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("MSCRM.BypassCustomPluginExecution", true);
req.setRequestHeader("OData-Version", "4.0");
req.onreadystatechange = function ()
if (this.readyState == 4)
req.onreadystatechange = null;
if (this.status == 204)
console.log(Updated);

else
var error = JSON.parse(this.response).error;
Xrm.Navigation.openErrorDialog( message: error.message );


;
req.send(JSON.stringify(entity));




如果是使用组织服务呢?下面是示例代码:
这种使用CrmServiceClient的方法,BypassPluginExecution  参数设置后,后续的请求都会使用设置的值。
CrmServiceClient crmServiceClient = new CrmServiceClient(ConfigurationManager.AppSettings["connectStr"]);
if (crmServiceClient.IsReady)

Console.WriteLine($"连接到Dynamics 365环境 (crmServiceClient.ConnectedOrgFriendlyName) 成功");
crmServiceClient.BypassPluginExecution = true;
Entity accountEntity = new Entity("account", Guid.Parse("b39f780f-f984-ec11-8d20-0022485940f2"));
accountEntity["telephone1"] = "7654321";
crmServiceClient.Update(accountEntity);



那如果是在插件中呢,也可以嘛?答案是也可以,但是要稍微变化下,比如下面是示例:
可以看到不能直接使用Update, Create, Delete等消息,
需要转换成使用 UpdateRequest, CreateRequest, DeleteRequest  等类,通过组织的Execute方法来执行。
这种方法每个Execute执行之前都要设置一次BypassCustomPluginExecution参数才行。
var updateEntity = new Entity("account", Guid.Parse("b39f780f-f984-ec11-8d20-0022485940f2"));
updateEntity["telephone1"] = "7654321";
var updateRequest = new UpdateRequest()

Target = updateEntity
;
updateRequest.Parameters.Add("BypassCustomPluginExecution", true);
orgSvc.Execute(updateRequest);

这里还设计到权限问题,因为我之前演示使用的账号具有系统管理员角色,所以不会碰到权限问题。若是没有这个角色,会碰到权限问题,这个需要的权限名称是prvBypassCustomPlugins,Guid是  148a9eaf-d0c4-4196-9852-c3a38e35f6a1 ,但是这个权限没有界面来操作添加给某个角色,只能通过代码,因为官方文档上有代码,所以我就直接copy附在文中供各位参考:
Web API版本
POST [Organization URI]/api/data/v9.1/roles(< id of role> )/Microsoft.Dynamics.CRM.AddPrivilegesRole HTTP/1.1
Content-Type: application/json
Accept: application/json
OData-MaxVersion: 4.0
OData-Version: 4.0


"Privileges": [

"PrivilegeId": "148a9eaf-d0c4-4196-9852-c3a38e35f6a1",
"Depth": "3"

]



组织服务版本:
var request = new AddPrivilegesRoleRequest

RoleId = new Guid("< id of role> "),
Privileges = new[]
new RolePrivilege
PrivilegeId = new Guid("148a9eaf-d0c4-4196-9852-c3a38e35f6a1"),
Depth = PrivilegeDepth.Global


;
svc.Execute(request);



【使用BypassCustomPluginExecution参数忽略插件逻辑】最后值得一提的是,跳过的是自定义或者第三方供应商的插件/实时工作流逻辑,并不会跳过微软核心插件和微软作为发布者的插件/实时工作流。

    推荐阅读