执行插件的替代方式:用JS调用操作

关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复229或者20161028可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong.me 。

要执行插件,需要对对记录做更改或者创建记录后触发事件才行,利用JavaScript不能直接调用插件,需要曲线救国,比如更改一个字段,然后保存记录触发插件。从Dynamics CRM 2016开始,JavaScript可以方便的调用操作了,这个应该是一个代替插件的一个方式。
我这里举出一个常用例子,命令栏的按钮,在记录保存后,用户对记录有修改权限,用户具有代理角色的时候按钮可见,叫提交,点击以后执行一些具有事务性的操作(多个步骤要么都成功,要么都失败,操作刚好也支持这个特性,如果用纯粹的JavaScript来做的话就不支持事务),然后当前页面提示操作成功2秒以后刷新页面,为啥要刷新页面?因为提交成功后有些字段只读了,你不刷新还是可以改写就会出问题。
操作的建立方法我就不说了,我建立了一个带字符串参数的操作如下,为什么要带一个参数呢?减少文件的数量,多个不同的操作的服务器端代码写在一块。
 
操作中调用了一个自定义工作流活动,代码如下:
public sealed class TestOperations : CodeActivity
{
    [Input("操作名称:提交/检测/维修/关闭")]
    [Default("提交")]
    public InArgument<string> OperationName { get; set; }

    protected override void Execute(CodeActivityContext executionContext)
    {
        ITracingService tracingService = executionContext.GetExtension<ITracingService>();

        //Create the context
        IWorkflowContext context = executionContext.GetExtension<IWorkflowContext>();
        IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
        IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
        var userid = context.UserId;
        var initiatingUserId = context.InitiatingUserId;
        tracingService.Trace("userid=" + userid.ToString() + ";initiatingUserId=" + initiatingUserId);
        var operationName = executionContext.GetValue<string>(OperationName);
        tracingService.Trace("执行的操作是:" + operationName);
        if (operationName.Equals("提交"))
        {
            var testSubEntity = new Entity("ly_testsub");
            testSubEntity["ly_name"] = DateTime.Now.ToString();
            testSubEntity["ly_test"] = new EntityReference(context.PrimaryEntityName, context.PrimaryEntityId);
            service.Create(testSubEntity);
            var noteEntity = new Entity("annotation");
            noteEntity["objectid"] = new EntityReference(context.PrimaryEntityName, context.PrimaryEntityId);
            noteEntity["subject"] = DateTime.Now.ToString();
            service.Create(noteEntity);
        }

    }
}
然后我用来做按钮的RibbonDiff如下:
1. 统一使用EnableRule来设置可见性,因为要用到 CustomRule,而DisplayRule不支持
这种调用JavaScript函数返回true/false的rule.
2.用户对当前记录有写权限请使用 RecordPrivilegeRule,这个如果记录变成禁用了,
按钮也不会显示,或者是新建记录的时候也不会显示.
3.鼠标放到按钮上后显示的提示中详细提示是 ToolTipDescription ,简单提示是 ToolTipTitle。
<RibbonDiffXml>
    <CustomActions>
        <CustomAction Id="ly.ly_test.Submit.Button.CustomAction" Location="Mscrm.Form.ly_test.MainTab.Save.Controls._children" Sequence="75">
            <CommandUIDefinition>
                <Button Command="ly.ly_test.Submit.Command" Id="ly.ly_test.Submit.Button" Image32by32="/_imgs/ribbon/runreport32.png" Image16by16="/_imgs/ribbon/RunReport_16.png" LabelText="$LocLabels:ly.ly_test.Submit.Button.LabelText" Sequence="75" TemplateAlias="o2" ToolTipTitle="$LocLabels:ly.ly_test.Submit.Button.ToolTipTitle" ToolTipDescription="$LocLabels:ly.ly_test.Submit.Button.ToolTipDescription" />
            </CommandUIDefinition>
        </CustomAction>
    </CustomActions>
    <Templates>
        <RibbonTemplates Id="Mscrm.Templates" />
    </Templates>
    <CommandDefinitions>
        <CommandDefinition Id="ly.ly_test.Submit.Command">
            <EnableRules>
                <EnableRule Id="ly.ly_test.submitEnableRule.EnableRule" />
            </EnableRules>
            <DisplayRules />
            <Actions>
                <JavaScriptFunction FunctionName="submit" Library="$webresource:ly_/test/js/TestRibbon.js" />
            </Actions>
        </CommandDefinition>
    </CommandDefinitions>
    <RuleDefinitions>
        <TabDisplayRules />
        <DisplayRules>
        </DisplayRules>
        <EnableRules>
            <EnableRule Id="ly.ly_test.submitEnableRule.EnableRule">
                <RecordPrivilegeRule AppliesTo="PrimaryEntity" Default="false" InvertResult="false" PrivilegeType="Write" />
                <ValueRule Field="statuscode" Value="1" Default="false" InvertResult="false" />
                <CustomRule FunctionName="submitEnableRule" Library="$webresource:ly_/test/js/TestRibbon.js" Default="false" InvertResult="false" />
            </EnableRule>
        </EnableRules>
    </RuleDefinitions>
    <LocLabels>
        <LocLabel Id="ly.ly_test.Submit.Button.LabelText">
            <Titles>
                <Title description="提交" languagecode="0" />
                <Title description="提交" languagecode="2052" />
            </Titles>
        </LocLabel>
        <LocLabel Id="ly.ly_test.Submit.Button.ToolTipTitle">
            <Titles>
                <Title description="提交" languagecode="0" />
                <Title description="提交" languagecode="2052" />
            </Titles>
        </LocLabel>
        <LocLabel Id="ly.ly_test.Submit.Button.ToolTipDescription">
            <Titles>
                <Title description="提交看看" languagecode="0" />
                <Title description="提交看看" languagecode="2052" />
            </Titles>
        </LocLabel>
    </LocLabels>
