【问题标题】:c# - Dynamics CRM Plugin - Auto-fill data prior to creationc# - Dynamics CRM Plugin - 在创建之前自动填充数据
【发布时间】:2016-11-08 13:35:02
【问题描述】:

我想使用插件来填写案例实体表单数据。我是使用 c# 和插件的新手,但我觉得这比使用 javascript 表单脚本更可靠。如果这是一个错误的假设,请告诉我。

我的目标是 1) 获取并检查用户的安全角色,2) 基于安全角色,使用通用的硬编码值自动填充“客户”字段。

案例表单上的“客户”字段是“系统必填”字段。我目前在事件创建、预验证和同步上注册了一个插件。当我尝试在不手动填写“客户”字段的情况下保存时,我无法保存,并且 UI 指出该字段尚未填写的事实。

我是否正在尝试做一些不可能的事情?或者我应该只使用 javascript 和/或业务规则来处理这样的事情吗?

【问题讨论】:

  • 那么您是希望在打开表单后立即填充该字段,还是在保存表单时填充该字段?
  • 它应该在表单打开后立即填充。

标签: javascript c# plugins dynamics-crm crm


【解决方案1】:
  1. 插件很昂贵。根据您的需要,使用 OnLoad JavaScript 函数更合适。
  2. 关于预验证阶段,验证实际上是检查用户权限等内容;在客户端检查现场要求级别。因此,即使是预验证插件也无法帮助用户跳过必填字段。
  3. 如果您喜欢插件,您可以为此字段设置一个默认值,并在插件中填充正确的值。

