Jak zapobiec nieskończonej pętli bez ExecutionContext.CallerOrigin w programie Microsoft Dynamics CRM 2011?

Jak zapobiec nieskończonej pętli bez ExecutionContext.CallerOrigin w programie Microsoft Dynamics CRM 2011?

Chociaż wydaje się, że zadano to jakiś czas temu (i przypuszczam, że PO znalazł już swoje rozwiązanie!), natknąłem się na to ostatnio, szukając podobnej odpowiedzi. Potrzebowałem dalszych badań, aby dowiedzieć się, czego potrzebuję, więc z tego powodu dodam to również tutaj dla każdego, kto się z tym spotka.

Po pierwsze, jeśli szukasz, ta nieruchomość stała się przestarzała. Podobno dlatego, że był zawodny, ale było kilka powodów, dla których potrzebowaliśmy CallerOrigin w MSCRM 4.0. Z drugiej strony istnieją sposoby, aby to również stało się przestarzałe:

Zapobiegaj nieskończonym pętlom (ponad 2 wtyczki)

To był powód, dla którego szukałem CallerOrigin i jak natrafiłem na to pytanie. Chciałem, aby wtyczka uruchamiała się tylko wtedy, gdy pochodzi od użytkownika w formularzu, a nie z innej wtyczki (np. Asyc process/webservice). W moim przypadku rozróżnienie „ponad 2 wtyczkami” jest dość ważne, ponieważ nie mogę użyć InputParameters do rozwiązania problemu. Mój przykład był podobny do następującego:

  • Zaktualizuj wtyczkę dla jednostki „nadrzędnej”. Jeśli zestaw opcji o nazwie „Status” w encji nadrzędnej został ustawiony na „Zatwierdzony”, chciałem następnie ustawić status wszystkich encji podrzędnych również na „Zatwierdzony”.

  • Zaktualizuj wtyczkę dla jednostki „dziecko”. Jeśli zestaw opcji o nazwie „Status” w encji podrzędnej został ustawiony na „approved”, a wszystkie inne elementy podrzędne tego samego rodzica mają ten parametr ustawiony na „Approved”, musiałem zaktualizować status rodzica, aby również został zatwierdzony.

Powoduje to nieskończoną pętlę, jeśli się przed nią nie zabezpieczysz. Nie możesz również użyć InputParameters do jego rozwiązania. Jednym z podstawowych rozwiązań jest użycie sprawdzania głębokości:

context.PluginExecutionContext.Depth

Jeśli jest większa niż 1, została wywołana przez inną wtyczkę/przepływ pracy. Uwaga:jeśli masz przepływ pracy, który uruchamia początkową aktualizację, możesz być ostrożny przy sprawdzaniu wartości.

Zapobiegaj problemom z synchronizacją z klienta offline

Otrzymaliśmy różne właściwości, które pomogą nam je rozróżnić. Użyj tych zamiast:

context.PluginExecutionContext.IsExecutingOffline
context.PluginExecutionContext.IsOfflinePlayback

Różne reagowanie w zależności od pochodzenia

OK, więc to jedyny scenariusz, w którym naprawdę potrzebujemy CallerOrigin. Myślę, że jedynym sposobem, w jaki możesz to zrobić, jest sprawdzenie typu samego PluginExecutionContext. Wiem, że w przypadku asynchronii jest to typ:

Microsoft.Crm.Asynchronous.AsyncExecutionContext

a dla wtyczek wygląda na to, że:

Microsoft.Crm.Extensibility.PipelineExecutionContext

Nie jestem pewien, co to jest, gdy pochodzi z zewnętrznego źródła, niestety nie mam w tej chwili żadnego kodu, który mógłbym przetestować i rozgryźć. Poza tym prawdopodobnie musiałbyś sprawdzić:

PluginExecutionContext.ParentContext

Jedyną inną metodą, na którą natknąłem się w celu wykrycia, skąd pochodzi aktualizacja, jest użycie niestandardowej flagi w formularzu. Możesz więc utworzyć zestaw opcji o nazwie „OriginOfChange” (lub coś podobnego) z opcjami

  • Formularz CRM (zapisywanie JavaScript)
  • Przepływ pracy
  • Wtyczka
  • itd.

Następnie cokolwiek aktualizuje encję, ustawia to pole podczas aktualizacji. W ten sposób można za każdym razem sprawdzać parametry wejściowe, aby zobaczyć, skąd pochodzi aktualizacja.

Ta ostatnia metoda jest najprawdopodobniej najbezpieczniejsza do zastosowania, jeśli musisz reagować inaczej w zależności od źródła.


Rozwiązaniem tego wątku jest "Po prostu sprawdź właściwość context.depth, jeśli jest większa niż 1 powrót"

Działało to doskonale w przypadku mojej wtyczki aktualizacyjnej, w której aktualizowałem encję w niej, powodując, że wtyczka została uruchomiona dwukrotnie, ale za drugim razem sprawdziła głębokość i zakończyła działanie.

Aktualizacja

Zdecydowanie najbezpieczniejszą metodą jest użycie wspólnych zmiennych, a nie głębi wtyczek. Jeśli jedyną rzeczą, która jest sprawdzana, jest głębokość wtyczki, to za każdym razem, gdy inna wtyczka uruchomi inną wtyczkę, nie zostanie ona wykonana, ponieważ jej głębokość wynosi 2, nawet jeśli wtyczka została uruchomiona po raz pierwszy dla zdarzenia Update.


Czy zajrzałeś do IPluginExecutionContext.InputParameters?

Inną opcją byłoby zmodyfikowanie wtyczki, aby niczego nie aktualizować, jeśli nie ma zmian, co uniemożliwiłoby nieskończoną pętlę.