</RibbonDiffXml>
用到的按钮的JavaScript如下:
1. 使用了 Xrm.Page.context.getUserRoles来传递用户拥有的角色ID,然后写了一个函数来判断
checkUserHasRoles 用户是否拥有多个角色中的一个,一般允许系统管理员也进行操作。
2.JavaScript数组已经直接支持 forEach,some等函数了,可以直接使用。
3.调用操作请注意使用了同步的请求来模拟插件。
4.刷新页面有点儿笨,当前页面提示成功等待两秒后刷新页面。
本来我想用别的办法,比如刷新后显示成功,可是不行,异步保存后提示也不好用。
function submitEnableRule() {
    return checkUserHasRoles(Xrm.Page.context.getUserRoles(), ["系统管理员", "代理"]);
}
function submit() {
    var clientURL = Xrm.Page.context.getClientUrl();
    var recordId = Xrm.Page.data.entity.getId().replace(/^{/, "").replace(/}$/, "");
    var req = new XMLHttpRequest()
    req.open("POST", encodeURI(clientURL + "/api/data/v8.0/ly_tests(" + recordId + ")/Microsoft.Dynamics.CRM.ly_TestOperation"), false);//true是异步请求,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 /* complete */) {
            req.onreadystatechange = null;
            if (this.status == 204) {//204代表成功无返回值
                //刷新页面
                Xrm.Page.ui.setFormNotification("操作成功!", 'INFO', '00F041A1-2D30-4B30-9D12-63285716D8ED');
                setTimeout(function () {
                    Xrm.Page.ui.clearFormNotification('00F041A1-2D30-4B30-9D12-63285716D8ED');
                    Xrm.Utility.openEntityForm(Xrm.Page.data.entity.getEntityName(), Xrm.Page.data.entity.getId());
                }, 2000);
            }
            else {
                var error = JSON.parse(this.response).error;
                Xrm.Utility.alertDialog("错误:" + error.message);
            }
        }
    };
    var requestmsg = {};
    requestmsg.OperationName = "提交";
    req.send(JSON.stringify(requestmsg));
}
function checkUserHasRoles(roleIdArray, roleNames) {
    var roleIds = "", userRoles = [], ret = false;
    var clientURL = Xrm.Page.context.getClientUrl();
    roleIdArray.forEach(function (element) {
        roleIds += "roleid eq " + element + " or ";
    });
    roleIds = roleIds.replace(/\sor\s$/, '');
    var req = new XMLHttpRequest()
    req.open("GET", encodeURI(clientURL + "/api/data/v8.1/roles?$select=name&$filter=" + roleIds), false);//true是异步请求,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) {
                var responseJSON = JSON.parse(this.responseText);
                if (responseJSON.value != null && responseJSON.value.length >= 1) {
                    responseJSON.value.forEach(function (element) {
                        if (roleNames.some(function (ele) { return ele == element.name })) {
                            ret = true;
                        }
                    });
                }
            }
        }
    }
    req.send();
    return ret;
}
//# sourceURL=TestRibbon.js
提交按钮效果如下:
 
 

猜你喜欢

转载自www.cnblogs.com/luoyong0201/p/Dynamics_365_Plugin_Replacement_JavaScript_Invoke_Action.html
今日推荐