diff --git a/src/XrmMockupShared/Core.cs b/src/XrmMockupShared/Core.cs index 3bb36351..b88e5a5e 100644 --- a/src/XrmMockupShared/Core.cs +++ b/src/XrmMockupShared/Core.cs @@ -673,6 +673,10 @@ internal OrganizationResponse Execute(OrganizationRequest request, EntityReferen pluginContext.OutputParameters["BusinessEntityCollection"] = (response as RetrieveMultipleResponse)?.EntityCollection; } + else if (request is RetrieveRequest) + { + pluginContext.OutputParameters["BusinessEntity"] = TryRetrieve((request as RetrieveRequest).Target); + } if (!string.IsNullOrEmpty(eventOp)) { diff --git a/src/XrmMockupShared/Mappings.cs b/src/XrmMockupShared/Mappings.cs index dfb4ffe9..513d8602 100644 --- a/src/XrmMockupShared/Mappings.cs +++ b/src/XrmMockupShared/Mappings.cs @@ -24,6 +24,7 @@ internal static partial class Mappings { { typeof(UpdateRequest), "Target" }, { typeof(AssociateRequest), "Target" }, { typeof(DisassociateRequest), "Target" }, + { typeof(RetrieveRequest), "Target" }, }; public static Dictionary RequestToEventOperation = new Dictionary() diff --git a/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs b/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs index 7d927525..9bc4a48d 100644 --- a/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs +++ b/src/XrmMockupShared/Requests/RetrieveMultipleRequestHandler.cs @@ -157,6 +157,12 @@ internal override OrganizationResponse Execute(OrganizationRequest orgRequest, E colToReturn = new EntityCollection(collection.Select(x=>x.Value).ToList()); } + if (queryExpr.Distinct) + { + var uniqueIds = new HashSet(); + colToReturn = new EntityCollection(colToReturn.Entities.Where(entity => uniqueIds.Add(entity.Id)).ToList()); + } + // According to docs, should return -1 if ReturnTotalRecordCount set to false colToReturn.TotalRecordCount = queryExpr.PageInfo.ReturnTotalRecordCount ? colToReturn.Entities.Count : -1; diff --git a/tests/SharedPluginsAndCodeactivites/RetrievePlugin.cs b/tests/SharedPluginsAndCodeactivites/RetrievePlugin.cs new file mode 100644 index 00000000..740bcdda --- /dev/null +++ b/tests/SharedPluginsAndCodeactivites/RetrievePlugin.cs @@ -0,0 +1,27 @@ +using DG.XrmFramework.BusinessDomain.ServiceContext; +using Microsoft.Xrm.Sdk; + + +namespace DG.Some.Namespace +{ + public class RetrievePlugin : Plugin + { + public RetrievePlugin() : base(typeof(RetrievePlugin)) + { + RegisterPluginStep( + EventOperation.Retrieve, + ExecutionStage.PostOperation, + ExecutePostRetrieve); + } + + protected void ExecutePostRetrieve(LocalPluginContext localContext) + { + var entity = localContext.PluginExecutionContext.OutputParameters["BusinessEntity"] as Entity; + + if (entity.ToEntity().StateCode == ContactState.Inactive) + { + throw new InvalidPluginExecutionException("Inactive contacts cannot be retrieved."); + } + } + } +} diff --git a/tests/SharedPluginsAndCodeactivites/SharedPluginsAndCodeactivites.projitems b/tests/SharedPluginsAndCodeactivites/SharedPluginsAndCodeactivites.projitems index 11c7fc45..c351cbf6 100644 --- a/tests/SharedPluginsAndCodeactivites/SharedPluginsAndCodeactivites.projitems +++ b/tests/SharedPluginsAndCodeactivites/SharedPluginsAndCodeactivites.projitems @@ -17,6 +17,7 @@ + diff --git a/tests/SharedTests/TestRetrieve.cs b/tests/SharedTests/TestRetrieve.cs index fedd028f..5fcb4b3c 100644 --- a/tests/SharedTests/TestRetrieve.cs +++ b/tests/SharedTests/TestRetrieve.cs @@ -301,5 +301,19 @@ public void TestRetrieveUserByFullName() var users = orgAdminService.RetrieveMultiple(q); Assert.Single(users.Entities); } + + [Fact] + public void TestRetrievePlugin() + { + var accountId = orgAdminService.Create(new Contact { LastName = "Test" }); + + orgAdminUIService.Update(new Contact(accountId) + { + StateCode = ContactState.Inactive, + StatusCode = Contact_StatusCode.Inactive + }); + + Assert.Throws(() => Contact.Retrieve(orgAdminService, accountId, x => x.LastName)); + } } } diff --git a/tests/SharedTests/TestRetrieveMultiple.cs b/tests/SharedTests/TestRetrieveMultiple.cs index 76fae032..e0d3b249 100644 --- a/tests/SharedTests/TestRetrieveMultiple.cs +++ b/tests/SharedTests/TestRetrieveMultiple.cs @@ -773,6 +773,44 @@ public void TestQueryExpressionLinkEntityNoSetEntityName() Assert.Equal(2, res.Count()); } + [Fact] + public void RetrieveMultipleWithLinkEntitiesReturnDistinctResults() + { + var lead = new Lead() + { + Subject = "Lead", + ParentContactId = contact1.ToEntityReference() + }; + orgAdminService.Create(lead); + + var linkEntity = new LinkEntity + { + LinkToEntityName = "lead", + LinkToAttributeName = "parentcontactid", + LinkFromEntityName = "contact", + LinkFromAttributeName = "contactid", + Columns = new ColumnSet(false), + EntityAlias = "contact", + JoinOperator = JoinOperator.LeftOuter, + }; + + var filter = new FilterExpression(LogicalOperator.And); + filter.AddCondition(new ConditionExpression("lastname", ConditionOperator.Equal, contact1.LastName)); + + var query = new QueryExpression("contact") + { + Distinct = true, + ColumnSet = new ColumnSet(), + LinkEntities = { linkEntity } + }; + + var res = orgAdminService.RetrieveMultiple(query).Entities; + + var distinctIdCount = res.Select(x => x.Id).Distinct().Count(); + + Assert.Equal(distinctIdCount, res.Count); + } + #endif [Fact] @@ -921,5 +959,16 @@ public void TestCaseSensitivity() Assert.Equal("MATT", res.Entities.Single().GetAttributeValue("firstname")); } + + [Fact] + public void TestRetrieveMultipleFailWithNonExistentAttribute() + { + var query = new QueryExpression("contact") + { + ColumnSet = new ColumnSet("x") + }; + + Assert.Throws(() => orgAdminService.RetrieveMultiple(query)); + } } }