Skip to content

Commit f83634d

Browse files
authored
fixes #931: Undeclared enum type value for untype value serialized as empty resource (#961)
* fixes #931: Undeclared enum type value for untype value serialized as empty resource * Update the comments.
1 parent 1d63aba commit f83634d

File tree

3 files changed

+76
-3
lines changed

3 files changed

+76
-3
lines changed

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

Lines changed: 34 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,7 @@ public virtual void AppendDynamicProperties(ODataResource resource, SelectExpand
638638

639639
IEdmStructuredType structuredType = resourceContext.StructuredType;
640640
IEdmStructuredObject structuredObject = resourceContext.EdmObject;
641+
ODataSerializerContext serializierContext = resourceContext.SerializerContext;
641642
object value;
642643
IDelta delta = structuredObject as IDelta;
643644
if (structuredObject is EdmUntypedObject untypedObject) // NO CLR, NO EDM
@@ -700,10 +701,25 @@ public virtual void AppendDynamicProperties(ODataResource resource, SelectExpand
700701
continue;
701702
}
702703

703-
IEdmTypeReference edmTypeReference = resourceContext.SerializerContext.GetEdmType(dynamicPropertyValue,
704-
dynamicPropertyValue.GetType(), true);
704+
Type propertyType = dynamicPropertyValue.GetType();
705+
IEdmTypeReference edmTypeReference = serializierContext.GetEdmType(dynamicPropertyValue, propertyType, true);
705706
if (edmTypeReference == null || edmTypeReference.IsStructuredOrUntyped())
706707
{
708+
if (TypeHelper.IsEnum(propertyType))
709+
{
710+
// we don't have the Edm enum type in the model, let's write it as string.
711+
dynamicProperties.Add(new ODataProperty
712+
{
713+
Name = dynamicProperty.Key,
714+
715+
// TBD: Shall we write the un-declared enum value as full-name string?
716+
// So, "Data":"Apple" => should be ""Data":"Namespace.EnumTypeName.Apple" ?
717+
Value = dynamicPropertyValue.ToString()
718+
});
719+
720+
continue;
721+
}
722+
707723
resourceContext.AppendDynamicOrUntypedProperty(dynamicProperty.Key, dynamicPropertyValue);
708724
}
709725
else
@@ -716,7 +732,7 @@ public virtual void AppendDynamicProperties(ODataResource resource, SelectExpand
716732
}
717733

718734
dynamicProperties.Add(propertySerializer.CreateProperty(
719-
dynamicPropertyValue, edmTypeReference, dynamicProperty.Key, resourceContext.SerializerContext));
735+
dynamicPropertyValue, edmTypeReference, dynamicProperty.Key, serializierContext));
720736
}
721737
}
722738

@@ -1388,8 +1404,23 @@ public virtual object CreateUntypedPropertyValue(IEdmStructuralProperty structur
13881404
// 1) If we can get EdmType from model, Let's use it.
13891405
// 2) If no (aka, we don't have an Edm type associated). So, let's treat it a Untyped.
13901406
actualType = writeContext.GetEdmType(propertyValue, propertyType, true);
1407+
13911408
if (actualType.IsStructuredOrUntyped())
13921409
{
1410+
if (TypeHelper.IsEnum(propertyType))
1411+
{
1412+
// we don't have the Edm enum type in the model, let's write it as string.
1413+
return new ODataProperty
1414+
{
1415+
Name = structuralProperty.Name,
1416+
1417+
// Shall we write the un-declared enum value as full-name string?
1418+
// So, "Data":"Apple" => should be ""Data":"Namespace.EnumTypeName.Apple" ?
1419+
// We keep it simple to write it as string (enum member name), not the full-name string.
1420+
Value = propertyValue.ToString()
1421+
};
1422+
}
1423+
13931424
return propertyValue;
13941425
}
13951426

test/Microsoft.AspNetCore.OData.E2E.Tests/Untyped/UntypedDataSource.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ public static IList<InModelPerson> GetAllPeople()
9898
}
9999
},
100100

101+
// not in model enum
102+
new InModelPerson
103+
{
104+
Id = 22, // special Id number
105+
Name = "Yin",
106+
Data = NotInModelEnum.Apple,
107+
Infos = new object[] { InModelColor.Blue, InModelColor.Green, NotInModelEnum.Apple },
108+
Containers = new Dictionary<string, object>
109+
{
110+
{ "EnumDynamic1", InModelColor.Blue },
111+
{ "EnumDynamic2", NotInModelEnum.Apple },
112+
}
113+
},
114+
101115
// In model complex
102116
new InModelPerson
103117
{

test/Microsoft.AspNetCore.OData.E2E.Tests/Untyped/UntypedTests.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,34 @@ public async Task QuerySinglePeople_OnDeclaredUntypedProperty(string request, st
324324
Assert.Equal(expected, payloadBody);
325325
}
326326

327+
[Fact]
328+
public async Task QuerySinglePeople_WithDeclaredOrUndeclaredEnum_OnUntypedAndDynamicProperty()
329+
{
330+
// Arrange
331+
HttpClient client = CreateClient();
332+
333+
// Act
334+
HttpResponseMessage response = await client.GetAsync("odata/people/22");
335+
336+
// Assert
337+
Assert.NotNull(response);
338+
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
339+
Assert.NotNull(response.Content);
340+
341+
string payloadBody = await response.Content.ReadAsStringAsync();
342+
343+
Assert.Equal("{\"@odata.context\":\"http://localhost/odata/$metadata#People/$entity\"," +
344+
"\"Id\":22," +
345+
"\"Name\":\"Yin\"," +
346+
"\"[email protected]\":\"#Microsoft.AspNetCore.OData.E2E.Tests.Untyped.InModelColor\"," +
347+
"\"EnumDynamic1\":\"Blue\"," +
348+
"\"EnumDynamic2\":\"Apple\"," +
349+
"\"[email protected]\":\"#String\"," +
350+
"\"Data\":\"Apple\"," +
351+
"\"Infos\":[\"Blue\",\"Green\",\"Apple\"]" +
352+
"}", payloadBody);
353+
}
354+
327355
[Fact]
328356
public async Task QuerySinglePeople_WithCollectionInCollection_OnDeclaredUntypedProperty()
329357
{

0 commit comments

Comments
 (0)