【讨论】:

    【解决方案2】:

    为了通过插件执行此操作,您可能需要对用户可能拥有的角色使用 RetrieveMultiple 请求,然后循环遍历结果以根据角色分配客户字段值...

    例如,如果您有一个 fetchxml 来获取您可以在插件中使用它的角色(您也可以使用 QueryExpression 来代替 fetchxml)...

    string FetchXML =  
        @"<fetch mapping='logical' count='50' version='1.0'>
            <entity name='systemuser'>
                <attribute name='fullname' />
            <link-entity name='systemuserroles' from='systemuserid' to='systemuserid'>
            <link-entity name='role' from='roleid' to='roleid'>
                <attribute name='name' />
            </link-entity>
            </link-entity>
            </entity>
        </fetch>";
    
    EntityCollection result = svcClient.OrganizationServiceProxy.RetrieveMultiple(new Microsoft.Xrm.Sdk.Query.FetchExpression(FetchXML));
    
    // and then loop thru result
    if (result != null)
    {
        foreach (var item in result.Entities) {
            // ... do your stuff here
            // item.roleName is just an idea.. I haven't tested the code yet..
            Entity case = new Entity("case");
    
            if (item.roleName == "role 01") 
                    contact.Attributes["customer_field"] = "hard-code value 01";
            if (item.roleName == "role 02") 
                    contact.Attributes["customer_field"] = "hard-code value 02";
    
             ...
             ...
        }
    }
    

    对于那个特定的场景,我认为你可以只使用 javascript 来实现它。如果你决定走这条路,这里有个主意……

    将 javascript 函数(例如 autoFillCustomer() )附加到表单的 onload 事件,该事件将验证角色名称并根据结果设置硬编码的所需值。

    function autoFillCustomer(){
            var roles = getAllUserRolesNames();
            var customerField = Xrm.Page.getAttribute("customer_field");
    
            for (var i = 0; i < roles.length; i++) {
                var roleName = roles[i];
    
                switch (roleName) {
                    case "Role Name 01":                
                        if ( customerField!= null )
                            customerFieldsetValue("hard-coded avlue 01");
    
                        break;
    
                    case "Role Name 021":                
                        if ( customerField!= null )
                            customerFieldsetValue("hard-coded avlue 02");
    
                        break;
    
                    default;            
                        if ( customerField!= null )
                            customerFieldsetValue("default value if needed");
                }
            }
        }
    

    然后.. 另一方面,您可能有另一个带有 getAllUserRolesName() 实现的 js 网络资源,并将其添加到您的表单中。 (这是因为您可以在未来的新场景中使用它)

    // Display Name: Get All User Roles Names
    // Description:  Returns an array containing all the roles and teams currently assigned to a user
    //               This will contain the name and not the guid which is what the standard getUserRoles() function does.
    function getAllUserRolesNames() {
        var guid = "[A-z0-9]{8}-[A-z0-9]{4}-[A-z0-9]{4}-[A-z0-9]{4}-[A-z0-9]{12}";
        var serverUrl = Xrm.Page.context.getClientUrl();
        var userId = Xrm.Page.context.getUserId();
        userId = userId.match(guid);
        var teamQuery = "TeamMembershipSet?$select=TeamId&$filter=SystemUserId eq guid'" + userId + "'";
        var teamRoleQuery = "TeamRolesSet?$select=RoleId&$filter=";
        var roleQuery = "RoleSet?$select=Name&$filter=";
        var teams = makeRequest(serverUrl, teamQuery, 0);
        teamRoleQuery = composeQuery(teamRoleQuery, "TeamId", teams);
        var teamRoles = makeRequest(serverUrl, teamRoleQuery, 1);
        userRoles = Xrm.Page.context.getUserRoles();
        if (userRoles != null) {
            for (var i = 0; i < userRoles.length; i++) {
                teamRoles.push(userRoles[i].match(guid));
            }
        }
        roleQuery = composeQuery(roleQuery, "RoleId", teamRoles);
        var roles = makeRequest(serverUrl, roleQuery, 2);
        return roles;
    }
    function makeRequest(serverUrl, query, type) {
        var oDataEndpointUrl = serverUrl + "/XRMServices/2011/OrganizationData.svc/";
        oDataEndpointUrl += query;
        var service = GetRequestObject();
        if (service != null) {
            service.open("GET", oDataEndpointUrl, false);
            service.setRequestHeader("X-Requested-With", "XMLHttpRequest");
            service.setRequestHeader("Accept", "application/json, text/javascript, */*");
            service.send(null);
            var retrieved = $.parseJSON(service.responseText).d;
            var results = new Array();
            switch (type) {
                case 0:
                for (var i = 0; i < retrieved.results.length; i++) {
                    results.push(retrieved.results[i].TeamId);
                }
                break;
                case 1:
                for (var i = 0; i < retrieved.results.length; i++) {
                    results.push(retrieved.results[i].RoleId);
                }
                break;
                case 2:
                for (var i = 0; i < retrieved.results.length; i++) {
                    if (results.indexOf(retrieved.results[i].Name) == -1) {
                        results.push(retrieved.results[i].Name);
                    }
                }
                break;
            }
            return results;
        }
        return null;
    }
    
    function GetRequestObject() {
        if (window.XMLHttpRequest) {
            return new window.XMLHttpRequest;
        } else {
            try {
                return new ActiveXObject("MSXML2.XMLHTTP.3.0");
            } catch (ex) {
                return null;
            }
        }
    }
    
    function composeQuery(queryBase, attribute, items) {
        if (items != null) {
            for (var i = 0; i < items.length; i++) {
                if (i == 0) {
                    queryBase += attribute + " eq (guid'" + items[i] + "')";
                } else {
                    queryBase += " or " + attribute + " eq (guid'" + items[i] + "')";
                }
            }
        }
        return queryBase;
    }
    

    【讨论】:

      【解决方案3】:

      编辑

      Arun 在 cmets 中指出,最初的问题是关于 Case (incident) 实体,而该实体的 Customer 字段是必填字段,不能修改为可选

      这意味着我在下面的答案对于 OP 来说是不可能的,但我将它留在这里以防它帮助任何在不同实体上工作的人


      即使您已将插件设置为在预验证时执行,这仍然在Create 消息管道上,这意味着您必须先点击保存按钮。但是,您已将该字段设置为必填,这就是您收到验证消息的原因

      如果您想坚持使用这种方法,我会进行以下更改:

      1. 更改“客户”字段使其不是必填项
      2. 将客户字段更改为只读
      3. 按照您的描述注册您的插件(创建;预验证;同步),以根据您的业务需求(即基于用户的安全角色)更新事件的 InputParameters

      此阶段的插件(预验证)意味着创建消息将在到达 CRM 数据库并将您的更改注入数据之前被拦截。

      这样做的好处(使用插件而不是其他用户建议的 javascript)是它将应用于所有 CRM 表单

      这种方法的缺点是用户在点击保存之前只能看到空的客户字段。如果他们按保存并关闭,那么他们可能根本没有意识到客户已被设置。您可以通过将此字段移动到名为“自动完成”或“系统生成”的部分来解决此问题,以便用户知道这是自动填写的

      【讨论】:

      • 想提一下 - 客户字段不能是非强制性的 - mobile.crmsoftwareblog.com/2016/09/…
      • @ArunVinoth 可选客户字段在 Dynamics CRM 365 中可用
      • 哇,很高兴知道。我知道可以添加客户类型属性。但是事件实体中的可选客户仍然令人难以置信..
      • @ArunVinoth 抱歉,我只是在谈论自定义客户字段。我刚刚检查了 Case 实体上的 Customer 仍然是系统强制性的。我会更新我的答案,因为它不符合 OP 的要求
      【解决方案4】:

      插件是更好的选择。在创建事件时设置一个虚拟客户,在预创建中您可以识别实际客户并覆盖虚拟值。

      http://mobile.crmsoftwareblog.com/2016/09/service-case-customer-field-not-required-dynamics-crm-2016/

      【讨论】:

        猜你喜欢
        • 2013-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-31
        • 1970-01-01
        • 2016-08-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多