diff --git a/XrmEntitySerializer.Tests/RemoteExecutionContextTests.cs b/XrmEntitySerializer.Tests/RemoteExecutionContextTests.cs index 7b73cd3..f20339f 100644 --- a/XrmEntitySerializer.Tests/RemoteExecutionContextTests.cs +++ b/XrmEntitySerializer.Tests/RemoteExecutionContextTests.cs @@ -34,5 +34,28 @@ public void RemoteExecutionContextCanBeSerializedAndDeserialized() Assert.Equal(((Entity)executionContext.InputParameters["Target"]).LogicalName, ((Entity)deserializedExecutionContext.InputParameters["Target"]).LogicalName); } + + [Fact] + public void RemoteExecutionContextCanBeDeserializedFromAzureServiceBusMessage() + { + var input = "{ \"BusinessUnitId\": \"f0bf3c9a-8150-e811-a953-000d3af29fc0\", \"CorrelationId\": \"39499111-e689-42a1-ae8a-5b14a84514ce\", \"Depth\": 1, \"InitiatingUserId\": \"df010dad-f103-4589-ba66-76a5a04c2a11\", \"InputParameters\": [ { \"key\": \"Target\", \"value\": { \"__type\": \"Entity:http:\\/\\/schemas.microsoft.com\\/xrm\\/2011\\/Contracts\", \"Attributes\": [ { \"key\": \"telephone1\", \"value\": \"1111\" }, { \"key\": \"accountid\", \"value\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\" }, { \"key\": \"modifiedon\", \"value\": \"\\/Date(1527757524000)\\/\" }, { \"key\": \"modifiedby\", \"value\": { \"__type\": \"EntityReference:http:\\/\\/schemas.microsoft.com\\/xrm\\/2011\\/Contracts\", \"Id\": \"df010dad-f103-4589-ba66-76a5a04c2a11\", \"KeyAttributes\": [], \"LogicalName\": \"systemuser\", \"Name\": null, \"RowVersion\": null } }, { \"key\": \"modifiedonbehalfby\", \"value\": null } ], \"EntityState\": null, \"FormattedValues\": [], \"Id\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\", \"KeyAttributes\": [], \"LogicalName\": \"account\", \"RelatedEntities\": [], \"RowVersion\": null } } ], \"IsExecutingOffline\": false, \"IsInTransaction\": true, \"IsOfflinePlayback\": false, \"IsolationMode\": 1, \"MessageName\": \"Update\", \"Mode\": 0, \"OperationCreatedOn\": \"\\/Date(1527757530151)\\/\", \"OperationId\": \"08fec203-ec78-4f7a-a024-c96e329a64fe\", \"OrganizationId\": \"b0714265-8e72-4d3b-8239-ecf0970a3da6\", \"OrganizationName\": \"org94971a24\", \"OutputParameters\": [], \"OwningExtension\": { \"Id\": \"3db800fe-0963-e811-a95a-000d3af24324\", \"KeyAttributes\": [], \"LogicalName\": \"sdkmessageprocessingstep\", \"Name\": \"D365WebHookHttpTrigger: Update of account\", \"RowVersion\": null }, \"ParentContext\": { \"BusinessUnitId\": \"f0bf3c9a-8150-e811-a953-000d3af29fc0\", \"CorrelationId\": \"39499111-e689-42a1-ae8a-5b14a84514ce\", \"Depth\": 1, \"InitiatingUserId\": \"df010dad-f103-4589-ba66-76a5a04c2a11\", \"InputParameters\": [ { \"key\": \"Target\", \"value\": { \"__type\": \"Entity:http:\\/\\/schemas.microsoft.com\\/xrm\\/2011\\/Contracts\", \"Attributes\": [ { \"key\": \"telephone1\", \"value\": \"1111\" }, { \"key\": \"accountid\", \"value\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\" } ], \"EntityState\": null, \"FormattedValues\": [], \"Id\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\", \"KeyAttributes\": [], \"LogicalName\": \"account\", \"RelatedEntities\": [], \"RowVersion\": null } }, { \"key\": \"SuppressDuplicateDetection\", \"value\": false } ], \"IsExecutingOffline\": false, \"IsInTransaction\": true, \"IsOfflinePlayback\": false, \"IsolationMode\": 1, \"MessageName\": \"Update\", \"Mode\": 0, \"OperationCreatedOn\": \"\\/Date(1527757524631)\\/\", \"OperationId\": \"08fec203-ec78-4f7a-a024-c96e329a64fe\", \"OrganizationId\": \"b0714265-8e72-4d3b-8239-ecf0970a3da6\", \"OrganizationName\": \"org94971a24\", \"OutputParameters\": [], \"OwningExtension\": { \"Id\": \"63cdbb1b-ea3e-db11-86a7-000a3a5473e8\", \"KeyAttributes\": [], \"LogicalName\": \"sdkmessageprocessingstep\", \"Name\": \"ObjectModel Implementation\", \"RowVersion\": null }, \"ParentContext\": null, \"PostEntityImages\": [], \"PreEntityImages\": [], \"PrimaryEntityId\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\", \"PrimaryEntityName\": \"account\", \"RequestId\": \"08fec203-ec78-4f7a-a024-c96e329a64fe\", \"SecondaryEntityName\": \"none\", \"SharedVariables\": [ { \"key\": \"ChangedEntityTypes\", \"value\": [ { \"__type\": \"KeyValuePairOfstringstring:#System.Collections.Generic\", \"key\": \"account\", \"value\": \"Update\" } ] } ], \"Stage\": 30, \"UserId\": \"df010dad-f103-4589-ba66-76a5a04c2a11\" }, \"PostEntityImages\": [], \"PreEntityImages\": [], \"PrimaryEntityId\": \"ec4e2f7d-9d60-e811-a95a-000d3af24950\", \"PrimaryEntityName\": \"account\", \"RequestId\": \"08fec203-ec78-4f7a-a024-c96e329a64fe\", \"SecondaryEntityName\": \"none\", \"SharedVariables\": [], \"Stage\": 40, \"UserId\": \"df010dad-f103-4589-ba66-76a5a04c2a11\"}"; + + EntitySerializer serializer = new EntitySerializer(); + MemoryStream memoryStream = new MemoryStream(new byte[9000], true); + + using (StreamWriter writer = new StreamWriter(memoryStream)) + { + writer.Write(input); + } + + RemoteExecutionContext deserializedExecutionContext; + memoryStream = new MemoryStream(memoryStream.ToArray()); + using (StreamReader reader = new StreamReader(memoryStream)) + { + deserializedExecutionContext = (RemoteExecutionContext)serializer.Deserialize(new JsonTextReader(reader), typeof(RemoteExecutionContext)); + } + + Assert.Equal("account", ((Entity)deserializedExecutionContext.InputParameters["Target"]).LogicalName); + } } } diff --git a/XrmEntitySerializer/CollectionTypeConverter.cs b/XrmEntitySerializer/CollectionTypeConverter.cs index a8d1c38..c907dde 100644 --- a/XrmEntitySerializer/CollectionTypeConverter.cs +++ b/XrmEntitySerializer/CollectionTypeConverter.cs @@ -24,7 +24,6 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist JArray jArray = JArray.Load(reader); result = ReadCollection(reader, objectType, (T)existingValue, serializer, jArray); } - else { for (int i = 0; i < 2; i++) diff --git a/XrmEntitySerializer/DecimalConverter.cs b/XrmEntitySerializer/DecimalConverter.cs index fb99612..16ed11f 100644 --- a/XrmEntitySerializer/DecimalConverter.cs +++ b/XrmEntitySerializer/DecimalConverter.cs @@ -34,7 +34,7 @@ protected override object ReadValue(JsonReader reader, Type objectType, object e } else if (!decimal.TryParse(reader.Value.ToString(), out result)) { - throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, "Unexpected token or value when parsing Guid. Token: {0}, Value: {1}", reader.TokenType, reader.Value)); + throw new JsonSerializationException(string.Format(CultureInfo.InvariantCulture, "Unexpected token or value when parsing Decimal. Token: {0}, Value: {1}", reader.TokenType, reader.Value)); } return result; } diff --git a/XrmEntitySerializer/ParameterCollectionConverter.cs b/XrmEntitySerializer/ParameterCollectionConverter.cs index caf24a5..a9e235f 100644 --- a/XrmEntitySerializer/ParameterCollectionConverter.cs +++ b/XrmEntitySerializer/ParameterCollectionConverter.cs @@ -16,7 +16,23 @@ protected override ParameterCollection ReadCollection(JsonReader reader, Type ob } foreach (JToken item in jArray) { - KeyValuePair pair = item.ToObject>(serializer); + var value = item.SelectToken("value"); + KeyValuePair pair; + if (value?.SelectToken("__type")?.ToString()?.StartsWith("Entity:") == true) + { + var deserialized = item.ToObject>(serializer); + pair = new KeyValuePair(deserialized.Key, deserialized.Value); + } + else if (value?.SelectToken("__type")?.ToString()?.StartsWith("EntityReference:") == true) + { + var deserialized = item.ToObject>(serializer); + pair = new KeyValuePair(deserialized.Key, deserialized.Value); + } + else + { + pair = item.ToObject>(serializer); + } + existingParameters.Add(pair.Key, pair.Value); } return existingParameters; diff --git a/XrmEntitySerializer/ValueTypeConverter.cs b/XrmEntitySerializer/ValueTypeConverter.cs index 266cd67..65fc2d5 100644 --- a/XrmEntitySerializer/ValueTypeConverter.cs +++ b/XrmEntitySerializer/ValueTypeConverter.cs @@ -19,6 +19,11 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist object result = null; bool parsed = false; + if (reader.TokenType == JsonToken.String) + { + return ReadValue(reader, objectType, existingValue, serializer); + } + for (int i = 0; i < 2; i++) { reader.Read(); @@ -28,7 +33,7 @@ public override object ReadJson(JsonReader reader, Type objectType, object exist reader.Read(); result = ReadValue(reader, objectType, existingValue, serializer); parsed = true; - } + } else { reader.Read();