public override void ExecuteExtention(DeployIntoFieldRequest request, DeployIntoFieldResponse response, ServiceRequestController controller) { var records = new List <IRecord>(); var publishIds = new List <string>(); var numberToDo = request.Files.Count(); var numberDone = 0; foreach (var file in request.Files.Select(f => f?.Replace("∕", "∕"))) { var fileInfo = new FileInfo(file); controller.UpdateProgress(++numberDone, numberToDo, "Importing " + fileInfo.Name); var thisResponseItem = new DeployIntoFieldResponseItem() { Name = fileInfo.Name }; response.AddResponseItem(thisResponseItem); try { var containingFolderName = fileInfo.Directory.Name; var containingFolderParentName = fileInfo.Directory.Parent != null ? fileInfo.Directory.Parent.Name : null; //get target record type string recordType = null; if (Service.GetAllRecordTypes().Any(r => r == containingFolderName)) { recordType = Service.GetAllRecordTypes().First(r => r == containingFolderName); } else if (Service.GetAllRecordTypes().Any(r => Service.GetDisplayName(r)?.ToLower() == containingFolderName.ToLower())) { recordType = Service.GetAllRecordTypes().First(r => Service.GetDisplayName(r)?.ToLower() == containingFolderName.ToLower()); } else { throw new NullReferenceException($"Could not find matching type by logical or display name for folder name of {containingFolderName}"); } thisResponseItem.RecordType = recordType; if (recordType == Entities.adx_webfile) { //this one goes into an attachment var matchingRecord = GetRecordToDeployInto(recordType, fileInfo.Name, containingFolderParentName); if (matchingRecord == null) { throw new NullReferenceException($"There is no {Service.GetDisplayName(recordType)} record name {fileInfo.Name} to load the file attachment into"); } thisResponseItem.Link = new Url(Service.GetWebUrl(matchingRecord.Type, matchingRecord.Id), "Open"); //get matching attachment by name else create a new one var fileAttachments = Service.RetrieveAllAndClauses(Entities.annotation, new[] { new Condition(Fields.annotation_.filename, ConditionType.Equal, fileInfo.Name), new Condition(Fields.annotation_.objectid, ConditionType.Equal, matchingRecord.Id) }).OrderBy(n => n.GetDateTime(Fields.annotation_.createdon)).ToArray(); var contentBytes = File.ReadAllBytes(file); var contentBase64String = Convert.ToBase64String(contentBytes); if (fileAttachments.Any()) { //lets update the last modifed one var attachmentToUpdate = fileAttachments.First(); if (attachmentToUpdate.GetStringField(Fields.annotation_.documentbody) != contentBase64String) { attachmentToUpdate.SetField(Fields.annotation_.documentbody, contentBase64String, Service); Service.Update(attachmentToUpdate, new[] { Fields.annotation_.documentbody }); thisResponseItem.Updated = true; } } else { //lets create a new attachment var newAttachment = Service.NewRecord(Entities.annotation); newAttachment.SetLookup(Fields.annotation_.objectid, matchingRecord.Id, matchingRecord.Type); newAttachment.SetField(Fields.annotation_.subject, fileInfo.Name, Service); newAttachment.SetField(Fields.annotation_.filename, fileInfo.Name, Service); newAttachment.SetField(Fields.annotation_.documentbody, contentBase64String, Service); Service.Create(newAttachment); thisResponseItem.Created = true; } } else { //get the record with the same name as the file var nameToMatch = fileInfo.Name.Substring(0, fileInfo.Name.LastIndexOf(".")); var matchingRecord = GetRecordToDeployInto(recordType, nameToMatch, containingFolderParentName); if (matchingRecord == null) { throw new NullReferenceException($"There is no {Service.GetDisplayName(recordType)} record name {fileInfo.Name} to load the file attachment into"); } thisResponseItem.Link = new Url(Service.GetWebUrl(matchingRecord.Type, matchingRecord.Id), "Open"); var targetField = GetTargetField(fileInfo, recordType); var contentText = File.ReadAllText(file); if (matchingRecord.GetStringField(targetField) != contentText) { matchingRecord.SetField(targetField, contentText, Service); Service.Update(matchingRecord, new[] { targetField }); thisResponseItem.Updated = true; } } } catch (Exception ex) { thisResponseItem.Exception = ex; } } }
public void VsixAddPortalCodeTest() { RecreatePortalData(createSecondDuplicateSite: true); var app = CreateAndLoadTestApplication <AddPortalCodeModule>(); var fakeProjectName = "FakeProjectName"; var directoryInfo = Directory.CreateDirectory(Path.Combine(VisualStudioService.SolutionDirectory, fakeProjectName)); VisualStudioService.SetSelectedItem(new FakeVisualStudioSolutionFolder(directoryInfo.FullName)); var websiteName = "Fake Site 1"; var webSite = XrmRecordService.GetFirst(Entities.adx_website, Fields.adx_website_.adx_name, websiteName); var request = new AddPortalCodeRequest { WebSite = XrmRecordService.ToLookup(webSite), ExportWhereFieldEmpty = true, CreateFolderForWebsiteName = true }; var dialog = app.NavigateToDialog <AddPortalCodeModule, AddPortalCodeDialog>(); var entryForm = app.GetSubObjectEntryViewModel(dialog); entryForm.GetLookupFieldFieldViewModel(nameof(AddPortalCodeRequest.WebSite)).SetValue(entryForm.GetLookupFieldFieldViewModel(nameof(AddPortalCodeRequest.WebSite)).ItemsSourceAsync.First(r => r.Record != null).Record); entryForm.GetBooleanFieldFieldViewModel(nameof(AddPortalCodeRequest.ExportWhereFieldEmpty)).Value = true; entryForm.GetBooleanFieldFieldViewModel(nameof(AddPortalCodeRequest.CreateFolderForWebsiteName)).Value = true; var section = entryForm.GetFieldSection(AddPortalCodeRequest.Sections.RecordsToInclude); var func = section.CustomFunctions.First(c => c.Id == "SELECTALL"); func.Invoke(); Assert.IsTrue(entryForm.GetEnumerableFieldViewModel(nameof(AddPortalCodeRequest.RecordsToExport)).GridRecords .All(r => r.GetBooleanFieldFieldViewModel(nameof(AddPortalCodeRequest.PortalRecordsToExport.Selected)).Value ?? false)); var webTemplateRow = entryForm.GetEnumerableFieldViewModel(nameof(AddPortalCodeRequest.RecordsToExport)) .GridRecords .First(gr => gr.GetRecordTypeFieldViewModel(nameof(AddPortalCodeRequest.PortalRecordsToExport.RecordType)).Value.Key == Entities.adx_webtemplate); webTemplateRow.GetBooleanFieldFieldViewModel(nameof(AddPortalCodeRequest.PortalRecordsToExport.IncludeAll)).Value = false; //this now auto runs when the flag above iunchecked //webTemplateRow.GetEnumerableFieldViewModel(nameof(AddPortalCodeRequest.PortalRecordsToExport.RecordsToInclude)).BulkAddButton.Invoke(); var templateRecordSelectionForm = entryForm.ChildForms.First() as MultiSelectDialogViewModel <PicklistOption>; templateRecordSelectionForm.ItemsSource.First().Select = true; templateRecordSelectionForm.ItemsSource.Last().Select = true; templateRecordSelectionForm.ApplyButtonViewModel.Invoke(); Assert.IsFalse(entryForm.ChildForms.Any()); Assert.IsTrue(entryForm.Validate()); entryForm.SaveButtonViewModel.Invoke(); var responseViewModel = app.GetCompletionViewModel(dialog); var response = responseViewModel.GetObject() as AddPortalCodeResponse; Assert.IsFalse(response.HasError); var rootFolder = Path.Combine(directoryInfo.FullName, websiteName); foreach (var typesFolder in new DirectoryInfo(rootFolder).GetDirectories()) { var fileCountInDirectory = typesFolder.GetFiles().Count(); var typeLabel = typesFolder.Name; var type = XrmRecordService.GetAllRecordTypes().First(rt => XrmRecordService.GetDisplayName(rt) == typeLabel); var recordsOfType = XrmRecordService.RetrieveAll(type, null); if (type == Entities.adx_webpage) { //web pages have a parent and child where onluy the ch9ild is exported // (multi language not implemented) // + each has html, css & javascript Assert.AreEqual((recordsOfType.Count() / 4) * 3, fileCountInDirectory); } else if (type == Entities.adx_webtemplate) { Assert.AreEqual(2, fileCountInDirectory); } else { Assert.AreEqual(recordsOfType.Count() / 2, fileCountInDirectory); } } }
private void ProcessForRelationships(CustomisationExporterRequest request, CustomisationExporterResponse response, LogController controller) { if (request.Relationships) { var allRelationship = new List <RelationshipExport>(); var types = GetRecordTypesToExport(request).OrderBy(t => Service.GetDisplayName(t)).ToArray(); var count = types.Count(); var manyToManyDone = new List <string>(); for (var i = 0; i < count; i++) { var thisType = types.ElementAt(i); var thisTypeLabel = Service.GetDisplayName(thisType); controller.UpdateProgress(i, count, "Exporting Relationships For " + thisTypeLabel); try { var relationships = Service.GetManyToManyRelationships(thisType); for (var j = 0; j < relationships.Count(); j++) { var relationship = relationships.ElementAt(j); try { if (relationship.RecordType1 == thisType || (!request.DuplicateManyToManyRelationshipSides && !manyToManyDone.Contains(relationship.SchemaName)) ) { allRelationship.Add(new RelationshipExport(relationship.SchemaName, relationship.RecordType1, relationship.RecordType2, relationship.IsCustomRelationship, relationship.RecordType1DisplayRelated, relationship.RecordType2DisplayRelated , relationship.Entity1IntersectAttribute, relationship.Entity2IntersectAttribute, RelationshipExport.RelationshipType.ManyToMany, relationship.RecordType1UseCustomLabel, relationship.RecordType2UseCustomLabel, relationship.RecordType1CustomLabel, relationship.RecordType2CustomLabel , relationship.RecordType1DisplayOrder, relationship.RecordType2DisplayOrder, relationship.MetadataId , null)); manyToManyDone.Add(relationship.SchemaName); } if (relationship.RecordType2 == thisType && (request.DuplicateManyToManyRelationshipSides || (!manyToManyDone.Contains(relationship.SchemaName)))) { allRelationship.Add(new RelationshipExport(relationship.SchemaName, relationship.RecordType2, relationship.RecordType1, relationship.IsCustomRelationship, relationship.RecordType2DisplayRelated, relationship.RecordType1DisplayRelated , relationship.Entity2IntersectAttribute, relationship.Entity1IntersectAttribute, RelationshipExport.RelationshipType.ManyToMany, relationship.RecordType2UseCustomLabel, relationship.RecordType1UseCustomLabel, relationship.RecordType2CustomLabel, relationship.RecordType1CustomLabel , relationship.RecordType2DisplayOrder, relationship.RecordType1DisplayOrder , relationship.MetadataId, null)); manyToManyDone.Add(relationship.SchemaName); } } catch (Exception ex) { response.AddResponseItem( new CustomisationExporterResponseItem("Error Exporting Relationship", relationship.SchemaName, ex)); } } if (request.IncludeOneToManyRelationships) { var oneTorelationships = Service.GetOneToManyRelationships(thisType); for (var j = 0; j < oneTorelationships.Count(); j++) { var relationship = oneTorelationships.ElementAt(j); try { var isCustomRelationship = Service.FieldExists(relationship.ReferencingAttribute, relationship.ReferencingEntity) && Service.GetFieldMetadata(relationship.ReferencingAttribute, relationship.ReferencingEntity).IsCustomField; allRelationship.Add(new RelationshipExport(relationship.SchemaName, relationship.ReferencedEntity, relationship.ReferencingEntity, isCustomRelationship, false, relationship.DisplayRelated , null, relationship.ReferencingAttribute, RelationshipExport.RelationshipType.OneToMany, false, relationship.IsCustomLabel, null, relationship.GetRelationshipLabel , 0, relationship.DisplayOrder, relationship.MetadataId, relationship.DeleteCascadeConfiguration)); } catch (Exception ex) { response.AddResponseItem( new CustomisationExporterResponseItem("Error Exporting Relationship", relationship.SchemaName, ex)); } } } } catch (Exception ex) { response.AddResponseItem(new CustomisationExporterResponseItem("Error Exporting Relationships", thisType, ex)); } } response.AddListToOutput("Relationships", allRelationship); } }
private void Load(string assemblyName) { var assemblyRecord = XrmRecordService.GetFirst(Entities.pluginassembly, Fields.pluginassembly_.name, assemblyName); if (assemblyRecord == null) { throw new NullReferenceException("Assembly Not Deployed"); } var pluginTypes = XrmRecordService.RetrieveAllAndClauses(Entities.plugintype, new[] { new Condition(Fields.plugintype_.pluginassemblyid, ConditionType.Equal, assemblyRecord.Id) }); if (!pluginTypes.Any()) { throw new NullReferenceException("Not Plugin Types Deployed For Assembly"); } SdkMessageStepsPre = XrmRecordService.RetrieveAllOrClauses(Entities.sdkmessageprocessingstep, pluginTypes.Select( pt => new Condition(Fields.sdkmessageprocessingstep_.plugintypeid, ConditionType.Equal, pt.Id))); var sdkMessageStepsWithFilter = SdkMessageStepsPre .Where(sms => sms.GetField(Fields.sdkmessageprocessingstep_.sdkmessagefilterid) != null); var filters = !sdkMessageStepsWithFilter.Any() ? new IRecord[0] : XrmRecordService.RetrieveAllOrClauses(Entities.sdkmessagefilter, sdkMessageStepsWithFilter.Select( sms => new Condition(Fields.sdkmessagefilter_.sdkmessagefilterid, ConditionType.Equal, sms.GetLookupId(Fields.sdkmessageprocessingstep_.sdkmessagefilterid)))); var preImages = SdkMessageStepsPre.Any() ? XrmRecordService.RetrieveAllOrClauses(Entities.sdkmessageprocessingstepimage, SdkMessageStepsPre.Select(m => new Condition(Fields.sdkmessageprocessingstepimage_.sdkmessageprocessingstepid, ConditionType.Equal, m.Id))) .Where(i => i.GetOptionKey(Fields.sdkmessageprocessingstepimage_.imagetype) == OptionSets.SdkMessageProcessingStepImage.ImageType.PreImage.ToString()) .GroupBy(i => i.GetLookupField(Fields.sdkmessageprocessingstepimage_.sdkmessageprocessingstepid)) .Where(g => g.Key != null && g.Key.Id != null) .ToDictionary(i => i.Key.Id, g => g.First()) : new Dictionary <string, IRecord>(); _entryObject = new PluginTriggers(); var triggers = new List <PluginTrigger>(); EntryObject.Triggers = triggers; EntryObject.Assembly = assemblyRecord.ToLookup(); foreach (var item in SdkMessageStepsPre) { var filterId = item.GetLookupId(Fields.sdkmessageprocessingstep_.sdkmessagefilterid); var matchingFilters = filters.Where(f => f.Id == filterId); var filter = matchingFilters.Any() ? matchingFilters.First() : null; var recordType = filter == null ? null : filter.GetStringField(Fields.sdkmessagefilter_.primaryobjecttypecode); RecordType recordTypeObj = null; try { recordTypeObj = new RecordType(recordType, XrmRecordService.GetDisplayName(recordType)); } catch (Exception) { } var rank = item.GetIntegerField(Fields.sdkmessageprocessingstep_.rank); var name = item.GetStringField(Fields.sdkmessageprocessingstep_.name); var stage = item.GetOptionKey(Fields.sdkmessageprocessingstep_.stage); var mode = item.GetOptionKey(Fields.sdkmessageprocessingstep_.mode); var filteringAttributesString = item.GetStringField(Fields.sdkmessageprocessingstep_.filteringattributes); var trigger = new PluginTrigger(); //load trigger details trigger.Id = item.Id; //for some unknown reason this field was setting the target type ot sdkmessage filter //despite the target being plugin type so I had to implement this to correct the type //the name is popuated after the loop trigger.Message = filter == null ? null : filter.GetLookupField(Fields.sdkmessagefilter_.sdkmessageid); item.SetField(Fields.sdkmessageprocessingstep_.plugintypeid, new Lookup(Entities.plugintype, item.GetLookupId(Fields.sdkmessageprocessingstep_.plugintypeid), null), XrmRecordService); trigger.Plugin = item.GetLookupField(Fields.sdkmessageprocessingstep_.plugintypeid); trigger.RecordType = recordTypeObj; trigger.Stage = stage.ParseEnum <PluginTrigger.PluginStage>(); trigger.Mode = mode.ParseEnum <PluginTrigger.PluginMode>(); trigger.Rank = rank; trigger.FilteringFields = filteringAttributesString == null ? new RecordField[0] : filteringAttributesString.Split(',') .Select(s => s.Trim()) .Where(s => !string.IsNullOrWhiteSpace(s)) .Select(s => new RecordField(s, s)) .ToArray(); trigger.SpecificUserContext = item.GetLookupField(Fields.sdkmessageprocessingstep_.impersonatinguserid); //load image details if there is one if (trigger.Id != null) { if (!preImages.ContainsKey(item.Id)) { trigger.PreImageAllFields = false; } else { var preImage = preImages[item.Id]; var attributes = preImage.GetStringField(Fields.sdkmessageprocessingstepimage_.attributes); trigger.PreImageAllFields = string.IsNullOrWhiteSpace(attributes); trigger.PreImageFields = attributes == null ? new RecordField[0] : attributes .Split(',') .Select(s => s.Trim()) .Where(s => !string.IsNullOrWhiteSpace(s)) .Select(s => new RecordField(s, s)) .ToArray(); trigger.PreImageName = preImage.GetStringField(Fields.sdkmessageprocessingstepimage_.entityalias); trigger.PreImageId = preImage.Id; } } triggers.Add(trigger); } //since I had to correct the target type for this fieldsw lookup need to populate the name if (triggers.Any()) { XrmRecordService.PopulateLookups(new Dictionary <string, List <Lookup> >() { { Fields.sdkmessageprocessingstep_.plugintypeid, triggers.Select(t => t.Plugin).ToList() } }, null); } }
private void LoadAssemblyDetails() { LoadingViewModel.LoadingMessage = "Loading Assembly"; Request.AssemblyName = VisualStudioService.GetSelectedProjectAssemblyName(); if (string.IsNullOrWhiteSpace(Request.AssemblyName)) { throw new NullReferenceException("Could Not Find Assembly Name"); } var assemblyRecord = XrmRecordService.GetFirst(Entities.pluginassembly, Fields.pluginassembly_.name, Request.AssemblyName); if (assemblyRecord == null) { throw new NullReferenceException("There is no plugin assembly deployed in the dynamics instance with a matching name. Try the deploy assembly option to deploy a new plugin assembly, or rename the assembly to match an existing assembly deployed to the instance"); } LoadingViewModel.LoadingMessage = "Loading Plugin Types"; var pluginTypes = XrmRecordService.RetrieveAllAndClauses(Entities.plugintype, new[] { new Condition(Fields.plugintype_.pluginassemblyid, ConditionType.Equal, assemblyRecord.Id) }); if (!pluginTypes.Any()) { throw new NullReferenceException("There No Plugin Types Deployed In This Assembly So No Triggers Can Be Created For Them"); } LoadingViewModel.LoadingMessage = "Loading Plugin Triggers"; Request.SetSdkMessageStepsPre(XrmRecordService.RetrieveAllOrClauses(Entities.sdkmessageprocessingstep, pluginTypes.Select( pt => new Condition(Fields.sdkmessageprocessingstep_.plugintypeid, ConditionType.Equal, pt.Id)))); var sdkMessageStepsWithFilter = Request.GetSdkMessageStepsPre() .Where(sms => sms.GetField(Fields.sdkmessageprocessingstep_.sdkmessagefilterid) != null); LoadingViewModel.LoadingMessage = "Loading Plugin Filters"; var filters = !sdkMessageStepsWithFilter.Any() ? new IRecord[0] : XrmRecordService.RetrieveAllOrClauses(Entities.sdkmessagefilter, sdkMessageStepsWithFilter.Select( sms => new Condition(Fields.sdkmessagefilter_.sdkmessagefilterid, ConditionType.Equal, sms.GetLookupId(Fields.sdkmessageprocessingstep_.sdkmessagefilterid)))); LoadingViewModel.LoadingMessage = "Loading Plugin Images"; var preImages = Request.GetSdkMessageStepsPre().Any() ? XrmRecordService.RetrieveAllOrClauses(Entities.sdkmessageprocessingstepimage, Request.GetSdkMessageStepsPre().Select(m => new Condition(Fields.sdkmessageprocessingstepimage_.sdkmessageprocessingstepid, ConditionType.Equal, m.Id))) .Where(i => i.GetOptionKey(Fields.sdkmessageprocessingstepimage_.imagetype) == OptionSets.SdkMessageProcessingStepImage.ImageType.PreImage.ToString()) .GroupBy(i => i.GetLookupField(Fields.sdkmessageprocessingstepimage_.sdkmessageprocessingstepid)) .Where(g => g.Key != null && g.Key.Id != null) .ToDictionary(i => i.Key.Id, g => g.First()) : new Dictionary <string, IRecord>(); var triggers = new List <PluginTrigger>(); foreach (var item in Request.GetSdkMessageStepsPre()) { var filterId = item.GetLookupId(Fields.sdkmessageprocessingstep_.sdkmessagefilterid); var matchingFilters = filters.Where(f => f.Id == filterId); var filter = matchingFilters.Any() ? matchingFilters.First() : null; var recordType = filter == null ? null : filter.GetStringField(Fields.sdkmessagefilter_.primaryobjecttypecode); RecordType recordTypeObj = null; if (recordType != null && recordType != "none") { try { recordTypeObj = new RecordType(recordType, XrmRecordService.GetDisplayName(recordType)); } catch (Exception) { } } var rank = item.GetIntegerField(Fields.sdkmessageprocessingstep_.rank); var name = item.GetStringField(Fields.sdkmessageprocessingstep_.name); var stage = item.GetOptionKey(Fields.sdkmessageprocessingstep_.stage); var mode = item.GetOptionKey(Fields.sdkmessageprocessingstep_.mode); var filteringAttributesString = item.GetStringField(Fields.sdkmessageprocessingstep_.filteringattributes); var trigger = new PluginTrigger(); //load trigger details trigger.Id = item.Id; //for some unknown reason this field was setting the target type ot sdkmessage filter //despite the target being plugin type so I had to implement this to correct the type //the name is popuated after the loop trigger.Message = item.GetField(Fields.sdkmessageprocessingstep_.sdkmessageid) as Lookup;// filter == null ? null : filter.GetLookupField(Fields.sdkmessagefilter_.sdkmessageid); item.SetField(Fields.sdkmessageprocessingstep_.plugintypeid, new Lookup(Entities.plugintype, item.GetLookupId(Fields.sdkmessageprocessingstep_.plugintypeid), null), XrmRecordService); trigger.Plugin = item.GetLookupField(Fields.sdkmessageprocessingstep_.plugintypeid); trigger.RecordType = recordTypeObj; trigger.Stage = stage.ParseEnum <PluginTrigger.PluginStage>(); trigger.Mode = mode.ParseEnum <PluginTrigger.PluginMode>(); trigger.Rank = rank; trigger.FilteringFields = filteringAttributesString == null ? new RecordField[0] : filteringAttributesString.Split(',') .Select(s => s.Trim()) .Where(s => !string.IsNullOrWhiteSpace(s)) .Select(s => new RecordField(s, XrmRecordService.GetFieldLabel(s, recordType))) .ToArray(); trigger.SpecificUserContext = item.GetLookupField(Fields.sdkmessageprocessingstep_.impersonatinguserid); //load image details if there is one if (trigger.Id != null) { if (!preImages.ContainsKey(item.Id)) { trigger.PreImageAllFields = false; } else { var preImage = preImages[item.Id]; var attributes = preImage.GetStringField(Fields.sdkmessageprocessingstepimage_.attributes); trigger.PreImageAllFields = string.IsNullOrWhiteSpace(attributes); trigger.PreImageFields = attributes == null ? new RecordField[0] : attributes .Split(',') .Select(s => s.Trim()) .Where(s => !string.IsNullOrWhiteSpace(s)) .Select(s => new RecordField(s, XrmRecordService.GetFieldLabel(s, recordType))) .ToArray(); trigger.PreImageName = preImage.GetStringField(Fields.sdkmessageprocessingstepimage_.entityalias); trigger.PreImageId = preImage.Id; trigger.PreImageIdUnique = preImage.GetField(Fields.sdkmessageprocessingstepimage_.sdkmessageprocessingstepimageidunique)?.ToString(); } } triggers.Add(trigger); } LoadingViewModel.LoadingMessage = "Loading Plugin Names"; //since I had to correct the target type for this fields lookup need to populate the name if (triggers.Any()) { XrmRecordService.PopulateLookups(new Dictionary <string, List <Lookup> >() { { Fields.sdkmessageprocessingstep_.plugintypeid, triggers.Select(t => t.Plugin).ToList() } }, null); } triggers = triggers .OrderBy(t => t.RecordType?.Value) .ThenBy(t => t.Message?.Name) .ThenByDescending(t => t.Stage) .ThenByDescending(t => t.Mode).ToList(); Request.Triggers = triggers; Request.Assembly = assemblyRecord.ToLookup(); LoadingViewModel.LoadingMessage = "Loading Plugins Into Grid"; }