Skip to content

Commit 84ee90d

Browse files
committed
Fix Writing Delta Responses
-only write properties in deltaset items that have been set -support writing additional properties for deleted entities -nested resource sets that aren't deltasets should be written w/o @delta -factored out ODataDeletedResourceSerializer -support writing delta payloads w/out knowing navigation source (i.e., when serializing results from a function)
1 parent 3813ee7 commit 84ee90d

File tree

8 files changed

+642
-121
lines changed

8 files changed

+642
-121
lines changed

src/Microsoft.AspNetCore.OData/Formatter/Serialization/ODataDeletedResourceSerializer.cs

+432
Large diffs are not rendered by default.

src/Microsoft.AspNetCore.OData/Formatter/Serialization/ODataDeltaResourceSetSerializer.cs

+43-8
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System;
99
using System.Collections;
1010
using System.Diagnostics.Contracts;
11+
using System.Reflection;
1112
using System.Runtime.Serialization;
1213
using System.Threading.Tasks;
1314
using Microsoft.AspNetCore.OData.Abstracts;
@@ -56,10 +57,6 @@ public override async Task WriteObjectAsync(object graph, Type type, ODataMessag
5657
}
5758

5859
IEdmEntitySetBase entitySet = writeContext.NavigationSource as IEdmEntitySetBase;
59-
if (entitySet == null)
60-
{
61-
throw new SerializationException(SRResources.EntitySetMissingDuringSerialization);
62-
}
6360

6461
IEdmTypeReference feedType = writeContext.GetEdmType(graph, type);
6562
Contract.Assert(feedType != null);
@@ -162,11 +159,19 @@ private async Task WriteDeltaResourceSetAsync(IEnumerable enumerable, IEdmTypeRe
162159
}
163160

164161
lastResource = item;
165-
DeltaItemKind kind = GetDelteItemKind(item);
162+
DeltaItemKind kind = GetDeltaItemKind(item);
166163
switch (kind)
167164
{
168165
case DeltaItemKind.DeletedResource:
169-
await WriteDeltaDeletedResourceAsync(item, writer, writeContext).ConfigureAwait(false);
166+
// hack. if the WriteDeltaDeletedResourceAsync isn't overridden, call the new version
167+
if (WriteDeltaDeletedResourceAsyncIsOverridden())
168+
{
169+
await WriteDeltaDeletedResourceAsync(item, writer, writeContext).ConfigureAwait(false);
170+
}
171+
else
172+
{
173+
await WriteDeletedResourceAsync(item, elementType, writer, writeContext).ConfigureAwait(false);
174+
}
170175
break;
171176
case DeltaItemKind.DeltaDeletedLink:
172177
await WriteDeltaDeletedLinkAsync(item, writer, writeContext).ConfigureAwait(false);
@@ -212,7 +217,7 @@ await entrySerializer.WriteDeltaObjectInlineAsync(item, elementType, writer, wri
212217
/// <param name="writeContext">The serializer context.</param>
213218
/// <returns>The function that generates the NextLink from an object.</returns>
214219
/// <returns></returns>
215-
internal static Func<object, Uri> GetNextLinkGenerator(ODataDeltaResourceSet deltaResourceSet, IEnumerable enumerable, ODataSerializerContext writeContext)
220+
internal static Func<object, Uri> GetNextLinkGenerator(ODataResourceSetBase deltaResourceSet, IEnumerable enumerable, ODataSerializerContext writeContext)
216221
{
217222
return ODataResourceSetSerializer.GetNextLinkGenerator(deltaResourceSet, enumerable, writeContext);
218223
}
@@ -266,6 +271,8 @@ public virtual ODataDeltaResourceSet CreateODataDeltaResourceSet(IEnumerable fee
266271
/// <param name="value">The object to be written.</param>
267272
/// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param>
268273
/// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param>
274+
[Obsolete("WriteDeltaDeletedResourceAsync(object, ODataWriter, ODataSerializerContext) is Deprecated and will be removed in the next version." +
275+
"Please use WriteDeletedResourceAsync(object, IEdmEntityTypeReference, ODataWriter, ODataSerializerContext)")]
269276
public virtual async Task WriteDeltaDeletedResourceAsync(object value, ODataWriter writer, ODataSerializerContext writeContext)
270277
{
271278
if (writer == null)
@@ -304,6 +311,27 @@ public virtual async Task WriteDeltaDeletedResourceAsync(object value, ODataWrit
304311
}
305312
}
306313

314+
/// <summary>
315+
/// Writes the given deltaDeletedEntry specified by the parameter graph as a part of an existing OData message using the given
316+
/// messageWriter and the writeContext.
317+
/// </summary>
318+
/// <param name="value">The object to be written.</param>
319+
/// <param name="expectedType">The expected type of the deleted resource.</param>
320+
/// <param name="writer">The <see cref="ODataDeltaWriter" /> to be used for writing.</param>
321+
/// <param name="writeContext">The <see cref="ODataSerializerContext"/>.</param>
322+
public virtual async Task WriteDeletedResourceAsync(object value, IEdmStructuredTypeReference expectedType, ODataWriter writer, ODataSerializerContext writeContext)
323+
{
324+
if (writer == null)
325+
{
326+
throw Error.ArgumentNull(nameof(writer));
327+
}
328+
329+
//todo:use serializer provider
330+
ODataDeletedResourceSerializer deletedResourceSerializer = new ODataDeletedResourceSerializer(SerializerProvider);
331+
332+
await deletedResourceSerializer.WriteObjectInlineAsync(value, expectedType, writer, writeContext);
333+
}
334+
307335
/// <summary>
308336
/// Writes the given deltaDeletedLink specified by the parameter graph as a part of an existing OData message using the given
309337
/// messageWriter and the writeContext.
@@ -382,7 +410,7 @@ public virtual async Task WriteDeltaLinkAsync(object value, ODataWriter writer,
382410
}
383411
}
384412

385-
internal DeltaItemKind GetDelteItemKind(object item)
413+
internal DeltaItemKind GetDeltaItemKind(object item)
386414
{
387415
IEdmChangedObject edmChangedObject = item as IEdmChangedObject;
388416
if (edmChangedObject != null)
@@ -414,4 +442,11 @@ private static IEdmStructuredTypeReference GetResourceType(IEdmTypeReference fee
414442
string message = Error.Format(SRResources.CannotWriteType, typeof(ODataDeltaResourceSetSerializer).Name, feedType.FullName());
415443
throw new SerializationException(message);
416444
}
445+
446+
private bool WriteDeltaDeletedResourceAsyncIsOverridden()
447+
{
448+
MethodInfo method = GetType().GetMethod("WriteDeltaDeletedResourceAsync", new Type[] { typeof(object), typeof(ODataWriter), typeof(ODataSerializerContext) });
449+
Contract.Assert(method != null, "WriteDeltaDeletedResourceAsync is not defined.");
450+
return method.DeclaringType != typeof(ODataDeltaResourceSetSerializer);
451+
}
417452
}

0 commit comments

Comments
 (0)