Как предотвратить бесконечный цикл без ExecutionContext.CallerOrigin в Microsoft Dynamics CRM 2011? - PullRequest
6 голосов
/ 16 мая 2011

При создании плагина в Microsoft Dynamics CRM 4.0 вы можете использовать следующее для проверки источника события, вызвавшего запуск плагина.

public void Execute(IPluginExecutionContext context)
    {
        if (context.CallerOrigin.GetType() == CallerOrigin.WebServiceApi.GetType())
        {
            return;
        }
        plugin code here...
     }

Это позволит вам проверить, было ли действие вызвано пользователем в форме, веб-службой или рабочим процессом и т. Д ...

У меня есть приложение для синхронизации, которое создает и обновляет объекты через WCF, и не хочу, чтобы плагин выполнялся, когда это происходит, только когда пользователи редактируют объекты (чтобы предотвратить бесконечные циклы в процессе синхронизации).

IExecutionContext.CallerOrigin был удален в MS Dynamics CRM 2011, , так каков новый способ сделать это?

Я думал, что может быть способ установить IExecutionContext.CorrelationId в вызовах WCF, а затем проверить его на наличие определенного Guid в плагине, но мне пока не повезло с этим.

Ответы [ 4 ]

11 голосов
/ 13 марта 2012

Хотя это, кажется, было задано некоторое время назад (и я полагаю, что ОП уже нашел свое решение!), Я наткнулся на него в поисках аналогичного ответа недавно. Потребовались дальнейшие исследования, чтобы выяснить, что мне нужно, поэтому по этой причине я добавлю это сюда и для всех, кто сталкивается с этим.

Во-первых, если вы ищете его, это свойство устарело. Возможно, потому что это было ненадежно, но было несколько причин, по которым нам нужен CallerOrigin в MSCRM 4.0. С другой стороны, есть способы обойти это устаревшим:

Предотвращение бесконечных циклов (более 2 плагинов)

Это была причина, по которой я искал CallerOrigin и как я наткнулся на этот вопрос. Я хотел, чтобы плагин запускался только в том случае, если он получен от пользователя в форме, а не от другого плагина (то есть asyc process / webservice). В моем случае различие между «более чем 2 плагинами» очень важно, потому что я не могу использовать InputParameters для решения проблемы. Мой пример был похож на следующее:

  • Обновлен плагин для "родительского" объекта. Если для родительского объекта был установлен параметр «Состояния», для которого было установлено «Одобрено», то впоследствии я хотел установить для всех дочерних объектов также статус «Одобрено».

  • Обновлен плагин для "дочерней" сущности. Если для набора параметров с именем «Status» на дочернем объекте было установлено значение «Approved», а для всех остальных дочерних элементов этого же родителя установлено значение «Approved», мне также потребовалось обновить Status на родительском объекте до «Approved».

Это вызывает бесконечный цикл, если вы не защищаете себя от этого. Вы также не можете использовать InputParameters для ее решения. Одним из основных решений является использование проверки глубины:

context.PluginExecutionContext.Depth

Если это больше 1, он был вызван другим плагином / рабочим процессом. Примечание. Если у вас есть рабочий процесс, запускающий первоначальное обновление, вы можете быть осторожны с тем, какое значение вы проверяете.

Предотвращение проблем синхронизации с автономным клиентом

Нам были даны разные свойства, чтобы помочь нам отличить их. Используйте это вместо:

context.PluginExecutionContext.IsExecutingOffline
context.PluginExecutionContext.IsOfflinePlayback

Реагирует по-разному в зависимости от происхождения

Хорошо, так что это единственный сценарий, где нам действительно нужен CallerOrigin. Я думаю, что единственный способ сделать это - проверить тип самого PluginExecutionContext. Я знаю, для асинхронного это тип:

Microsoft.Crm.Asynchronous.AsyncExecutionContext

и для плагинов это выглядит так:

Microsoft.Crm.Extensibility.PipelineExecutionContext

Не уверен, что это, если исходить из внешнего источника, к сожалению, в данный момент у меня нет кода, чтобы проверить и выяснить это. Помимо всего, что вам, вероятно, придется проверить:

PluginExecutionContext.ParentContext

Единственный другой метод, с которым я столкнулся, для определения, откуда пришло обновление, - использование пользовательского флага в форме. Таким образом, вы можете создать OptionSet с именем «OriginOfChange» (или что-то подобное) с параметрами

  • Форма CRM (Javascript onsave)
  • Workflow
  • Plugin
  • и т.д.

Тогда то, что когда-либо обновляет сущность, устанавливает это поле во время обновления. Таким образом, вы можете проверять входные параметры каждый раз, чтобы увидеть, откуда пришло обновление.

Этот последний метод, скорее всего, наиболее безопасный для применения, если вам нужно реагировать по-разному в зависимости от источника.

3 голосов
/ 02 августа 2012

Решение этого потока состоит в том, чтобы "просто проверить свойство context.depth, если оно больше, чем 1 return"

Он отлично работал для моего плагина обновления, где я обновлял сущность внутри него, вызывая двойной запуск плагина, но во второй раз он проверял глубину и выходил.

Обновление

Безусловно, самый безопасный метод - использовать общие параметры , а не глубину плагина. Если единственное, что проверяется, - это глубина плагина, то каждый раз, когда другой плагин запускает другой плагин, он не будет работать, потому что его глубина равна 2, даже если плагин запускается впервые для события Update.

2 голосов
/ 17 мая 2011

Вы заглянули внутрь IPluginExecutionContext.InputParameters?

Другой вариант - изменить ваш плагин так, чтобы он ничего не обновлял, если бы не было изменений, что предотвратит возможность бесконечного цикла.

0 голосов
/ 05 ноября 2013

Глубина исполнения, а не рекурсии. Вы можете получить глубину> 1 при первом запуске вашего плагина. Думайте об этом как об Уровне в конвейере выполнения (на самом деле это глубина стека выполнения), кто-то получил его первым, когда выполнение прошло, Глубина увеличивается на 1, поэтому следующие в строке выполняют какую-то другую операцию и перед ее повторной передачей к трубе увеличивается на +1 глубину, теперь Dynamics запускает ваш плагин, ваша глубина будет равна 3 (Initial 1 [+1 | +1]). CRM 2011 локально ограничен по умолчанию до 8, а онлайн ограничен до глубины 16.

Итак, для предотвращения рекурсии с помощью Depth вы просто ПРИНИМАЕТЕ, а не можете утверждать это.

MSDN IExecutionContext.Depth Property

Мои 2 цента, С уважением Эрик Арен

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...