简体   繁体   English

Dynamics CRM 2011 - 通过插件阻止实体创建

[英]Dynamics CRM 2011 - Block Creation of Entity via Plugin

Problem: We use the CRM for Outlook plugin to automatically log our support emails, but internal emails between employees (some of which contain sensitive information) are also being logged. 问题:我们使用CRM for Outlook插件自动记录我们的支持电子邮件,但员工之间的内部电子邮件(其中一些包含敏感信息)也会被记录。

Ideal Solution: I am attempting to write a pre-event (the "create email" message) plugin to block the automatic logging of internal emails, but (apparently) the only way to stop a message from being executed is to throw an exception in the pre-event phase, but this always results in an error message being shown in outlook (which we obviously can't have). 理想的解决方案:我正在尝试编写一个事件前(“创建电子邮件”消息)插件来阻止内部电子邮件的自动记录,但(显然)阻止消息被执行的唯一方法是抛出异常事件前阶段,但这总是导致在outlook中显示错误消息(我们显然不能拥有)。 According to the documentation, only the "InvalidPluginExecutionExeception" is supposed to show messages to the user, but this is not the case as all exceptions result in an error message in the user's Outlook application. 根据文档,只有“InvalidPluginExecutionExeception”应该向用户显示消息,但事实并非如此,因为所有异常都会导致用户的Outlook应用程序中出现错误消息。

Potential Solution: There is also a "CheckPromoteEmail" message that (according to the documentation) determines whether or not an email should be promoted to the CRM (I assume "promoted to CRM" means "make an email entity to store in CRM"), but I couldn't find anything in the context that would let me tell CRM to not promote the email. 潜在的解决方案:还有一条“CheckPromoteEmail”消息(根据文档)确定是否应该将电子邮件提升为CRM(我假设“提升为CRM”意味着“使电子邮件实体存储在CRM中”) ,但我在上下文中找不到任何可以告诉CRM不推广电子邮件的内容。 Is there some flag buried in the context that I can set, or some way to invlaidate the email so the CRM's own logic decides to not store it? 是否有一些标记隐藏在我可以设置的上下文中,或者某种方式来放置电子邮件,以便CRM自己的逻辑决定不存储它?

Workaround Solution: The only other solution that I am aware of (mentioned here ) to just clear the subject and contents of the email after it has been created, but I would rather stop the email from being created in the first place than editing or deleting it after time and resources have been wasted creating the email. 解决方法解决方案:我知道( 此处提到)的唯一其他解决方案,只是在创建电子邮件后清除主题和内容,但我宁愿停止创建电子邮件,而不是编辑或删除经过时间和资源浪费创建电子邮件。

Is there a clean way to stop an operation from a plugin? 是否有一种干净的方法来阻止插件的操作? Or from anywhere? 或者从哪里来? If there isn't, does anyone know why Microsoft didn't provide this feature? 如果没有,有谁知道为什么微软不提供此功能? They already have ironclad rollback functionality under the hood in case an operation fails, why don't they just give me a way to call the rollback? 如果操作失败,他们已经具备了强大的回滚功能,他们为什么不给我一种方法来调用回滚?

Here's my code in case it's helpful in answering my question: 这是我的代码,以防它回答我的问题:

public class InternalEmailFilter : IPlugin
{
    void IPlugin.Execute(IServiceProvider serviceProvider)
    {
        IPluginExecutionContext _context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        Entity e = (Entity)_context.InputParameters["Target"];
        bool shouldStore = ShouldStoreInCRM(e);

        if (shouldStore == false)
        {
            throw new Exception(); //attempting to stop the operation without an InvalidPluginExecutionException, but still results in error message to user
        }            
    }

    protected bool ShouldStoreInCRM(Entity e)
    {

           List<Entity> parties = new List<Entity>();

            var atttributes = e.Attributes;
            if (atttributes.ContainsKey("to") == true) parties.AddRange((atttributes["to"] as EntityCollection).Entities);
            if (atttributes.ContainsKey("from") == true) parties.AddRange((atttributes["from"] as EntityCollection).Entities);
            if (atttributes.ContainsKey("cc") == true) parties.AddRange((atttributes["cc"] as EntityCollection).Entities);
            if (atttributes.ContainsKey("bcc") == true) parties.AddRange((atttributes["bcc"] as EntityCollection).Entities);

            foreach (Entity p in parties)
            {
                if (p.LogicalName == "activityparty" && p.Attributes.ContainsKey("addressused") == true && p.Attributes["addressused"] != null)
                {
                    if (p.Attributes["addressused"].ToString().ToLower().Contains("@ourdomain.com") == false)
                    {
                        return true; //someone connected in the email is not an employee, store the email
                    }
                }
            }

            return false;  //everyone was an employee, do not store          
    }
}

After much blood, sweat, and tears I finally figured out how to do this: 经过大量的血,汗和泪,我终于想出了如何做到这一点:

You have to use an async post-event plugin on the "Create email" message to delete the email from the DB with the CRMService after it has been created. 您必须在“创建电子邮件”消息上使用异步事件后插件,以便在创建CRMService后从数据库中删除该电子邮件。 It has to be asynchronous because you need to wait for the CRM finish creating and 'let go' of the entity before you can delete it. 它必须是异步的,因为您需要等待CRM完成创建并“释放”实体才能删除它。 Otherwise, the process hangs. 否则,该过程会挂起。

Any of these solutions would have been better, but for reference, you cannot: 任何这些解决方案都会更好,但作为参考,你不能:

  1. Throw an exception in the pre-event to cancel the create/promote email operation without either showing the user an error message or wreaking havoc on their Outlook. 在事件前抛出异常以取消创建/提升电子邮件操作,而不向用户显示错误消息或对其Outlook造成严重破坏。 Even though only the InvlaidPluginExectuionExecption is supposed to show a message to a user, all exceptions show error messages to users. 即使只有InvlaidPluginExectuionExecption应该向用户显示消息,所有异常都会向用户显示错误消息。
  2. Block the promotion of an email to CRM. 阻止向CRM发送电子邮件。 The CheckPromoteEmail message pre-event (amazingly) gives no information about the message to be potentially promoted (so there's no data to use to decide if the message should be promoted) and there is nothing to use to tell CRM to not promote the message. CheckPromoteEmail消息事件前(令人惊讶地)没有提供有关可能被提升的消息的信息(因此没有数据可用于决定是否应该提升消息)并且没有任何可用来告诉CRM不提升消息。 And, if you use the pre/post-event and try and use the Output params and change the ShouldPromote flag there, it does nothing. 并且,如果您使用事件前/后事件并尝试使用输出参数并在那里更改ShouldPromote标志,则它什么都不做。
  3. Clear the body content of an email before an Entity is created for it - any changes you make to the body content in the pre-event don't stay with the execution context and are lost when the core operation begins. 在为其创建实体之前清除电子邮件的正文内容 - 您在事件前对正文内容所做的任何更改都不会保留在执行上下文中,并且在核心操作开始时会丢失。

Maddening. 郁闷了。

Sorry, the workaround is your only option. 对不起,解决方法是您唯一的选择。 The only way to stop an operation via a plugin is to throw an exception. 通过插件停止操作的唯一方法是抛出异常。 Why did Microsoft do this? 为什么微软这样做? I assume they didn't want plugins silently failing. 我假设他们不希望插件无声地失败。

As for the workaround, you should clear the subject and body before they go into the database by clearing them in your pre-event plugin, then clean up the record itself in a post-event asynchronous plugin. 至于解决方法,你应该进入数据库之前清除主题和正文,方法是事件前插件中清除它们,然后在事件后异步插件中清理记录本身​​。 This way that sensitive info doesn't make it into any auditing logs either. 这样敏感信息也不会进入任何审核日志。

Finally, look at DeliverPromoteEmail instead of CreateEmail . 最后,查看DeliverPromoteEmail而不是CreateEmail DeliverPromoteEmail is what is used by Outlook to create the tracked emails. DeliverPromoteEmail是Outlook用于创建跟踪的电子邮件的内容。 This way you could still create Emails in the CRM UI that don't fire this plugin (if needed). 这样,您仍然可以在CRM UI中创建不会触发此插件的电子邮件(如果需要)。

edit CheckPromoteEmail only looks at the tracking token in the subject (and/or the MessageID in the email header) to decide whether an email should be tracked, so it won't be useful either. 编辑 CheckPromoteEmail仅查看主题中的跟踪令牌(和/或电子邮件标题中的MessageID)以确定是否应跟踪电子邮件,因此它也没有用处。

您可以选择在个人设置中选择跟踪所有电子邮件,电子邮件回复CRM电子邮件(已经跟踪的电子邮件),来自记录(帐户等)的电子邮件以及已启用电子邮件的记录中的电子邮件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM