26.08.2010, 10:47 | #1 |
Участник
|
KeyNotFoundException и HttpUnhandledException в плагине на update сущьности customerrelationship
Суть плагина:
есть сущность, customerrelationship-отношение с клиентом( customerrelatinship.PNG ) , если в поле "Роль1" стоит значение "Входит в холдинг", то для соответствующего Бизнес Партнера (это поле "Сторона 1") проставлять поле "условное объединение с иным БП" в значение " задано в отношении"( БП.PNG ) . Нужно отслеживать все изменения в сущности customerrelationship(ее удаление , update изменение ее полей) т.е. поддерживать в актуальном состоянии поле "условное объединение с иным БП" в БП. Аналогично для полей "Сторона2" и "Роль2". Проблема в следующем: Есть отношение, у него запполнены сторона1 сторона2 роль1 роль2 . Если его открыть и изменить роль1 на "ПУСТО" то плагин ведет себя некорректно: 1) если нажимать save то он оставляет прежнее значение поля "роль1" и на "пусто" его НЕ меняет. 2) а если нажать save and close то он "пусто" в поле "роль1" сохраняет (если потом его открыть то это видно) НО остается окно с ошибкой (crm error on save&close.PNG ) Что интересно: аналогичные действия для "Роль2" и "Сторона2" проходят нормально!!! это код плагина(CustomerrelationPlugin.txt ) Цитата:
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Crm.Sdk; using Microsoft.Crm.SdkTypeProxy; using Microsoft.Crm.Sdk.Query; using System.Xml; namespace test_25_08_2010 { public class noticeOnCustomerrelationshipPlugin : IPlugin { public noticeOnCustomerrelationshipPlugin(string unsecureConfig, string secureConfig) { try { } catch (Exception ex) { throw new InvalidPluginExecutionException( "An error occurred in the detailSummator plug-in.", ex); } } public void Execute(IPluginExecutionContext context) { DynamicEntity entity = null; if (context.InputParameters.Properties.Contains("Target")) { if (context.InputParameters.Properties["Target"] is DynamicEntity) { entity = (DynamicEntity)context.InputParameters.Properties["Target"]; Guid inHoldingCompanyGuid = new Guid("98CBD94A-2FEE-DE11-8853-00155D4E1B14");//id сущности "входит в холдинг" Customer customerC = null;//Сторона1 Guid customerCValue = new Guid("00000000-0000-0000-0000-000000000000"); Lookup customerLk = null;//Роль1 Guid customerLkValue = new Guid("00000000-0000-0000-0000-000000000000"); DynamicEntity cEntity = null; if (entity.Properties.Contains("customerid") && entity.Properties.Contains("customerroleid")) { customerC = (Customer)entity.Properties["customerid"];//Сторона1 customerCValue = customerC.Value; customerLk = (Lookup)entity.Properties["customerroleid"];//Роль1 customerLkValue = customerLk.Value; } else { if (entity.Properties.Contains("customerrelationshipid") && context.MessageName != "Update") { // cEntity = getCustomerrelationshipById(context, ((Key)entity.Properties["customerrelationshipid"]).Value, "customerid", "customerroleid"); // customerC = (Customer)cEntity.Properties["customerid"];//Сторона1 customerCValue = customerC.Value; if (cEntity.Properties.Contains("customerroleid")) { customerLk = (Lookup)cEntity.Properties["customerroleid"];//Роль1 customerLkValue = customerLk.Value; } } } if (context.MessageName == "Create" && entity.Properties.Contains("customerroleid") && !customerLk.IsNull && (customerLkValue == inHoldingCompanyGuid)) { changeCustomerrelationshipNamberOfAccount(context, new Key(customerCValue), new CrmBoolean(true)); } if (context.MessageName == "Update") { //getting entity from preStage image DynamicEntity preCustomerrelationship1 = null; Customer preCustomer = null; Guid preCustomerValue = new Guid("00000000-0000-0000-0000-000000000000"); Lookup preCustomerLk = null; Guid preCustomerLkValue = new Guid("00000000-0000-0000-0000-000000000000"); if (context.PreEntityImages.Properties.Contains("CustomerrelationshipPreImage") && context.PreEntityImages.Properties["CustomerrelationshipPreImage"] is DynamicEntity) { preCustomerrelationship1 = (DynamicEntity)context.PreEntityImages.Properties["CustomerrelationshipPreImage"]; preCustomer = (Customer)preCustomerrelationship1.Properties["customerid"]; preCustomerValue = preCustomer.Value; if (preCustomerrelationship1.Properties.Contains("customerroleid")) { preCustomerLk = (Lookup)preCustomerrelationship1.Properties["customerroleid"]; preCustomerLkValue = preCustomerLk.Value; } //try //{ // preCustomerLk = (Lookup)preCustomerrelationship.Properties["customerroleid"]; // preCustomerLkValue = preCustomerLk.Value; //} //catch (KeyNotFoundException) { } } //getting entity from postStage image DynamicEntity postCustomerrelationship1 = null; Customer postCustomer = null; Guid postCustomerValue = new Guid("00000000-0000-0000-0000-000000000000"); Lookup postCustomerLk = null; Guid postCustomerLkValue = new Guid("00000000-0000-0000-0000-000000000000"); // Проверяем что post-снимок существует if (context.PostEntityImages.Properties.Contains("CustomerrelationshipPostImage") && context.PostEntityImages.Properties["CustomerrelationshipPostImage"] is DynamicEntity) { postCustomerrelationship1 = (DynamicEntity)context.PostEntityImages.Properties["CustomerrelationshipPostImage"]; postCustomer = (Customer)postCustomerrelationship1.Properties["customerid"]; postCustomerValue = postCustomer.Value; if (postCustomerrelationship1.Properties.Contains("customerroleid")) { postCustomerLk = (Lookup)postCustomerrelationship1.Properties["customerroleid"]; postCustomerLkValue = postCustomerLk.Value; } //try //{ // postCustomerLk = (Lookup)postCustomerrelationship.Properties["customerroleid"]; // postCustomerLkValue = postCustomerLk.Value; //} //catch (KeyNotFoundException) { } } //if customerid changed //work just with the OLD customerrelationship!!! if (preCustomerValue != postCustomerValue) { if (preCustomerLkValue == inHoldingCompanyGuid) { changeCustomerrelationshipNamberOfAccountUsingSearch(context, "customerid", preCustomerValue, "customerroleid", 0); } } if (postCustomerLkValue == inHoldingCompanyGuid) { changeCustomerrelationshipNamberOfAccount(context, new Key(postCustomerValue), new CrmBoolean(true)); } else { if (postCustomerValue == preCustomerValue && preCustomerLkValue == inHoldingCompanyGuid) { changeCustomerrelationshipNamberOfAccountUsingSearch(context, "customerid", postCustomerValue, "customerroleid", 0); } } } Customer partnerC = null;//Сторона2 Guid partnerCValue = new Guid("00000000-0000-0000-0000-000000000000"); Lookup partnerLk = null;//Роль2 Guid partnerLkValue = new Guid("00000000-0000-0000-0000-000000000000"); DynamicEntity pEntity = null; if (entity.Properties.Contains("partnerid") && entity.Properties.Contains("partnerroleid")) { partnerC = (Customer)entity.Properties["partnerid"];//Сторона2 partnerCValue = partnerC.Value; partnerLk = (Lookup)entity.Properties["partnerroleid"];//Роль2 partnerLkValue = partnerLk.Value; } else { if (entity.Properties.Contains("customerrelationshipid") && context.MessageName != "Update") { pEntity = getCustomerrelationshipById(context, ((Key)entity.Properties["customerrelationshipid"]).Value, "partnerid", "partnerroleid"); partnerC = (Customer)pEntity.Properties["partnerid"];//Сторона2 partnerCValue = partnerC.Value; if (pEntity.Properties.Contains("partnerroleid")) { partnerLk = (Lookup)pEntity.Properties["partnerroleid"];//Роль2 partnerLkValue = partnerLk.Value; } } } if (context.MessageName == "Create" && entity.Properties.Contains("partnerroleid") && !partnerLk.IsNull && (partnerLkValue == inHoldingCompanyGuid)) { changeCustomerrelationshipNamberOfAccount(context, new Key(partnerCValue), new CrmBoolean(true)); } if (context.MessageName == "Update") { //getting entity from preStage image DynamicEntity preCustomerrelationship2 = null; Customer prePartner = null; Guid prePartnerValue = new Guid("00000000-0000-0000-0000-000000000000"); Lookup prePartnerLk = null; Guid prePartnerLkValue = new Guid("00000000-0000-0000-0000-000000000000"); if (context.PreEntityImages.Properties.Contains("CustomerrelationshipPreImage") && context.PreEntityImages.Properties["CustomerrelationshipPreImage"] is DynamicEntity) { // Получаем pre-снимок как объект DynamicEntity preCustomerrelationship2 = (DynamicEntity)context.PreEntityImages.Properties["CustomerrelationshipPreImage"]; prePartner = (Customer)preCustomerrelationship2.Properties["partnerid"]; prePartnerValue = prePartner.Value; if (preCustomerrelationship2.Properties.Contains("partnerroleid")) { prePartnerLk = (Lookup)preCustomerrelationship2.Properties["partnerroleid"]; prePartnerLkValue = prePartnerLk.Value; } //try //{ // prePartnerLk = (Lookup)preCustomerrelationship.Properties["partnerroleid"]; // prePartnerLkValue = prePartnerLk.Value; //} //catch (KeyNotFoundException) { } } //getting entity from postStage image DynamicEntity postCustomerrelationship2 = null; Customer postPartner = null; Guid postPartnerValue = new Guid("00000000-0000-0000-0000-000000000000"); Lookup postPartnerLk = null; Guid postPartnerLkValue = new Guid("00000000-0000-0000-0000-000000000000"); // Проверяем что post-снимок существует if (context.PostEntityImages.Properties.Contains("CustomerrelationshipPostImage") && context.PostEntityImages.Properties["CustomerrelationshipPostImage"] is DynamicEntity) { postCustomerrelationship2 = (DynamicEntity)context.PostEntityImages.Properties["CustomerrelationshipPostImage"]; postPartner = (Customer)postCustomerrelationship2.Properties["partnerid"]; postPartnerValue = postPartner.Value; if (postCustomerrelationship2.Properties.Contains("partnerroleid")) { postPartnerLk = (Lookup)postCustomerrelationship2.Properties["partnerroleid"]; postPartnerLkValue = postPartnerLk.Value; } //try //{ // postPartnerLk = (Lookup)postCustomerrelationship.Properties["partnerroleid"]; // postPartnerLkValue = postPartnerLk.Value; //} //catch (KeyNotFoundException) { } } //if partnerid changed //work just with the OLD customerrelationship!!!!!!!!!!! if (postPartnerValue != prePartnerValue) { if (prePartnerLkValue == inHoldingCompanyGuid) { changeCustomerrelationshipNamberOfAccountUsingSearch(context, "partnerid", prePartnerValue, "partnerroleid", 0); } } if (postPartnerLkValue == inHoldingCompanyGuid) { changeCustomerrelationshipNamberOfAccount(context, new Key(postPartnerValue), new CrmBoolean(true)); } else { if (postPartnerValue == prePartnerValue && prePartnerLkValue == inHoldingCompanyGuid) { changeCustomerrelationshipNamberOfAccountUsingSearch(context, "partnerid", postPartnerValue, "partnerroleid", 0); } } } }//если это DynamicEntity else { if (context.InputParameters.Properties["Target"] is Moniker) { Guid DelInHoldingCompany = new Guid("98CBD94A-2FEE-DE11-8853-00155D4E1B14");//id сущности "входит в холдинг" Moniker m = (Moniker)context.InputParameters.Properties["Target"]; DynamicEntity cDelEntity = getCustomerrelationshipById(context, m.Id, "customerid", "customerroleid"); Customer customerC = (Customer)cDelEntity.Properties["customerid"];//Сторона1 Guid customerCValue = customerC.Value; Lookup customerLk = null; Guid customerLkValue = new Guid("00000000-0000-0000-0000-000000000000"); if (cDelEntity.Properties.Contains("customerroleid")) { customerLk = (Lookup)cDelEntity.Properties["customerroleid"];//Роль1 customerLkValue = customerLk.Value; } if (customerLkValue == DelInHoldingCompany && context.MessageName == "Delete") { changeCustomerrelationshipNamberOfAccountUsingSearch(context, "customerid", customerCValue, "customerroleid", -1); } DynamicEntity pDelEntity = getCustomerrelationshipById(context, m.Id, "partnerid", "partnerroleid"); Customer partnerC = (Customer)pDelEntity.Properties["partnerid"];//Сторона2 Guid partnerCValue = partnerC.Value; Lookup partnerLk = null; Guid partnerLkValue = new Guid("00000000-0000-0000-0000-000000000000"); if (pDelEntity.Properties.Contains("partnerroleid")) { partnerLk = (Lookup)pDelEntity.Properties["partnerroleid"];//Роль2 partnerLkValue = partnerLk.Value; } if (partnerLkValue == DelInHoldingCompany && context.MessageName == "Delete") { changeCustomerrelationshipNamberOfAccountUsingSearch(context, "partnerid", partnerCValue, "partnerroleid", -1); } }//если это Moniker }// else для DynamicEntity }//если содержит "Target" } private BusinessEntityCollection getCustomerrelationshipsOfAccount(IPluginExecutionContext context, string typename, string pidname, Guid pguid, String role)//метод возвращает id тех сущностей типа typename, у которых pidname==pguid { Guid inHoldingCompanyG = new Guid("98CBD94A-2FEE-DE11-8853-00155D4E1B14");//id сущности "входит в холдинг" ICrmService service = context.CreateCrmService(false); QueryByAttribute query = new QueryByAttribute(); query.EntityName = typename; query.ColumnSet = new ColumnSet(); query.ColumnSet.AddColumn(String.Format("{0}id", typename)); query.Attributes = new string[] { pidname, role }; query.Values = new object[] { pguid, inHoldingCompanyG }; RetrieveMultipleRequest request = new RetrieveMultipleRequest(); request.Query = query; request.ReturnDynamicEntities = true; RetrieveMultipleResponse response = (RetrieveMultipleResponse)service.Execute(request); return response.BusinessEntityCollection; } private void changeCustomerrelationshipNamberOfAccount(IPluginExecutionContext context, Key bpKey, CrmBoolean value) { DynamicEntity entityToUpdate = new DynamicEntity(); entityToUpdate.Name = "account"; entityToUpdate.Properties.Add(new KeyProperty("accountid", bpKey)); entityToUpdate.Properties.Add(new CrmBooleanProperty("gar_conditional_association", value)); TargetUpdateDynamic accountTU = new TargetUpdateDynamic(); accountTU.Entity = entityToUpdate; UpdateRequest accountUR = new UpdateRequest(); accountUR.Target = accountTU; ICrmService service = context.CreateCrmService(false); UpdateResponse response = (UpdateResponse)service.Execute(accountUR); } private void changeCustomerrelationshipNamberOfAccountUsingSearch(IPluginExecutionContext context, String nameId, Guid pguid, String role, int correction) { BusinessEntityCollection ds = getCustomerrelationshipsOfAccount(context, "customerrelationship", nameId, pguid, role); int count = 0; count = ds.BusinessEntities.Count; if (count + correction > 0) { changeCustomerrelationshipNamberOfAccount(context, new Key(pguid), new CrmBoolean(true)); } else { changeCustomerrelationshipNamberOfAccount(context, new Key(pguid), new CrmBoolean(false)); } } private DynamicEntity getCustomerrelationshipById(IPluginExecutionContext context, Guid pguid, String nameId, String nameRoleId) { TargetRetrieveDynamic target = new TargetRetrieveDynamic(); target.EntityId = pguid; target.EntityName = "customerrelationship"; ColumnSet columnSet = new ColumnSet(); columnSet.AddColumn(nameId); columnSet.AddColumn(nameRoleId); // Create a retrieve request object. RetrieveRequest retrieve = new RetrieveRequest(); retrieve.Target = target; retrieve.ColumnSet = columnSet; retrieve.ReturnDynamicEntities = true; // Create a response reference and execute the retrieve request. ICrmService service = context.CreateCrmService(false); RetrieveResponse response = (RetrieveResponse)service.Execute(retrieve); DynamicEntity pentity = (DynamicEntity)response.BusinessEntity; return pentity; } } } |
|
26.08.2010, 15:23 | #2 |
Участник
|
Еще бы пара строчек кода и уже далеко не каждый взялся бы вникнуть в его суть...
А можно осторожно спросить, что мешает Вам отладить этот плагин в дебаггере?
__________________
Опыт позволяет ошибаться гораздо увереннее. |
|
|
За это сообщение автора поблагодарили: a33ik (1). |
27.08.2010, 10:07 | #3 |
Участник
|
Да кода многовато сорри я не так давно занялся MS crm около 1.5 месяца, а тему сюда вообще впервые создаю. в след раз учту этот косяк читабельности темы
Ничего не мешает я его отлаживал: 1) если при изменении отношения нажимать save and close,то он корректно проходит нужные if 'ы и конкретно условие где проверяется не пустое ли поле "Роль1" тоже правильно проходит. а в конце вместо закрытия окна с отношением в этом же окне остается ошибка(ее скрин я прикрепил к теме) 2) а если save нажимать то переменная РОЛЬ1получает значение не "пусто" которое я ставлю, а то значения что было при открытии (это во время дебага видно) а)Мне просто интересны мысли насчет ошибки. б) интересно почему при save он не сохраняет "пусто" в) и вопрос немного отвлеченный от темы: если у меня в папке C:\Program Files\Microsoft Dynamics CRM\Server\bin\assembly лежат предыдущие версии этого плагина и они были зарегистрированы на туже сущность событие и т.д что текущая версия плагина, может ли быть так что исполняется не последняя версия плагина а какая то из старых? причем предыдущии версии разрегистрированы, но iisreset не делал
__________________
rurik |
|
28.08.2010, 13:19 | #4 |
Moderator
|
Что значит предыдущие? Вы их нумеруете что ли вместо того, чтобы заменять? Я обычно отлаживаюсь так:
1. Настраиваю проект, чтобы собранные бинарные файлы и (pdb) сохранялись в папке assembly. 2. При регистрации сборки, указываю сохранять ее в базе. Отладка при этом работает нормально. 3. Изменяю код, собираю, обновляю в системе, после чего подключаюсь к процесу и отлаживаю. Перезагрузка IIS в этом случае не всегда требуется. Случай когда требуется очень легко отличить - если дебагер не подключается, то надо ресетить.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
29.08.2010, 20:07 | #5 |
Участник
|
по поводу отладки: 1) и 2) делаю именно так как и вы. просто пытался удалить файлы с ошибкой после того как я разрегистрировал соответствующую им сборку пишет что их использует w3pp процесс, соответственно приходится либо iisreset и отлаженное класть с тем же именем либо первый разрегиваю кладу отлаженное с другим именем и его регю
А что вы(Артем Enot Грунин) имеете в виду под "обновляю в системе"? в папке assembly. меняете бинарные файлы и (pdb) ? это? и он их подцепляет и работает уже новая сборка?(я просто не знаю каких действий достаточно чтобы заработала измененная сборка) А на счет ошибки есть мысли? хотя бы в какую сторону копать) ?
__________________
rurik |
|
30.08.2010, 14:26 | #6 |
Участник
|
а можно ли сделать поле обязательным к заполнению?(сущность "отношение с клиентом" нередактируема) или как то в плагине обязать пользователя вводить это поле иначе не будет сохранятся
P.S.лезть в базу и делать поле обязательным это вариант рискованный
__________________
rurik Последний раз редактировалось u.rastegaev; 30.08.2010 в 15:58. |
|
30.08.2010, 20:40 | #7 |
Moderator
|
Сделать поле обязательным можно в настройках соответствующего атрибута через интерфейс системы. Просто откройте на редактирование нужный атрибут и установите нужный уровень требований.
По поводу обновить в системе: плагин регистратор позволяет не только регистрировать, но и обновлять сборку при внесении в нее изменений. Если вы выбрали опцию "хранить сборку в базе", то без принудительного обновления при помощи утилиты вы новый код в процесс не подгрузите. Если сборку хранить в каталоге bin (при регистрации плагина), то собирать в него проект не получится - сервер будет блокировать сборку до вызова iisreset.
__________________
http://fixrm.wordpress.com, снятие/наведение порчи. Быстро, дорого, гарантия. MS Certified Dirty Magic Professional |
|
31.08.2010, 09:45 | #8 |
Участник
|
В том то и проблема что через интерфейс системы этого сделать нельзя, сущность не кастомизабельная и атрибут "Роль1" тоже нередактиируем
по поводу обновить: как именно? в PluginRegistrationTool выделяю сборку -> правая кнопка-> update->появляется окно как при регистрации новой сборки -> выбираю файл новой сборки-> ок и все? теперь в этом плагине работает новая сборка, ту которую я только что выбрал? а по поводу ошибки есть идеи? кстати я зарегил на эту же сущьность на те же события с теми же имейджами пустой плагин(я имею ввиду конструктор + execute пустой без моего кода) тоже самое и что самое странное опять keyNotFoundException: вообще не понятно( Цитата:
using System;
using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Crm.Sdk; using Microsoft.Crm.SdkTypeProxy; using Microsoft.Crm.Sdk.Query; using System.Xml; namespace test_empty_2 { public class noticeOnCustomerrelationshipPlugin : IPlugin { public noticeOnCustomerrelationshipPlugin(string unsecureConfig, string secureConfig) {} public void Execute(IPluginExecutionContext context) {} } }
__________________
rurik |
|
31.08.2010, 15:41 | #9 |
Участник
|
Сразу два вопроса:
1. А сборка-то подписана? 2. А Вы уверены, что именно этот плагин падает? Ну т.е. если его регистрацию задисэблить, то ошибка исчезает?
__________________
Опыт позволяет ошибаться гораздо увереннее. |
|
01.09.2010, 14:12 | #10 |
Участник
|
1) вы имеете ввиду ключем? да подписана
2) я разрегистрировал плагин - ошибка осталась, но у меня все таки сомнения в чистоте эксперимента, сегодня вечерком ребутну Crm и напишу,пропала ошибка или нет.
__________________
rurik |
|
01.09.2010, 20:04 | #11 |
Участник
|
сейчас ребутнул crm( iisreset ) ошибка осталась.
__________________
rurik |
|
01.09.2010, 20:35 | #12 |
Участник
|
Таким образом, можно сделать довольно уверенный вывод о том, что источником ошибки является не вышеуказанный плагин. Есть еще другие плагины? Отключайте их по одному и смотрите, когда пропадет ошибка.
__________________
Опыт позволяет ошибаться гораздо увереннее. |
|
|
|