Skip to content
This repository was archived by the owner on Jun 20, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
9e35332
Generate stream paths for navigation properties
irvinesunday Sep 2, 2020
bf234c9
Refactor out stream path generation into separate function
irvinesunday Sep 2, 2020
da8a2d2
Create base class for media entity operations handler
irvinesunday Sep 2, 2020
39645b1
Add new stream segments conditional checks when creating a NavPropPath
irvinesunday Sep 2, 2020
df4ac10
Add Get and Put operation ids for single-valued nav. prop. paths
irvinesunday Sep 2, 2020
1deb55d
Update handler with support for both Entityset/Singleton stream paths
irvinesunday Sep 2, 2020
468bf78
Update tests to validate the stream paths updates
irvinesunday Sep 2, 2020
654ba30
Revert removed modifier
irvinesunday Sep 2, 2020
4b0a872
Add support for creating a media entity
irvinesunday Sep 7, 2020
b8c74b3
Update tests to validate POST operation for creating media entity
irvinesunday Sep 7, 2020
323ae20
Comment update
irvinesunday Sep 7, 2020
d6dc0a3
Refactor out common code into private methods
irvinesunday Sep 9, 2020
e3ba126
Remove unnecessary schema definition
irvinesunday Sep 9, 2020
4308909
Add application/json content type for RequestBody in media entity POST
irvinesunday Sep 9, 2020
77333d7
Add application/json content in RequestBody
irvinesunday Sep 9, 2020
15fa8d5
Merge branch 'is/nav-prop-stream-paths' into is/media-entity-post
irvinesunday Sep 9, 2020
c3e4e0d
Nitpick: format code
irvinesunday Sep 9, 2020
da22a62
Merge branch 'is/nav-prop-stream-paths' into is/media-entity-post
irvinesunday Sep 9, 2020
ed014fb
Null condition check
irvinesunday Sep 9, 2020
1889069
Add application/json content type for media entities RequestBody/Resp…
irvinesunday Sep 9, 2020
f75d520
Merge branch 'is/media-entity-post' into is/acceptable-media-types
irvinesunday Sep 9, 2020
1d3f56c
Retrieve AcceptableMediaTypes for media entities from annotations
irvinesunday Sep 9, 2020
de8ab80
Add AcceptableMediaTypes OData term constant
irvinesunday Sep 9, 2020
5b54aef
Simplify code
irvinesunday Sep 9, 2020
42640dd
Update tests to validate fetching of AcceptableMediaTypes from annota…
irvinesunday Sep 9, 2020
5f857e2
Get media stream structural property and nav, property annotations
irvinesunday Sep 16, 2020
e8f6d07
Get media type for EntityType instead of EntitySet
irvinesunday Sep 16, 2020
de73511
Revert to original code
irvinesunday Sep 17, 2020
ad40f24
Create local method for generating custom Edm model
irvinesunday Sep 17, 2020
e8486a0
Correct annotations target reference
irvinesunday Sep 17, 2020
1c1f895
Merge branch 'master' into is/acceptable-media-types
irvinesunday Sep 17, 2020
d1ec94f
Fix original code
irvinesunday Sep 17, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ public static IEnumerable<string> GetCollection(this IEdmModel model, IEdmVocabu
}
}

return value.ToList();
return value?.ToList();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,28 @@ private IDictionary<string, OpenApiMediaType> GetContentDescription()

if (EntitySet.EntityType().HasStream)
{
// TODO: Read the AcceptableMediaType annotation from model
content.Add(Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType
IEnumerable<string> mediaTypes = Context.Model.GetCollection(EntitySet.EntityType(),
CapabilitiesConstants.AcceptableMediaTypes);

if (mediaTypes != null)
{
Schema = new OpenApiSchema
foreach (string item in mediaTypes)
{
Type = "string",
Format = "binary"
content.Add(item, null);
}
});
}
else
{
// Default content type
content.Add(Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "string",
Format = "binary"
}
});
}
}

content.Add(Constants.ApplicationJsonMediaType, new OpenApiMediaType
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Generator;
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
using System.Collections.Generic;
using System.Linq;

namespace Microsoft.OpenApi.OData.Operation
Expand Down Expand Up @@ -65,20 +64,7 @@ protected override void SetResponses(OpenApiOperation operation)
new OpenApiResponse
{
Description = "Retrieved media content",
Content = new Dictionary<string, OpenApiMediaType>
{
{
Constants.ApplicationOctetStreamMediaType,
new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "string",
Format = "binary"
}
}
}
}
Content = GetContentDescription()
}
}
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
// ------------------------------------------------------------

using Microsoft.OData.Edm;
using Microsoft.OData.Edm.Vocabularies;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Models;
using Microsoft.OpenApi.OData.Common;
using Microsoft.OpenApi.OData.Edm;
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
using System.Collections.Generic;
using System.Linq;

