-
Notifications
You must be signed in to change notification settings - Fork 351
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
POC for writing instance annotations and odata.count for expanded resource sets #2194
base: release-7.x
Are you sure you want to change the base?
Changes from 3 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,9 @@ namespace Microsoft.OData | |
{ | ||
#region Namespaces | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Diagnostics.CodeAnalysis; | ||
using Microsoft.OData.Evaluation; | ||
#endregion Namespaces | ||
|
||
|
@@ -92,6 +94,24 @@ public Uri AssociationLinkUrl | |
} | ||
} | ||
|
||
/// <summary>Gets or sets the number of items in the resource set.</summary> | ||
/// <returns>The number of items in the resource set.</returns> | ||
public long? Count | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. what about if the nested resource info is single? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have added a validation! |
||
{ | ||
get; | ||
set; | ||
} | ||
|
||
/// <summary> | ||
/// Collection of custom instance annotations. | ||
/// </summary> | ||
[SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "We want to allow the same instance annotation collection instance to be shared across ODataLib OM instances.")] | ||
public ICollection<ODataInstanceAnnotation> InstanceAnnotations | ||
{ | ||
get { return this.GetInstanceAnnotations(); } | ||
set { this.SetInstanceAnnotations(value); } | ||
} | ||
|
||
/// <summary>Gets or sets the context url for this nested resource info.</summary> | ||
/// <returns>The URI representing the context url of the nested resource info.</returns> | ||
internal Uri ContextUrl { get; set; } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -555,6 +555,40 @@ private void WriteAnnotationAtEndExpandedFeedShouldFail(ODataFormat format) | |
testRequestOfSingleton.Throws<ODataException>(Strings.ODataJsonLightWriter_InstanceAnnotationNotSupportedOnExpandedResourceSet); | ||
} | ||
|
||
[Fact] | ||
public void WriteAnnotationAndCountAtStartExpandedFeedShouldPassInJsonLight() | ||
{ | ||
string expectedPayload = | ||
"{" + | ||
"\"@odata.context\":\"http://www.example.com/$metadata#TestEntitySet/$entity\"," + | ||
"\"ID\":1," + | ||
"\"[email protected]\":\"http://service/navLink\"," + | ||
"\"[email protected]\":10," + | ||
"\"[email protected]\":123" + | ||
"}"; | ||
|
||
this.WriteAnnotationAndCountAtStartExpandedFeedShouldPass(ODataFormat.Json, expectedPayload, EntitySet); | ||
} | ||
|
||
private void WriteAnnotationAndCountAtStartExpandedFeedShouldPass(ODataFormat format, string expectedPayload, IEdmNavigationSource navigationSource) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
{ | ||
Action<ODataWriter> action = (odataWriter) => | ||
{ | ||
var entryToWrite = new ODataResource { Properties = new[] { new ODataProperty { Name = "ID", Value = 1 } } }; | ||
odataWriter.WriteStart(entryToWrite); | ||
|
||
ODataNestedResourceInfo navLink = new ODataNestedResourceInfo { Name = "ResourceSetNavigationProperty", Url = new Uri("http://service/navLink", UriKind.RelativeOrAbsolute), IsCollection = true }; | ||
navLink.Count = 10; | ||
navLink.InstanceAnnotations.Add(new ODataInstanceAnnotation("custom.StartFeedAnnotation", PrimitiveValue1)); | ||
odataWriter.WriteStart(navLink); | ||
|
||
odataWriter.WriteEnd(); | ||
odataWriter.WriteEnd(); | ||
}; | ||
|
||
this.WriteAnnotationsAndValidatePayload(action, navigationSource, format, expectedPayload, request: false, createFeedWriter: false); | ||
} | ||
|
||
#endregion Writing instance annotations on expanded feeds | ||
|
||
#region Write Delta Feed | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -89,6 +89,20 @@ static CustomInstanceAnnotationAcceptanceTests() | |
"\"@Custom.FeedEndAnnotation\":1" + | ||
"}"; | ||
|
||
const string JsonLightExpandedResourceSetPayloadWithCountAndCustomInstanceAnnotations = | ||
"{" + | ||
"\"@odata.context\":\"http://www.example.com/service.svc/$metadata#TestEntitySet\"," + | ||
"\"value\":[" + | ||
"{" + | ||
"\"ID\":1," + | ||
"\"[email protected]\":\"http://example.com/multiple\"," + | ||
"\"[email protected]\":10," + | ||
"\"[email protected]\":\"123\"," + | ||
"\"[email protected]\":123" + | ||
"}" + | ||
"]" + | ||
"}"; | ||
|
||
[Fact] | ||
public void CustomInstanceAnnotationFromFeedAndEntryInJsonLightShouldBeSkippedByTheReaderByDefault() | ||
{ | ||
|
@@ -121,6 +135,48 @@ public void CustomInstanceAnnotationFromFeedAndEntryInJsonLightShouldBeSkippedBy | |
} | ||
} | ||
|
||
[Fact] | ||
public void ShouldBeAbleToReadCountAndCustomInstanceAnnotationsFromExpandedResourceSetsInJsonLight() | ||
{ | ||
var stream = new MemoryStream(Encoding.UTF8.GetBytes(JsonLightExpandedResourceSetPayloadWithCountAndCustomInstanceAnnotations)); | ||
var readerSettings = new ODataMessageReaderSettings { EnableMessageStreamDisposal = true }; | ||
|
||
IODataResponseMessage messageToRead = new InMemoryMessage { StatusCode = 200, Stream = stream }; | ||
messageToRead.SetHeader("Content-Type", "application/json;odata.streaming=true"); | ||
|
||
// Enable reading custom instance annotations. | ||
//messageToRead.PreferenceAppliedHeader().AnnotationFilter = "Custom.*"; | ||
messageToRead.PreferenceAppliedHeader().AnnotationFilter = "*"; | ||
|
||
using (var messageReader = new ODataMessageReader(messageToRead, readerSettings, Model)) | ||
{ | ||
var odataReader = messageReader.CreateODataResourceSetReader(EntitySet, EntityType); | ||
while (odataReader.Read()) | ||
{ | ||
switch (odataReader.State) | ||
{ | ||
case ODataReaderState.NestedResourceInfoStart: | ||
break; | ||
case ODataReaderState.NestedResourceInfoEnd: | ||
ODataNestedResourceInfo navigationLink = (ODataNestedResourceInfo)odataReader.Item; | ||
|
||
if (navigationLink.Name == "ResourceSetNavigationProperty") | ||
{ | ||
Assert.Equal("ResourceSetNavigationProperty", navigationLink.Name); | ||
Assert.Equal(10, navigationLink.Count); | ||
Assert.Equal(2, navigationLink.InstanceAnnotations.Count); | ||
Assert.Equal("custom.MyAnnotation", navigationLink.InstanceAnnotations.First().Name); | ||
Assert.Equal("custom.StartFeedAnnotation", navigationLink.InstanceAnnotations.Last().Name); | ||
Assert.Equal(true, navigationLink.IsCollection); | ||
Assert.Equal(new Uri("http://example.com/multiple"), navigationLink.Url); | ||
Assert.Equal(new Uri("http://www.example.com/service.svc/TestEntitySet(1)/ResourceSetNavigationProperty/$ref"), navigationLink.AssociationLinkUrl); | ||
} | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
|
||
[Fact] | ||
public void ShouldBeAbleToReadCustomInstanceAnnotationFromFeedAndEntryInJsonLight() | ||
{ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noet: you don't really need the section for a property -- you cover what it returns in the summary.