首页 > 解决方案 > 如何编写一个在相关子网格更新时触发的插件

问题描述

我正在创建一个插件,该插件应该在合同实体的表单上的子网格(contractdetail)中添加新记录时触发。contract 和 contractdetail (contract_line_items) 之间存在 1-N 关系。我只希望我的插件在合同实体处于活动状态(状态码 == 0)时执行。我只想基于此更新一些记录,但是,我无法根据我想要的标准执行插件。这是我到目前为止所拥有的:

using System;
using System.Collections.Generic;
using System.ServiceModel;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;


/// <summary>
/// This plugin will update Unit Orders after the contract has already been invoiced.
/// The update will run on the alter unit orders.
/// </summary>

namespace MAGA.Plugins
{


    [CrmPluginRegistration(MessageNameEnum.Update,
    "contractdetail",
    StageEnum.PostOperation,
    ExecutionModeEnum.Asynchronous,
    "contractid",
    "Post-Invoice Contract",
    1000,
    IsolationModeEnum.Sandbox,
    Image1Name = "PreImage",
    Image1Type = ImageTypeEnum.PreImage,
    Image1Attributes = "")]
    public class UnitPluginPostInvoice : IPlugin
    {

        public void Execute(IServiceProvider serviceProvider)
        {
            // Extract the tracing service for use in debugging sandboxed plug-ins.
            // Will be registering this plugin, thus will need to add tracing service related code.

            ITracingService tracing = (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            //obtain execution context from service provider.
            IPluginExecutionContext context = (IPluginExecutionContext)
                serviceProvider.GetService(typeof(IPluginExecutionContext));

            // InputParameters collection contains all the data passed in the message request. 
            if (context.InputParameters.Contains("Target") &&
                context.InputParameters["Target"] is Entity)
            {
                Entity entity = (Entity)context.InputParameters["Target"];

                Entity PreImage = context.PreEntityImages["PreIMage"];



                if (entity.LogicalName != "contractdetail" && entity.GetAttributeValue<OptionSetValue>("statecode").Value != 0)
                    return;


                IOrganizationServiceFactory serviceFactory =
                    (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));

                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);


                var contractId = entity.GetAttributeValue<EntityReference>("contractid");
                var contract = service.Retrieve(contractId.LogicalName, contractId.Id, new ColumnSet(true));

                if (contract.GetAttributeValue<OptionSetValue>("statecode").Value != 0)
                    return;

                try
                {
                    // Plugin code here
                }
                catch (FaultException<OrganizationServiceFault> ex)
                {
                    throw new InvalidPluginExecutionException("An error occured.. Phil is responsible. ", ex);
                }
                catch (Exception ex)
                {
                    tracing.Trace("An error occured: {0}", ex.ToString());
                    throw;
                }
            }


        }

    }

}

这是一张供视觉参考的图片!

合同表格

标签: pluginsdynamics-crmdynamics-365

解决方案


对代码的一些评论:

  • 该插件是异步的。除非您正在与 Web 服务通信,否则您应该切换到同步。它还为用户提供了更好的反馈。
  • 事件是更新(MessageNameEnum.Update),它应该只在这种情况下创建
  • 当您获取合约状态时,更改此:new ColumnSet(true) 为:new ColumnSet("statecode")。true 表示返回所有列。
  • 在 try-catch 中包含所有内容。

其余的看起来不错。祝你好运,替我向菲尔问好。


推荐阅读