Expand Down Expand Up @@ -83,18 +85,18 @@ protected override void SetExtensions(OpenApiOperation operation)
/// <returns></returns>
protected string GetOperationId(string prefix, string identifier)
{
Utils.CheckArgumentNull(prefix, nameof(prefix));
Utils.CheckArgumentNull(identifier, nameof(identifier));
Utils.CheckArgumentNullOrEmpty(prefix, nameof(prefix));
Utils.CheckArgumentNullOrEmpty(identifier, nameof(identifier));

IList<string> items = new List<string>
{
NavigationSource.Name
};

var lastpath = Path.Segments.Last(c => c is ODataStreamContentSegment || c is ODataStreamPropertySegment);
foreach (var segment in Path.Segments.Skip(1))
ODataSegment lastSegment = Path.Segments.Last(c => c is ODataStreamContentSegment || c is ODataStreamPropertySegment);
foreach (ODataSegment segment in Path.Segments.Skip(1))
{
if (segment == lastpath)
if (segment == lastSegment)
{
items.Add(prefix + Utils.UpperFirstChar(identifier));
break;
Expand All @@ -110,5 +112,77 @@ protected string GetOperationId(string prefix, string identifier)

return string.Join(".", items);
}

/// <summary>
/// Gets a media entity content description.
/// </summary>
/// <returns>The entity content description.</returns>
protected IDictionary<string, OpenApiMediaType> GetContentDescription()
{
var content = new Dictionary<string, OpenApiMediaType>();

OpenApiSchema schema = new OpenApiSchema
{
Type = "string",
Format = "binary"
};

IEdmVocabularyAnnotatable annotatableElement = null;
IEdmEntityType entityType = EntitySet != null ? EntitySet.EntityType() : Singleton.EntityType();
ODataSegment lastSegmentStreamProp = Path.Segments.LastOrDefault(c => c is ODataStreamPropertySegment);

if (lastSegmentStreamProp != null)
{
// Get the annotatable stream property
// The stream property can either be a structural type or navigation type property
IEdmProperty property = GetStructuralProperty(entityType, lastSegmentStreamProp.Identifier);
if (property == null)
{
property = GetNavigationProperty(entityType, lastSegmentStreamProp.Identifier);
}

annotatableElement = property;
}
else
{
annotatableElement = entityType;
}

// Fetch the respective AcceptableMediaTypes
IEnumerable<string> mediaTypes = null;
if (annotatableElement != null)
{
mediaTypes = Context.Model.GetCollection(annotatableElement,
CapabilitiesConstants.AcceptableMediaTypes);
}

if (mediaTypes != null)
{
foreach (string item in mediaTypes)
{
content.Add(item, null);
}
}
else
{
// Default content type
content.Add(Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType
{
Schema = schema
});
};

return content;
}

private IEdmStructuralProperty GetStructuralProperty(IEdmEntityType entityType, string identifier)
{
return entityType.DeclaredStructuralProperties().FirstOrDefault(x => x.Name.Equals(identifier));
}

private IEdmNavigationProperty GetNavigationProperty(IEdmEntityType entityType, string identifier)
{
return entityType.DeclaredNavigationProperties().FirstOrDefault(x => x.Name.Equals(identifier));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
// ------------------------------------------------------------

using System.Collections.Generic;
using System.Linq;
using Microsoft.OData.Edm;
using Microsoft.OpenApi.Models;
Expand Down Expand Up @@ -58,48 +57,11 @@ protected override void SetBasicInfo(OpenApiOperation operation)
/// <inheritdoc/>
protected override void SetRequestBody(OpenApiOperation operation)
{
OpenApiSchema schema = null;

if (Context.Settings.EnableDerivedTypesReferencesForRequestBody)
{
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(EntitySet.EntityType(), Context.Model);
}

if (schema == null)
{
schema = new OpenApiSchema
{
Reference = new OpenApiReference
{
Type = ReferenceType.Schema,
Id = EntitySet != null ? EntitySet.EntityType().FullName() : Singleton.EntityType().FullName()
}
};
}

operation.RequestBody = new OpenApiRequestBody
{
Required = true,
Description = "New media content.",
Content = new Dictionary<string, OpenApiMediaType>
{
{
Constants.ApplicationOctetStreamMediaType, new OpenApiMediaType
{
Schema = new OpenApiSchema
{
Type = "string",
Format = "binary"
}
}
},
{
Constants.ApplicationJsonMediaType, new OpenApiMediaType
{
Schema = schema
}
}
}
Content = GetContentDescription()
};

base.SetRequestBody(operation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,10 @@ internal class CapabilitiesConstants
/// Org.OData.Capabilities.V1.KeyAsSegmentSupported
/// </summary>
public const string KeyAsSegmentSupported = "Org.OData.Capabilities.V1.KeyAsSegmentSupported";

/// <summary>
/// Org.OData.Core.V1.AcceptableMediaTypes
/// </summary>
public const string AcceptableMediaTypes = "Org.OData.Core.V1.AcceptableMediaTypes";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -326,12 +326,12 @@ public void CreateEntitySetGetOperationReturnsSecurityForReadRestrictions(bool e
}
}

public static IEdmModel GetEdmModel(string annotation, bool hasStream = false)
public static IEdmModel GetEdmModel(string annotation)
{
const string template = @"<edmx:Edmx Version=""4.0"" xmlns:edmx=""http://docs.oasis-open.org/odata/ns/edmx"">
<edmx:DataServices>
<Schema Namespace=""NS"" xmlns=""http://docs.oasis-open.org/odata/ns/edm"">
<EntityType Name=""Customer"" HasStream=""{0}"">
<EntityType Name=""Customer"">
<Key>
<PropertyRef Name=""ID"" />
</Key>
Expand All @@ -341,17 +341,14 @@ public static IEdmModel GetEdmModel(string annotation, bool hasStream = false)
<EntitySet Name=""Customers"" EntityType=""NS.Customer"" />
</EntityContainer>
<Annotations Target=""NS.Default/Customers"">
{1}
{0}
</Annotations>
</Schema>
</edmx:DataServices>
</edmx:Edmx>";
string modelText = string.Format(template, hasStream, annotation);

IEdmModel model;
IEnumerable<EdmError> errors;

bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out model, out errors);
string modelText = string.Format(template, annotation);
bool result = CsdlReader.TryParse(XElement.Parse(modelText).CreateReader(), out IEdmModel model, out _);
Assert.True(result);
return model;
}
Expand Down
Loading