Compare commits
13 commits
master
...
bugfix/oda
Author | SHA1 | Date | |
---|---|---|---|
26eabeceae | |||
85fda323ff | |||
dae89b6da7 | |||
d0b3e2079f | |||
4ee8e9e5eb | |||
7eee372958 | |||
4790d7067e | |||
9716b1d0bf | |||
b5b9e08908 | |||
1bb0a3feca | |||
faa8df1365 | |||
f31925bd64 | |||
9f6a60e5ad |
35
src/Microsoft.OpenApi.OData.Reader/Edm/EdmTypeExtensions.cs
Normal file
35
src/Microsoft.OpenApi.OData.Reader/Edm/EdmTypeExtensions.cs
Normal file
|
@ -0,0 +1,35 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Edm
|
||||
{
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="IEdmType"/>
|
||||
/// </summary>
|
||||
public static class EdmTypeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines wether a path parameter should be wrapped in quotes based on the type of the parameter.
|
||||
/// </summary>
|
||||
/// <param name="edmType">The type of the parameter.</param>
|
||||
public static bool ShouldPathParameterBeQuoted(this IEdmType edmType)
|
||||
{
|
||||
if (edmType == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return edmType.TypeKind switch
|
||||
{
|
||||
EdmTypeKind.Enum => true,
|
||||
EdmTypeKind.Primitive when edmType.IsString() || edmType.IsTemporal() => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -77,13 +77,7 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
}
|
||||
else
|
||||
{
|
||||
IList<string> keyStrings = new List<string>();
|
||||
foreach (var key in KeyMappings)
|
||||
{
|
||||
keyStrings.Add(key.Key + "={" + key.Value + "}");
|
||||
}
|
||||
|
||||
return String.Join(",", keyStrings);
|
||||
return string.Join(",", KeyMappings.Select(x => x.Key + "='{" + x.Value + "}'"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,7 +103,8 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
foreach (var keyProperty in keys)
|
||||
{
|
||||
string name = Utils.GetUniqueName(keyProperty.Name, parameters);
|
||||
keyStrings.Add(keyProperty.Name + "={" + name + "}");
|
||||
var quote = keyProperty.Type.Definition.ShouldPathParameterBeQuoted() ? "'" : string.Empty;
|
||||
keyStrings.Add($"{keyProperty.Name}={quote}{{{name}}}{quote}");
|
||||
}
|
||||
|
||||
return String.Join(",", keyStrings);
|
||||
|
|
|
@ -83,7 +83,8 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
}
|
||||
else
|
||||
{
|
||||
return p.Name + "={" + uniqueName + "}";
|
||||
var quote = p.Type.Definition.ShouldPathParameterBeQuoted() ? "'" : string.Empty;
|
||||
return $"{p.Name}={quote}{{{uniqueName}}}{quote}";
|
||||
}
|
||||
})));
|
||||
|
||||
|
|
|
@ -148,7 +148,8 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
}
|
||||
else
|
||||
{
|
||||
return p.Name + "={" + uniqueName + "}";
|
||||
var quote = p.Type.Definition.ShouldPathParameterBeQuoted() ? "'" : string.Empty;
|
||||
return p.Name + $"={quote}{{{uniqueName}}}{quote}";
|
||||
}
|
||||
})));
|
||||
|
||||
|
|
|
@ -289,13 +289,15 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
{
|
||||
return ODataPathKind.Metadata;
|
||||
}
|
||||
|
||||
if (Segments.Last().Kind == ODataSegmentKind.DollarCount)
|
||||
else if (Segments.Last().Kind == ODataSegmentKind.DollarCount)
|
||||
{
|
||||
return ODataPathKind.DollarCount;
|
||||
}
|
||||
|
||||
if (Segments.Any(c => c.Kind == ODataSegmentKind.StreamProperty || c.Kind == ODataSegmentKind.StreamContent))
|
||||
else if (Segments.Last().Kind == ODataSegmentKind.TypeCast)
|
||||
{
|
||||
return ODataPathKind.TypeCast;
|
||||
}
|
||||
else if (Segments.Any(c => c.Kind == ODataSegmentKind.StreamProperty || c.Kind == ODataSegmentKind.StreamContent))
|
||||
{
|
||||
return ODataPathKind.MediaEntity;
|
||||
}
|
||||
|
@ -315,22 +317,17 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
{
|
||||
return ODataPathKind.NavigationProperty;
|
||||
}
|
||||
|
||||
if (Segments.Count == 1)
|
||||
else if (Segments.Count == 1 && Segments[0] is ODataNavigationSourceSegment segment)
|
||||
{
|
||||
ODataNavigationSourceSegment segment = Segments[0] as ODataNavigationSourceSegment;
|
||||
if (segment != null)
|
||||
if (segment.NavigationSource is IEdmSingleton)
|
||||
{
|
||||
if (segment.NavigationSource is IEdmSingleton)
|
||||
{
|
||||
return ODataPathKind.Singleton;
|
||||
}
|
||||
else
|
||||
{
|
||||
return ODataPathKind.EntitySet;
|
||||
}
|
||||
return ODataPathKind.Singleton;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return ODataPathKind.EntitySet;
|
||||
}
|
||||
}
|
||||
else if (Segments.Count == 2 && Segments.Last().Kind == ODataSegmentKind.Key)
|
||||
{
|
||||
return ODataPathKind.Entity;
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
Singleton,
|
||||
|
||||
/// <summary>
|
||||
/// Represents an operation (function or action) path, for example: ~/users/NS.findRooms(roomId={roomId})
|
||||
/// Represents an operation (function or action) path, for example: ~/users/NS.findRooms(roomId='{roomId}')
|
||||
/// </summary>
|
||||
Operation,
|
||||
|
||||
|
@ -60,9 +60,14 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
/// </summary>
|
||||
DollarCount,
|
||||
|
||||
/// <summary>
|
||||
/// Represents a type cast path, for example: ~/groups/{id}/members/microsoft.graph.user
|
||||
/// </summary>
|
||||
TypeCast,
|
||||
|
||||
/// <summary>
|
||||
/// Represents an un-supported/unknown path.
|
||||
/// </summary>
|
||||
Unknown
|
||||
}
|
||||
Unknown,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,6 +127,7 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
ODataPathKind kind = path.Kind;
|
||||
switch(kind)
|
||||
{
|
||||
case ODataPathKind.TypeCast:
|
||||
case ODataPathKind.DollarCount:
|
||||
case ODataPathKind.Entity:
|
||||
case ODataPathKind.EntitySet:
|
||||
|
@ -189,6 +190,15 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
if(count?.Countable ?? true)
|
||||
CreateCountPath(path, convertSettings);
|
||||
|
||||
//TODO read the cast restrictions annotation
|
||||
var derivedTypes = _model
|
||||
.FindAllDerivedTypes(entitySet.EntityType())
|
||||
.Where(x => x.TypeKind == EdmTypeKind.Entity)
|
||||
.OfType<IEdmEntityType>()
|
||||
.ToArray();
|
||||
if(derivedTypes.Any())
|
||||
CreateTypeCastPaths(path, convertSettings, derivedTypes);
|
||||
|
||||
path.Push(new ODataKeySegment(entityType));
|
||||
AppendPath(path.Clone());
|
||||
}
|
||||
|
@ -285,19 +295,32 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
IEdmEntityType navEntityType = navigationProperty.ToEntityType();
|
||||
var targetsMany = navigationProperty.TargetMultiplicity() == EdmMultiplicity.Many;
|
||||
var propertyPath = navigationProperty.GetPartnerPath()?.Path;
|
||||
var propertyPathIsEmpty = string.IsNullOrEmpty(propertyPath);
|
||||
|
||||
if (targetsMany && (string.IsNullOrEmpty(propertyPath) ||
|
||||
(count?.IsNonCountableNavigationProperty(propertyPath) ?? true)))
|
||||
if (targetsMany)
|
||||
{
|
||||
// ~/entityset/{key}/collection-valued-Nav/$count
|
||||
CreateCountPath(currentPath, convertSettings);
|
||||
if(propertyPathIsEmpty ||
|
||||
(count?.IsNonCountableNavigationProperty(propertyPath) ?? true))
|
||||
{
|
||||
// ~/entityset/{key}/collection-valued-Nav/$count
|
||||
CreateCountPath(currentPath, convertSettings);
|
||||
}
|
||||
|
||||
//TODO read the cast restrictions annotation
|
||||
var derivedTypes = _model
|
||||
.FindAllDerivedTypes(navigationProperty.DeclaringType)
|
||||
.Where(x => x.TypeKind == EdmTypeKind.Entity)
|
||||
.OfType<IEdmEntityType>()
|
||||
.ToArray();
|
||||
if(derivedTypes.Any())
|
||||
CreateTypeCastPaths(currentPath, convertSettings, derivedTypes);
|
||||
}
|
||||
|
||||
if (!navigationProperty.ContainsTarget)
|
||||
{
|
||||
// Non-Contained
|
||||
// Single-Valued: ~/entityset/{key}/single-valued-Nav/$ref
|
||||
// Collection-valued: ~/entityset/{key}/collection-valued-Nav/$ref?$id ={navKey}
|
||||
// Collection-valued: ~/entityset/{key}/collection-valued-Nav/$ref?$id='{navKey}'
|
||||
CreateRefPath(currentPath);
|
||||
|
||||
if (targetsMany)
|
||||
|
@ -393,6 +416,26 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
AppendPath(countPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create OData type cast paths.
|
||||
/// </summary>
|
||||
/// <param name="currentPath">The current OData path.</param>
|
||||
/// <param name="convertSettings">The settings for the current conversion.</param>
|
||||
/// <param name="targetTypes">The target types to generate a path for.</param>
|
||||
private void CreateTypeCastPaths(ODataPath currentPath, OpenApiConvertSettings convertSettings, params IEdmEntityType[] targetTypes)
|
||||
{
|
||||
if(currentPath == null) throw new ArgumentNullException(nameof(currentPath));
|
||||
if(convertSettings == null) throw new ArgumentNullException(nameof(convertSettings));
|
||||
if(!convertSettings.EnableODataTypeCast || targetTypes == null || !targetTypes.Any()) return;
|
||||
|
||||
foreach(var targetType in targetTypes)
|
||||
{
|
||||
var castPath = currentPath.Clone();
|
||||
castPath.Push(new ODataTypeCastSegment(targetType));
|
||||
AppendPath(castPath);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all bounding <see cref="IEdmOperation"/>.
|
||||
/// </summary>
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace Microsoft.OpenApi.OData.Edm
|
|||
{
|
||||
private readonly string _streamPropertyName;
|
||||
/// <summary>
|
||||
/// Initializes a new instance of <see cref="ODataTypeCastSegment"/> class.
|
||||
/// Initializes a new instance of <see cref="ODataStreamPropertySegment"/> class.
|
||||
/// </summary>
|
||||
/// <param name="streamPropertyName">The name of the stream property.</param>
|
||||
public ODataStreamPropertySegment(string streamPropertyName)
|
||||
|
|
|
@ -136,7 +136,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
|
||||
if (parameterNameMapping != null)
|
||||
{
|
||||
parameter.Description = $"Usage: {edmParameter.Name}={{{parameterNameMapping[edmParameter.Name]}}}";
|
||||
var quote = edmParameter.Type.Definition.ShouldPathParameterBeQuoted() ? "'" : string.Empty;
|
||||
parameter.Description = $"Usage: {edmParameter.Name}={quote}{{{parameterNameMapping[edmParameter.Name]}}}{quote}";
|
||||
}
|
||||
|
||||
parameters.Add(parameter);
|
||||
|
@ -203,7 +204,8 @@ namespace Microsoft.OpenApi.OData.Generator
|
|||
|
||||
if (keySegment.KeyMappings != null)
|
||||
{
|
||||
parameter.Description = parameter.Description + $", {keyProperty.Name}={{{parameter.Name}}}";
|
||||
var quote = keyProperty.Type.Definition.ShouldPathParameterBeQuoted() ? "'" : string.Empty;
|
||||
parameter.Description += $", {keyProperty.Name}={quote}{{{parameter.Name}}}{quote}";
|
||||
}
|
||||
|
||||
parameter.Extensions.Add(Constants.xMsKeyType, new OpenApiString(entityType.Name));
|
||||
|
|
|
@ -188,6 +188,11 @@ namespace Microsoft.OpenApi.OData
|
|||
/// </summary>
|
||||
public bool EnableDollarCountPath { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets a value indicating whether or not to include the OData type cast segments on entity sets.
|
||||
/// </summary>
|
||||
public bool EnableODataTypeCast { get; set; } = true;
|
||||
|
||||
internal OpenApiConvertSettings Clone()
|
||||
{
|
||||
var newSettings = new OpenApiConvertSettings
|
||||
|
@ -219,6 +224,7 @@ namespace Microsoft.OpenApi.OData
|
|||
ShowRootPath = this.ShowRootPath,
|
||||
PathProvider = this.PathProvider,
|
||||
EnableDollarCountPath = this.EnableDollarCountPath,
|
||||
EnableODataTypeCast = this.EnableODataTypeCast,
|
||||
};
|
||||
|
||||
return newSettings;
|
||||
|
|
|
@ -183,7 +183,7 @@ namespace Microsoft.OpenApi.OData.Operation
|
|||
|
||||
if (!LastSegmentIsKeySegment && NavigationProperty.TargetMultiplicity() == EdmMultiplicity.Many)
|
||||
{
|
||||
// Need to verify that TopSupported or others should be applyed to navigaiton source.
|
||||
// Need to verify that TopSupported or others should be applied to navigation source.
|
||||
// So, how about for the navigation property.
|
||||
OpenApiParameter parameter = Context.CreateTop(NavigationProperty);
|
||||
if (parameter != null)
|
||||
|
|
|
@ -101,33 +101,29 @@ namespace Microsoft.OpenApi.OData.Operation
|
|||
NavigationSource.Name
|
||||
};
|
||||
|
||||
foreach (var segment in Path.Segments.Skip(1))
|
||||
foreach (var segment in Path.Segments.Skip(1).OfType<ODataNavigationPropertySegment>())
|
||||
{
|
||||
ODataNavigationPropertySegment npSegment = segment as ODataNavigationPropertySegment;
|
||||
if (npSegment != null)
|
||||
if (segment.NavigationProperty == NavigationProperty)
|
||||
{
|
||||
if (npSegment.NavigationProperty == NavigationProperty)
|
||||
items.Add(NavigationProperty.ToEntityType().Name);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (items.Count >= Context.Settings.TagDepth - 1)
|
||||
{
|
||||
items.Add(NavigationProperty.ToEntityType().Name);
|
||||
items.Add(segment.NavigationProperty.ToEntityType().Name);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (items.Count >= Context.Settings.TagDepth - 1)
|
||||
{
|
||||
items.Add(npSegment.NavigationProperty.ToEntityType().Name);
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(npSegment.NavigationProperty.Name);
|
||||
}
|
||||
items.Add(segment.NavigationProperty.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string name = string.Join(".", items);
|
||||
OpenApiTag tag = new OpenApiTag
|
||||
OpenApiTag tag = new()
|
||||
{
|
||||
Name = name
|
||||
};
|
||||
|
@ -155,28 +151,24 @@ namespace Microsoft.OpenApi.OData.Operation
|
|||
};
|
||||
|
||||
var lastpath = Path.Segments.Last(c => c is ODataNavigationPropertySegment);
|
||||
foreach (var segment in Path.Segments.Skip(1))
|
||||
foreach (var segment in Path.Segments.Skip(1).OfType<ODataNavigationPropertySegment>())
|
||||
{
|
||||
ODataNavigationPropertySegment npSegment = segment as ODataNavigationPropertySegment;
|
||||
if (npSegment != null)
|
||||
if (segment == lastpath)
|
||||
{
|
||||
if (segment == lastpath)
|
||||
if (prefix != null)
|
||||
{
|
||||
if (prefix != null)
|
||||
{
|
||||
items.Add(prefix + Utils.UpperFirstChar(npSegment.NavigationProperty.Name));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(Utils.UpperFirstChar(npSegment.NavigationProperty.Name));
|
||||
}
|
||||
|
||||
break;
|
||||
items.Add(prefix + Utils.UpperFirstChar(segment.NavigationProperty.Name));
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(npSegment.NavigationProperty.Name);
|
||||
items.Add(Utils.UpperFirstChar(segment.NavigationProperty.Name));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
items.Add(segment.NavigationProperty.Name);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,410 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
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.Generator;
|
||||
using Microsoft.OpenApi.OData.Vocabulary.Capabilities;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a .../namespace.typename get
|
||||
/// </summary>
|
||||
internal class ODataTypeCastGetOperationHandler : OperationHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public override OperationType OperationType => OperationType.Get;
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets the segment before cast.
|
||||
/// this segment could be "entity set", "Collection property", etc.
|
||||
/// </summary>
|
||||
internal ODataSegment LastSecondSegment { get; set; }
|
||||
|
||||
private bool isKeySegment;
|
||||
private bool IsSingleElement
|
||||
{
|
||||
get => isKeySegment ||
|
||||
singleton != null ||
|
||||
(navigationProperty != null &&
|
||||
!navigationProperty.Type.IsCollection() &&
|
||||
entitySet == null);
|
||||
}
|
||||
private NavigationPropertyRestriction restriction;
|
||||
private IEdmSingleton singleton;
|
||||
private IEdmEntitySet entitySet;
|
||||
private IEdmNavigationProperty navigationProperty;
|
||||
private IEdmEntityType parentEntityType;
|
||||
private IEdmEntityType targetEntityType;
|
||||
private const int SecondLastSegmentIndex = 2;
|
||||
/// <inheritdoc/>
|
||||
protected override void Initialize(ODataContext context, ODataPath path)
|
||||
{
|
||||
base.Initialize(context, path);
|
||||
|
||||
// get the last second segment
|
||||
int count = path.Segments.Count;
|
||||
if(count >= SecondLastSegmentIndex)
|
||||
LastSecondSegment = path.Segments.ElementAt(count - SecondLastSegmentIndex);
|
||||
|
||||
parentEntityType = LastSecondSegment.EntityType;
|
||||
if(LastSecondSegment is ODataNavigationPropertySegment navigationPropertySegment)
|
||||
{
|
||||
SetNavigationPropertyAndRestrictionFromNavigationSegment(navigationPropertySegment, path);
|
||||
}
|
||||
else if(LastSecondSegment is ODataNavigationSourceSegment sourceSegment)
|
||||
{
|
||||
if(sourceSegment.NavigationSource is IEdmEntitySet)
|
||||
SetEntitySetAndRestrictionFromSourceSegment(sourceSegment);
|
||||
else if (sourceSegment.NavigationSource is IEdmSingleton)
|
||||
SetSingletonAndRestrictionFromSourceSegment(sourceSegment);
|
||||
}
|
||||
else if(LastSecondSegment is ODataKeySegment)
|
||||
{
|
||||
isKeySegment = true;
|
||||
var thirdLastSegment = path.Segments.ElementAt(count - SecondLastSegmentIndex - 1);
|
||||
if(thirdLastSegment is ODataNavigationPropertySegment navigationPropertySegment1)
|
||||
{
|
||||
SetNavigationPropertyAndRestrictionFromNavigationSegment(navigationPropertySegment1, path);
|
||||
}
|
||||
else if(thirdLastSegment is ODataNavigationSourceSegment sourceSegment1)
|
||||
{
|
||||
SetEntitySetAndRestrictionFromSourceSegment(sourceSegment1);
|
||||
}
|
||||
}
|
||||
if(path.Last() is ODataTypeCastSegment oDataTypeCastSegment)
|
||||
{
|
||||
targetEntityType = oDataTypeCastSegment.EntityType;
|
||||
}
|
||||
else throw new NotImplementedException($"type cast type {path.Last().GetType().FullName} not implemented");
|
||||
}
|
||||
|
||||
private void SetNavigationPropertyAndRestrictionFromNavigationSegment(ODataNavigationPropertySegment navigationPropertySegment, ODataPath path)
|
||||
{
|
||||
navigationProperty = navigationPropertySegment.NavigationProperty;
|
||||
var navigationPropertyPath = string.Join("/",
|
||||
Path.Segments.Where(s => !(s is ODataKeySegment || s is ODataNavigationSourceSegment
|
||||
|| s is ODataStreamContentSegment || s is ODataStreamPropertySegment)).Select(e => e.Identifier));
|
||||
|
||||
if(path.FirstSegment is ODataNavigationSourceSegment navigationSourceSegment)
|
||||
{
|
||||
NavigationRestrictionsType navigation = navigationSourceSegment.NavigationSource switch {
|
||||
IEdmEntitySet entitySet => Context.Model.GetRecord<NavigationRestrictionsType>(entitySet, CapabilitiesConstants.NavigationRestrictions),
|
||||
IEdmSingleton singleton => Context.Model.GetRecord<NavigationRestrictionsType>(singleton, CapabilitiesConstants.NavigationRestrictions),
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (navigation?.RestrictedProperties != null)
|
||||
{
|
||||
restriction = navigation.RestrictedProperties.FirstOrDefault(r => r.NavigationProperty != null && r.NavigationProperty == navigationPropertyPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetEntitySetAndRestrictionFromSourceSegment(ODataNavigationSourceSegment sourceSegment)
|
||||
{
|
||||
if(sourceSegment.NavigationSource is IEdmEntitySet eSet)
|
||||
{
|
||||
entitySet = eSet;
|
||||
SetRestrictionFromAnnotable(eSet);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetSingletonAndRestrictionFromSourceSegment(ODataNavigationSourceSegment sourceSegment)
|
||||
{
|
||||
if(sourceSegment.NavigationSource is IEdmSingleton sTon)
|
||||
{
|
||||
singleton = sTon;
|
||||
SetRestrictionFromAnnotable(sTon);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void SetRestrictionFromAnnotable(IEdmVocabularyAnnotatable annotable)
|
||||
{
|
||||
NavigationRestrictionsType navigation = Context.Model.GetRecord<NavigationRestrictionsType>(annotable, CapabilitiesConstants.NavigationRestrictions);
|
||||
if (navigation?.RestrictedProperties != null)
|
||||
{
|
||||
restriction = navigation.RestrictedProperties.FirstOrDefault(r => r.NavigationProperty == null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetBasicInfo(OpenApiOperation operation)
|
||||
{
|
||||
// Summary
|
||||
if(IsSingleElement)
|
||||
operation.Summary = $"Get the item of type {parentEntityType.ShortQualifiedName()} as {targetEntityType.ShortQualifiedName()}";
|
||||
else
|
||||
operation.Summary = $"Get the items of type {targetEntityType.ShortQualifiedName()} in the {parentEntityType.ShortQualifiedName()} collection";
|
||||
|
||||
// OperationId
|
||||
if (Context.Settings.EnableOperationId)
|
||||
{
|
||||
operation.OperationId = $"Get.{parentEntityType.ShortQualifiedName()}.As.{targetEntityType.ShortQualifiedName()}";
|
||||
}
|
||||
|
||||
base.SetBasicInfo(operation);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetResponses(OpenApiOperation operation)
|
||||
{
|
||||
if(IsSingleElement)
|
||||
SetSingleResponse(operation);
|
||||
else
|
||||
SetCollectionResponse(operation);
|
||||
|
||||
operation.Responses.Add(Constants.StatusCodeDefault, Constants.StatusCodeDefault.GetResponse());
|
||||
|
||||
base.SetResponses(operation);
|
||||
}
|
||||
private void SetCollectionResponse(OpenApiOperation operation)
|
||||
{
|
||||
OpenApiSchema schema = null;
|
||||
if (Context.Settings.EnableDerivedTypesReferencesForResponses)
|
||||
{
|
||||
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(parentEntityType, Context.Model);
|
||||
}
|
||||
|
||||
if (schema == null)
|
||||
{
|
||||
schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = $"{parentEntityType.FullName()}.To.{targetEntityType.FullName()}"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
var properties = new Dictionary<string, OpenApiSchema>
|
||||
{
|
||||
{
|
||||
"value",
|
||||
new OpenApiSchema
|
||||
{
|
||||
Type = "array",
|
||||
Items = schema
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (Context.Settings.EnablePagination)
|
||||
{
|
||||
properties.Add(
|
||||
"@odata.nextLink",
|
||||
new OpenApiSchema
|
||||
{
|
||||
Type = "string"
|
||||
});
|
||||
}
|
||||
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode200,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "Retrieved entities",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType,
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = new OpenApiSchema
|
||||
{
|
||||
Title = $"Collection of items of type {targetEntityType.ShortQualifiedName()} in the {parentEntityType.ShortQualifiedName()} collection",
|
||||
Type = "object",
|
||||
Properties = properties
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
private void SetSingleResponse(OpenApiOperation operation)
|
||||
{
|
||||
OpenApiSchema schema = null;
|
||||
|
||||
if (Context.Settings.EnableDerivedTypesReferencesForResponses)
|
||||
{
|
||||
schema = EdmModelHelper.GetDerivedTypesReferenceSchema(targetEntityType, Context.Model);
|
||||
}
|
||||
|
||||
if (schema == null)
|
||||
{
|
||||
schema = new OpenApiSchema
|
||||
{
|
||||
Reference = new OpenApiReference
|
||||
{
|
||||
Type = ReferenceType.Schema,
|
||||
Id = targetEntityType.FullName()
|
||||
}
|
||||
};
|
||||
}
|
||||
operation.Responses = new OpenApiResponses
|
||||
{
|
||||
{
|
||||
Constants.StatusCode200,
|
||||
new OpenApiResponse
|
||||
{
|
||||
Description = "Result entities",
|
||||
Content = new Dictionary<string, OpenApiMediaType>
|
||||
{
|
||||
{
|
||||
Constants.ApplicationJsonMediaType,
|
||||
new OpenApiMediaType
|
||||
{
|
||||
Schema = schema
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
protected override void SetTags(OpenApiOperation operation)
|
||||
{
|
||||
IList<string> items = new List<string>
|
||||
{
|
||||
parentEntityType.Name,
|
||||
targetEntityType.Name,
|
||||
};
|
||||
|
||||
string name = string.Join(".", items);
|
||||
OpenApiTag tag = new()
|
||||
{
|
||||
Name = name
|
||||
};
|
||||
if(!IsSingleElement)
|
||||
tag.Extensions.Add(Constants.xMsTocType, new OpenApiString("page"));
|
||||
operation.Tags.Add(tag);
|
||||
|
||||
Context.AppendTag(tag);
|
||||
|
||||
base.SetTags(operation);
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
protected override void SetParameters(OpenApiOperation operation)
|
||||
{
|
||||
base.SetParameters(operation);
|
||||
|
||||
if(navigationProperty != null) {
|
||||
if (IsSingleElement)
|
||||
{
|
||||
new OpenApiParameter[] {
|
||||
Context.CreateSelect(navigationProperty),
|
||||
Context.CreateExpand(navigationProperty),
|
||||
}
|
||||
.Where(x => x != null)
|
||||
.ToList()
|
||||
.ForEach(p => operation.Parameters.Add(p));
|
||||
}
|
||||
else
|
||||
{
|
||||
GetParametersForAnnotableOfMany(navigationProperty)
|
||||
.Union(
|
||||
new OpenApiParameter[] {
|
||||
Context.CreateOrderBy(navigationProperty),
|
||||
Context.CreateSelect(navigationProperty),
|
||||
Context.CreateExpand(navigationProperty),
|
||||
})
|
||||
.Where(x => x != null)
|
||||
.ToList()
|
||||
.ForEach(p => operation.Parameters.Add(p));
|
||||
}
|
||||
}
|
||||
else if(entitySet != null)
|
||||
{
|
||||
if(IsSingleElement)
|
||||
{
|
||||
new OpenApiParameter[] {
|
||||
Context.CreateSelect(entitySet),
|
||||
Context.CreateExpand(entitySet),
|
||||
}
|
||||
.Where(x => x != null)
|
||||
.ToList()
|
||||
.ForEach(p => operation.Parameters.Add(p));
|
||||
}
|
||||
else
|
||||
{
|
||||
GetParametersForAnnotableOfMany(entitySet)
|
||||
.Union(
|
||||
new OpenApiParameter[] {
|
||||
Context.CreateOrderBy(entitySet),
|
||||
Context.CreateSelect(entitySet),
|
||||
Context.CreateExpand(entitySet),
|
||||
})
|
||||
.Where(x => x != null)
|
||||
.ToList()
|
||||
.ForEach(p => operation.Parameters.Add(p));
|
||||
}
|
||||
}
|
||||
else if(singleton != null)
|
||||
{
|
||||
new OpenApiParameter[] {
|
||||
Context.CreateSelect(singleton),
|
||||
Context.CreateExpand(singleton),
|
||||
}
|
||||
.Where(x => x != null)
|
||||
.ToList()
|
||||
.ForEach(p => operation.Parameters.Add(p));
|
||||
}
|
||||
}
|
||||
private IEnumerable<OpenApiParameter> GetParametersForAnnotableOfMany(IEdmVocabularyAnnotatable annotable)
|
||||
{
|
||||
// Need to verify that TopSupported or others should be applied to navigation source.
|
||||
// So, how about for the navigation property.
|
||||
return new OpenApiParameter[] {
|
||||
Context.CreateTop(annotable),
|
||||
Context.CreateSkip(annotable),
|
||||
Context.CreateSearch(annotable),
|
||||
Context.CreateFilter(annotable),
|
||||
Context.CreateCount(annotable),
|
||||
};
|
||||
}
|
||||
|
||||
protected override void SetSecurity(OpenApiOperation operation)
|
||||
{
|
||||
if (restriction == null || restriction.ReadRestrictions == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ReadRestrictionsBase readBase = restriction.ReadRestrictions;
|
||||
|
||||
operation.Security = Context.CreateSecurityRequirements(readBase.Permissions).ToList();
|
||||
}
|
||||
|
||||
protected override void SetExtensions(OpenApiOperation operation)
|
||||
{
|
||||
if (Context.Settings.EnablePagination && !IsSingleElement)
|
||||
{
|
||||
OpenApiObject extension = new()
|
||||
{
|
||||
{ "nextLinkName", new OpenApiString("@odata.nextLink")},
|
||||
{ "operationName", new OpenApiString(Context.Settings.PageableOperationName)}
|
||||
};
|
||||
|
||||
operation.Extensions.Add(Constants.xMsPageable, extension);
|
||||
}
|
||||
|
||||
base.SetExtensions(operation);
|
||||
}
|
||||
}
|
|
@ -89,6 +89,12 @@ namespace Microsoft.OpenApi.OData.Operation
|
|||
{
|
||||
{OperationType.Get, new DollarCountGetOperationHandler() }
|
||||
}},
|
||||
|
||||
// .../namespace.typename (cast, get)
|
||||
{ODataPathKind.TypeCast, new Dictionary<OperationType, IOperationHandler>
|
||||
{
|
||||
{OperationType.Get, new ODataTypeCastGetOperationHandler() },
|
||||
}},
|
||||
};
|
||||
|
||||
/// <inheritdoc/>
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.PathItem;
|
||||
|
||||
/// <summary>
|
||||
/// Path item handler for type cast for example: ~/groups/{id}/members/microsoft.graph.user
|
||||
/// </summary>
|
||||
internal class ODataTypeCastPathItemHandler : PathItemHandler
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
protected override ODataPathKind HandleKind => ODataPathKind.TypeCast;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override void SetOperations(OpenApiPathItem item)
|
||||
{
|
||||
AddOperation(item, OperationType.Get);
|
||||
}
|
||||
}
|
|
@ -45,6 +45,9 @@ namespace Microsoft.OpenApi.OData.PathItem
|
|||
// $count
|
||||
{ ODataPathKind.DollarCount, new DollarCountPathItemHandler() },
|
||||
|
||||
// ~/groups/{id}/members/microsoft.graph.user
|
||||
{ ODataPathKind.TypeCast, new ODataTypeCastPathItemHandler() },
|
||||
|
||||
// Unknown
|
||||
{ ODataPathKind.Unknown, null },
|
||||
};
|
||||
|
|
|
@ -3,6 +3,8 @@ abstract Microsoft.OpenApi.OData.Edm.ODataSegment.Identifier.get -> string
|
|||
abstract Microsoft.OpenApi.OData.Edm.ODataSegment.Kind.get -> Microsoft.OpenApi.OData.Edm.ODataSegmentKind
|
||||
Microsoft.OpenApi.OData.Common.Utils
|
||||
Microsoft.OpenApi.OData.Edm.EdmModelExtensions
|
||||
Microsoft.OpenApi.OData.Edm.EdmTypeExtensions
|
||||
static Microsoft.OpenApi.OData.Edm.EdmTypeExtensions.ShouldPathParameterBeQuoted(this Microsoft.OData.Edm.IEdmType edmType) -> bool
|
||||
Microsoft.OpenApi.OData.Edm.IODataPathProvider
|
||||
Microsoft.OpenApi.OData.Edm.IODataPathProvider.CanFilter(Microsoft.OData.Edm.IEdmElement element) -> bool
|
||||
Microsoft.OpenApi.OData.Edm.IODataPathProvider.GetPaths(Microsoft.OData.Edm.IEdmModel model, Microsoft.OpenApi.OData.OpenApiConvertSettings settings) -> System.Collections.Generic.IEnumerable<Microsoft.OpenApi.OData.Edm.ODataPath>
|
||||
|
@ -59,7 +61,8 @@ Microsoft.OpenApi.OData.Edm.ODataPathKind.Operation = 3 -> Microsoft.OpenApi.ODa
|
|||
Microsoft.OpenApi.OData.Edm.ODataPathKind.OperationImport = 4 -> Microsoft.OpenApi.OData.Edm.ODataPathKind
|
||||
Microsoft.OpenApi.OData.Edm.ODataPathKind.Ref = 6 -> Microsoft.OpenApi.OData.Edm.ODataPathKind
|
||||
Microsoft.OpenApi.OData.Edm.ODataPathKind.Singleton = 2 -> Microsoft.OpenApi.OData.Edm.ODataPathKind
|
||||
Microsoft.OpenApi.OData.Edm.ODataPathKind.Unknown = 10 -> Microsoft.OpenApi.OData.Edm.ODataPathKind
|
||||
Microsoft.OpenApi.OData.Edm.ODataPathKind.TypeCast = 10 -> Microsoft.OpenApi.OData.Edm.ODataPathKind
|
||||
Microsoft.OpenApi.OData.Edm.ODataPathKind.Unknown = 11 -> Microsoft.OpenApi.OData.Edm.ODataPathKind
|
||||
Microsoft.OpenApi.OData.Edm.ODataPathProvider
|
||||
Microsoft.OpenApi.OData.Edm.ODataPathProvider.ODataPathProvider() -> void
|
||||
Microsoft.OpenApi.OData.Edm.ODataRefSegment
|
||||
|
@ -130,6 +133,8 @@ Microsoft.OpenApi.OData.OpenApiConvertSettings.PathProvider.get -> Microsoft.Ope
|
|||
Microsoft.OpenApi.OData.OpenApiConvertSettings.PathProvider.set -> void
|
||||
Microsoft.OpenApi.OData.OpenApiConvertSettings.EnableDollarCountPath.get -> bool
|
||||
Microsoft.OpenApi.OData.OpenApiConvertSettings.EnableDollarCountPath.set -> void
|
||||
Microsoft.OpenApi.OData.OpenApiConvertSettings.EnableODataTypeCast.get -> bool
|
||||
Microsoft.OpenApi.OData.OpenApiConvertSettings.EnableODataTypeCast.set -> void
|
||||
Microsoft.OpenApi.OData.OpenApiConvertSettings.PrefixEntityTypeNameBeforeKey.get -> bool
|
||||
Microsoft.OpenApi.OData.OpenApiConvertSettings.PrefixEntityTypeNameBeforeKey.set -> void
|
||||
Microsoft.OpenApi.OData.OpenApiConvertSettings.RequireDerivedTypesConstraintForBoundOperations.get -> bool
|
||||
|
|
|
@ -83,7 +83,7 @@ namespace Microsoft.OpenApi.OData.Edm.Tests
|
|||
};
|
||||
|
||||
// Assert
|
||||
Assert.Equal("firstName={firstName},lastName={lastName}", segment.GetPathItemName(settings));
|
||||
Assert.Equal("firstName='{firstName}',lastName='{lastName}'", segment.GetPathItemName(settings));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,7 +80,7 @@ namespace Microsoft.OpenApi.OData.Edm.Tests
|
|||
var segment = new ODataOperationImportSegment(_functionImport);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("MyFunction(firstName={firstName},lastName={lastName})",
|
||||
Assert.Equal("MyFunction(firstName='{firstName}',lastName='{lastName}')",
|
||||
segment.GetPathItemName(new OpenApiConvertSettings()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -98,9 +98,9 @@ namespace Microsoft.OpenApi.OData.Edm.Tests
|
|||
|
||||
[Theory]
|
||||
[InlineData(true, true, "{param}")]
|
||||
[InlineData(true, false, "NS.MyFunction(param={param})")]
|
||||
[InlineData(false, true, "NS.MyFunction(param={param})")]
|
||||
[InlineData(false, false, "NS.MyFunction(param={param})")]
|
||||
[InlineData(true, false, "NS.MyFunction(param='{param}')")]
|
||||
[InlineData(false, true, "NS.MyFunction(param='{param}')")]
|
||||
[InlineData(false, false, "NS.MyFunction(param='{param}')")]
|
||||
public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedFunction(bool isEscapedFunction, bool enableEscapeFunctionCall, string expected)
|
||||
{
|
||||
// Arrange & Act
|
||||
|
@ -121,9 +121,9 @@ namespace Microsoft.OpenApi.OData.Edm.Tests
|
|||
|
||||
[Theory]
|
||||
[InlineData(true, true, "{param}:")]
|
||||
[InlineData(true, false, "NS.MyFunction(param={param})")]
|
||||
[InlineData(false, true, "NS.MyFunction(param={param})")]
|
||||
[InlineData(false, false, "NS.MyFunction(param={param})")]
|
||||
[InlineData(true, false, "NS.MyFunction(param='{param}')")]
|
||||
[InlineData(false, true, "NS.MyFunction(param='{param}')")]
|
||||
[InlineData(false, false, "NS.MyFunction(param='{param}')")]
|
||||
public void GetPathItemNameReturnsCorrectFunctionLiteralForEscapedComposableFunction(bool isEscapedFunction, bool enableEscapeFunctionCall, string expected)
|
||||
{
|
||||
// Arrange & Act
|
||||
|
|
|
@ -249,10 +249,10 @@ namespace Microsoft.OpenApi.OData.Edm.Tests
|
|||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, true, "/Customers/FirstName={FirstName},LastName={LastName}")]
|
||||
[InlineData(true, false, "/Customers/FirstName={FirstName},LastName={LastName}")]
|
||||
[InlineData(false, true, "/Customers(FirstName={FirstName},LastName={LastName})")]
|
||||
[InlineData(false, false, "/Customers(FirstName={FirstName},LastName={LastName})")]
|
||||
[InlineData(true, true, "/Customers/FirstName='{FirstName}',LastName='{LastName}'")]
|
||||
[InlineData(true, false, "/Customers/FirstName='{FirstName}',LastName='{LastName}'")]
|
||||
[InlineData(false, true, "/Customers(FirstName='{FirstName}',LastName='{LastName}')")]
|
||||
[InlineData(false, false, "/Customers(FirstName='{FirstName}',LastName='{LastName}')")]
|
||||
public void GetPathItemNameReturnsCorrectStringWithMultipleKeySegment(bool keyAsSegment, bool prefix, string expected)
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
@ -75,12 +75,12 @@ namespace Microsoft.OpenApi.OData.Generator.Tests
|
|||
[InlineData(true, true, true, "/Customers({ID}):/{param}:")]
|
||||
[InlineData(true, true, false, "/Customers({ID}):/{param}")]
|
||||
|
||||
[InlineData(true, false, true, "/Customers({ID})/NS.MyFunction(param={param})")]
|
||||
[InlineData(true, false, false, "/Customers({ID})/NS.MyFunction(param={param})")]
|
||||
[InlineData(false, true, true, "/Customers({ID})/NS.MyFunction(param={param})")]
|
||||
[InlineData(false, true, false, "/Customers({ID})/NS.MyFunction(param={param})")]
|
||||
[InlineData(false, false, true, "/Customers({ID})/NS.MyFunction(param={param})")]
|
||||
[InlineData(false, false, false, "/Customers({ID})/NS.MyFunction(param={param})")]
|
||||
[InlineData(true, false, true, "/Customers({ID})/NS.MyFunction(param='{param}')")]
|
||||
[InlineData(true, false, false, "/Customers({ID})/NS.MyFunction(param='{param}')")]
|
||||
[InlineData(false, true, true, "/Customers({ID})/NS.MyFunction(param='{param}')")]
|
||||
[InlineData(false, true, false, "/Customers({ID})/NS.MyFunction(param='{param}')")]
|
||||
[InlineData(false, false, true, "/Customers({ID})/NS.MyFunction(param='{param}')")]
|
||||
[InlineData(false, false, false, "/Customers({ID})/NS.MyFunction(param='{param}')")]
|
||||
public void CreatePathItemsReturnsForEscapeFunctionModel(bool enableEscaped, bool hasEscapedAnnotation, bool isComposable, string expected)
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>..\..\tool\35MSSharedLib1024.snk</AssemblyOriginatorKeyFile>
|
||||
<DelaySign>true</DelaySign>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<OutputPath Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">..\..\bin\debug\test\</OutputPath>
|
||||
<OutputPath Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">..\..\bin\release\test\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
|
|
@ -134,7 +134,7 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
|
|||
|
||||
if (enableOperationId)
|
||||
{
|
||||
Assert.Equal("FunctionImport.MyFunction-3e3f", operation.OperationId);
|
||||
Assert.Equal("FunctionImport.MyFunction-cc1c", operation.OperationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -229,7 +229,7 @@ namespace Microsoft.OpenApi.OData.Operation.Tests
|
|||
|
||||
if (enableOperationId)
|
||||
{
|
||||
Assert.Equal("Customers.Customer.MyFunction-28ae", operation.OperationId);
|
||||
Assert.Equal("Customers.Customer.MyFunction-df74", operation.OperationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
// ------------------------------------------------------------
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License (MIT). See LICENSE in the repo root for license information.
|
||||
// ------------------------------------------------------------
|
||||
|
||||
using System.Linq;
|
||||
using Microsoft.OData.Edm;
|
||||
using Microsoft.OpenApi.Extensions;
|
||||
using Microsoft.OpenApi.OData.Edm;
|
||||
using Microsoft.OpenApi.OData.PathItem.Tests;
|
||||
using Microsoft.OpenApi.OData.Tests;
|
||||
using Xunit;
|
||||
|
||||
namespace Microsoft.OpenApi.OData.Operation.Tests;
|
||||
public class ODataTypeCastGetOperationHandlerTests
|
||||
{
|
||||
private readonly ODataTypeCastGetOperationHandler _operationHandler = new ();
|
||||
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(false, false)]
|
||||
public void CreateODataTypeCastGetOperationReturnsCorrectOperationForCollectionNavigationProperty(bool enableOperationId, bool enablePagination)
|
||||
{// ../People/{id}/Friends/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee
|
||||
// Arrange
|
||||
IEdmModel model = EdmModelHelper.TripServiceModel;
|
||||
OpenApiConvertSettings settings = new()
|
||||
{
|
||||
EnableOperationId = enableOperationId,
|
||||
EnablePagination = enablePagination,
|
||||
};
|
||||
ODataContext context = new(model, settings);
|
||||
IEdmEntitySet people = model.EntityContainer.FindEntitySet("People");
|
||||
Assert.NotNull(people);
|
||||
|
||||
IEdmEntityType person = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Person");
|
||||
IEdmEntityType employee = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Employee");
|
||||
IEdmNavigationProperty navProperty = person.DeclaredNavigationProperties().First(c => c.Name == "Friends");
|
||||
ODataPath path = new(new ODataNavigationSourceSegment(people),
|
||||
new ODataKeySegment(people.EntityType()),
|
||||
new ODataNavigationPropertySegment(navProperty),
|
||||
new ODataTypeCastSegment(employee));
|
||||
|
||||
// Act
|
||||
var operation = _operationHandler.CreateOperation(context, path);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(operation);
|
||||
Assert.Equal("Get the items of type Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee in the Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person collection", operation.Summary);
|
||||
Assert.NotNull(operation.Tags);
|
||||
var tag = Assert.Single(operation.Tags);
|
||||
Assert.Equal("Person.Employee", tag.Name);
|
||||
Assert.Single(tag.Extensions);
|
||||
|
||||
Assert.NotNull(operation.Parameters);
|
||||
Assert.Equal(9, operation.Parameters.Count);
|
||||
|
||||
Assert.Null(operation.RequestBody);
|
||||
if(enablePagination)
|
||||
Assert.Single(operation.Extensions);
|
||||
|
||||
Assert.Equal(2, operation.Responses.Count);
|
||||
Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key));
|
||||
|
||||
if (enableOperationId)
|
||||
{
|
||||
Assert.Equal("Get.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person.As.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.OperationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Null(operation.OperationId);
|
||||
}
|
||||
Assert.True(operation.Responses["200"].Content["application/json"].Schema.Properties.ContainsKey("value"));
|
||||
}
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(false, false)]
|
||||
public void CreateODataTypeCastGetOperationReturnsCorrectOperationForEntitySet(bool enableOperationId, bool enablePagination)
|
||||
{// .../People/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee
|
||||
// Arrange
|
||||
IEdmModel model = EdmModelHelper.TripServiceModel;
|
||||
OpenApiConvertSettings settings = new()
|
||||
{
|
||||
EnableOperationId = enableOperationId,
|
||||
EnablePagination = enablePagination,
|
||||
};
|
||||
ODataContext context = new(model, settings);
|
||||
IEdmEntitySet people = model.EntityContainer.FindEntitySet("People");
|
||||
Assert.NotNull(people);
|
||||
|
||||
IEdmEntityType employee = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Employee");
|
||||
ODataPath path = new(new ODataNavigationSourceSegment(people),
|
||||
new ODataTypeCastSegment(employee));
|
||||
|
||||
// Act
|
||||
var operation = _operationHandler.CreateOperation(context, path);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(operation);
|
||||
Assert.Equal("Get the items of type Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee in the Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person collection", operation.Summary);
|
||||
Assert.NotNull(operation.Tags);
|
||||
var tag = Assert.Single(operation.Tags);
|
||||
Assert.Equal("Person.Employee", tag.Name);
|
||||
Assert.Single(tag.Extensions);
|
||||
|
||||
Assert.NotNull(operation.Parameters);
|
||||
Assert.Equal(8, operation.Parameters.Count);
|
||||
|
||||
Assert.Null(operation.RequestBody);
|
||||
if(enablePagination)
|
||||
Assert.Single(operation.Extensions);
|
||||
|
||||
Assert.Equal(2, operation.Responses.Count);
|
||||
Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key));
|
||||
|
||||
if (enableOperationId)
|
||||
{
|
||||
Assert.Equal("Get.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person.As.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.OperationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Null(operation.OperationId);
|
||||
}
|
||||
Assert.True(operation.Responses["200"].Content["application/json"].Schema.Properties.ContainsKey("value"));
|
||||
}
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(false, false)]
|
||||
public void CreateODataTypeCastGetOperationReturnsCorrectOperationForEntitySetId(bool enableOperationId, bool enablePagination)
|
||||
{// .../People/{id}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee
|
||||
// Arrange
|
||||
IEdmModel model = EdmModelHelper.TripServiceModel;
|
||||
OpenApiConvertSettings settings = new()
|
||||
{
|
||||
EnableOperationId = enableOperationId,
|
||||
EnablePagination = enablePagination,
|
||||
};
|
||||
ODataContext context = new(model, settings);
|
||||
IEdmEntitySet people = model.EntityContainer.FindEntitySet("People");
|
||||
Assert.NotNull(people);
|
||||
|
||||
IEdmEntityType person = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Person");
|
||||
IEdmEntityType employee = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Employee");
|
||||
ODataPath path = new(new ODataNavigationSourceSegment(people),
|
||||
new ODataKeySegment(people.EntityType()),
|
||||
new ODataTypeCastSegment(employee));
|
||||
|
||||
// Act
|
||||
var operation = _operationHandler.CreateOperation(context, path);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(operation);
|
||||
Assert.Equal("Get the item of type Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person as Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.Summary);
|
||||
Assert.NotNull(operation.Tags);
|
||||
var tag = Assert.Single(operation.Tags);
|
||||
Assert.Equal("Person.Employee", tag.Name);
|
||||
Assert.Empty(tag.Extensions);
|
||||
|
||||
Assert.NotNull(operation.Parameters);
|
||||
Assert.Equal(3, operation.Parameters.Count); //select, expand, id
|
||||
|
||||
Assert.Null(operation.RequestBody);
|
||||
if(enablePagination)
|
||||
Assert.Empty(operation.Extensions);
|
||||
|
||||
Assert.Equal(2, operation.Responses.Count);
|
||||
Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key));
|
||||
|
||||
if (enableOperationId)
|
||||
{
|
||||
Assert.Equal("Get.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person.As.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.OperationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Null(operation.OperationId);
|
||||
}
|
||||
Assert.False(operation.Responses["200"].Content["application/json"].Schema.Properties.ContainsKey("value"));
|
||||
}
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(false, false)]
|
||||
public void CreateODataTypeCastGetOperationReturnsCorrectOperationForSingleNavigationproperty(bool enableOperationId, bool enablePagination)
|
||||
{// .../People/{id}/BestFriend/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee
|
||||
// Arrange
|
||||
IEdmModel model = EdmModelHelper.TripServiceModel;
|
||||
OpenApiConvertSettings settings = new()
|
||||
{
|
||||
EnableOperationId = enableOperationId,
|
||||
EnablePagination = enablePagination,
|
||||
};
|
||||
ODataContext context = new(model, settings);
|
||||
IEdmEntitySet people = model.EntityContainer.FindEntitySet("People");
|
||||
Assert.NotNull(people);
|
||||
|
||||
IEdmEntityType person = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Person");
|
||||
IEdmEntityType employee = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Employee");
|
||||
IEdmNavigationProperty navProperty = person.DeclaredNavigationProperties().First(c => c.Name == "BestFriend");
|
||||
ODataPath path = new(new ODataNavigationSourceSegment(people),
|
||||
new ODataKeySegment(people.EntityType()),
|
||||
new ODataNavigationPropertySegment(navProperty),
|
||||
new ODataTypeCastSegment(employee));
|
||||
|
||||
// Act
|
||||
var operation = _operationHandler.CreateOperation(context, path);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(operation);
|
||||
Assert.Equal("Get the item of type Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person as Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.Summary);
|
||||
Assert.NotNull(operation.Tags);
|
||||
var tag = Assert.Single(operation.Tags);
|
||||
Assert.Equal("Person.Employee", tag.Name);
|
||||
Assert.Empty(tag.Extensions);
|
||||
|
||||
Assert.NotNull(operation.Parameters);
|
||||
Assert.Equal(3, operation.Parameters.Count); //select, expand, id
|
||||
|
||||
Assert.Null(operation.RequestBody);
|
||||
if(enablePagination)
|
||||
Assert.Empty(operation.Extensions);
|
||||
|
||||
Assert.Equal(2, operation.Responses.Count);
|
||||
Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key));
|
||||
|
||||
if (enableOperationId)
|
||||
{
|
||||
Assert.Equal("Get.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person.As.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.OperationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Null(operation.OperationId);
|
||||
}
|
||||
Assert.False(operation.Responses["200"].Content["application/json"].Schema.Properties.ContainsKey("value"));
|
||||
}
|
||||
[Theory]
|
||||
[InlineData(true, true)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
[InlineData(false, false)]
|
||||
public void CreateODataTypeCastGetOperationReturnsCorrectOperationForSingleton(bool enableOperationId, bool enablePagination)
|
||||
{// .../Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee
|
||||
// Arrange
|
||||
IEdmModel model = EdmModelHelper.TripServiceModel;
|
||||
OpenApiConvertSettings settings = new()
|
||||
{
|
||||
EnableOperationId = enableOperationId,
|
||||
EnablePagination = enablePagination,
|
||||
};
|
||||
ODataContext context = new(model, settings);
|
||||
IEdmSingleton me = model.EntityContainer.FindSingleton("Me");
|
||||
Assert.NotNull(me);
|
||||
|
||||
IEdmEntityType employee = model.SchemaElements.OfType<IEdmEntityType>().First(c => c.Name == "Employee");
|
||||
ODataPath path = new(new ODataNavigationSourceSegment(me),
|
||||
new ODataTypeCastSegment(employee));
|
||||
|
||||
// Act
|
||||
var operation = _operationHandler.CreateOperation(context, path);
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(operation);
|
||||
Assert.Equal("Get the item of type Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person as Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.Summary);
|
||||
Assert.NotNull(operation.Tags);
|
||||
var tag = Assert.Single(operation.Tags);
|
||||
Assert.Equal("Person.Employee", tag.Name);
|
||||
Assert.Empty(tag.Extensions);
|
||||
|
||||
Assert.NotNull(operation.Parameters);
|
||||
Assert.Equal(2, operation.Parameters.Count); //select, expand
|
||||
|
||||
Assert.Null(operation.RequestBody);
|
||||
if(enablePagination)
|
||||
Assert.Empty(operation.Extensions);
|
||||
|
||||
Assert.Equal(2, operation.Responses.Count);
|
||||
Assert.Equal(new string[] { "200", "default" }, operation.Responses.Select(e => e.Key));
|
||||
|
||||
if (enableOperationId)
|
||||
{
|
||||
Assert.Equal("Get.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Person.As.Microsoft.OData.Service.Sample.TrippinInMemory.Models.Employee", operation.OperationId);
|
||||
}
|
||||
else
|
||||
{
|
||||
Assert.Null(operation.OperationId);
|
||||
}
|
||||
Assert.False(operation.Responses["200"].Content["application/json"].Schema.Properties.ContainsKey("value"));
|
||||
}
|
||||
}
|
|
@ -22,6 +22,7 @@ namespace Microsoft.OpenApi.OData.PathItem.Tests
|
|||
[InlineData(ODataPathKind.MediaEntity, typeof(MediaEntityPathItemHandler))]
|
||||
[InlineData(ODataPathKind.Metadata, typeof(MetadataPathItemHandler))]
|
||||
[InlineData(ODataPathKind.DollarCount, typeof(DollarCountPathItemHandler))]
|
||||
[InlineData(ODataPathKind.TypeCast, typeof(ODataTypeCastPathItemHandler))]
|
||||
public void GetHandlerReturnsCorrectHandlerType(ODataPathKind pathKind, Type handlerType)
|
||||
{
|
||||
// Arrange
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
{
|
||||
"swagger": "2.0",
|
||||
"info": {
|
||||
"title": "OData Service for namespace Microsoft.OData.Service.Sample.TrippinInMemory.Models",
|
||||
|
@ -1206,7 +1206,7 @@
|
|||
"x-ms-docs-operation-type": "function"
|
||||
}
|
||||
},
|
||||
"/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": {
|
||||
"/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Me.Functions"
|
||||
|
@ -1220,7 +1220,7 @@
|
|||
{
|
||||
"in": "path",
|
||||
"name": "userName",
|
||||
"description": "Usage: userName={userName}",
|
||||
"description": "Usage: userName='{userName}'",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
@ -1350,7 +1350,7 @@
|
|||
"x-ms-docs-operation-type": "action"
|
||||
}
|
||||
},
|
||||
"/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": {
|
||||
"/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Me.Functions"
|
||||
|
@ -1364,7 +1364,7 @@
|
|||
{
|
||||
"in": "path",
|
||||
"name": "lastName",
|
||||
"description": "Usage: lastName={lastName}",
|
||||
"description": "Usage: lastName='{lastName}'",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
@ -2949,7 +2949,7 @@
|
|||
"x-ms-docs-operation-type": "function"
|
||||
}
|
||||
},
|
||||
"/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": {
|
||||
"/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"NewComePeople.Functions"
|
||||
|
@ -2971,7 +2971,7 @@
|
|||
{
|
||||
"in": "path",
|
||||
"name": "userName",
|
||||
"description": "Usage: userName={userName}",
|
||||
"description": "Usage: userName='{userName}'",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
@ -3117,7 +3117,7 @@
|
|||
"x-ms-docs-operation-type": "action"
|
||||
}
|
||||
},
|
||||
"/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": {
|
||||
"/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"NewComePeople.Functions"
|
||||
|
@ -3139,7 +3139,7 @@
|
|||
{
|
||||
"in": "path",
|
||||
"name": "lastName",
|
||||
"description": "Usage: lastName={lastName}",
|
||||
"description": "Usage: lastName='{lastName}'",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
@ -4842,7 +4842,7 @@
|
|||
"x-ms-docs-operation-type": "function"
|
||||
}
|
||||
},
|
||||
"/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": {
|
||||
"/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"People.Functions"
|
||||
|
@ -4864,7 +4864,7 @@
|
|||
{
|
||||
"in": "path",
|
||||
"name": "userName",
|
||||
"description": "Usage: userName={userName}",
|
||||
"description": "Usage: userName='{userName}'",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
@ -5010,7 +5010,7 @@
|
|||
"x-ms-docs-operation-type": "action"
|
||||
}
|
||||
},
|
||||
"/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": {
|
||||
"/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"People.Functions"
|
||||
|
@ -5032,7 +5032,7 @@
|
|||
{
|
||||
"in": "path",
|
||||
"name": "lastName",
|
||||
"description": "Usage: lastName={lastName}",
|
||||
"description": "Usage: lastName='{lastName}'",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
swagger: '2.0'
|
||||
swagger: '2.0'
|
||||
info:
|
||||
title: OData Service for namespace Microsoft.OData.Service.Sample.TrippinInMemory.Models
|
||||
description: This OData service is located at http://services.odata.org/TrippinRESTierService
|
||||
|
@ -822,7 +822,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/responses/error'
|
||||
x-ms-docs-operation-type: function
|
||||
'/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})':
|
||||
'/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')':
|
||||
get:
|
||||
tags:
|
||||
- Me.Functions
|
||||
|
@ -833,7 +833,7 @@ paths:
|
|||
parameters:
|
||||
- in: path
|
||||
name: userName
|
||||
description: 'Usage: userName={userName}'
|
||||
description: 'Usage: userName=''{userName}'''
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
|
@ -919,7 +919,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/responses/error'
|
||||
x-ms-docs-operation-type: action
|
||||
'/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})':
|
||||
'/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')':
|
||||
get:
|
||||
tags:
|
||||
- Me.Functions
|
||||
|
@ -930,7 +930,7 @@ paths:
|
|||
parameters:
|
||||
- in: path
|
||||
name: lastName
|
||||
description: 'Usage: lastName={lastName}'
|
||||
description: 'Usage: lastName=''{lastName}'''
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
|
@ -2038,7 +2038,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/responses/error'
|
||||
x-ms-docs-operation-type: function
|
||||
'/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})':
|
||||
'/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')':
|
||||
get:
|
||||
tags:
|
||||
- NewComePeople.Functions
|
||||
|
@ -2055,7 +2055,7 @@ paths:
|
|||
x-ms-docs-key-type: Person
|
||||
- in: path
|
||||
name: userName
|
||||
description: 'Usage: userName={userName}'
|
||||
description: 'Usage: userName=''{userName}'''
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
|
@ -2153,7 +2153,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/responses/error'
|
||||
x-ms-docs-operation-type: action
|
||||
'/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})':
|
||||
'/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')':
|
||||
get:
|
||||
tags:
|
||||
- NewComePeople.Functions
|
||||
|
@ -2170,7 +2170,7 @@ paths:
|
|||
x-ms-docs-key-type: Person
|
||||
- in: path
|
||||
name: lastName
|
||||
description: 'Usage: lastName={lastName}'
|
||||
description: 'Usage: lastName=''{lastName}'''
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
|
@ -3364,7 +3364,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/responses/error'
|
||||
x-ms-docs-operation-type: function
|
||||
'/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})':
|
||||
'/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')':
|
||||
get:
|
||||
tags:
|
||||
- People.Functions
|
||||
|
@ -3381,7 +3381,7 @@ paths:
|
|||
x-ms-docs-key-type: Person
|
||||
- in: path
|
||||
name: userName
|
||||
description: 'Usage: userName={userName}'
|
||||
description: 'Usage: userName=''{userName}'''
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
|
@ -3479,7 +3479,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/responses/error'
|
||||
x-ms-docs-operation-type: action
|
||||
'/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})':
|
||||
'/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')':
|
||||
get:
|
||||
tags:
|
||||
- People.Functions
|
||||
|
@ -3496,7 +3496,7 @@ paths:
|
|||
x-ms-docs-key-type: Person
|
||||
- in: path
|
||||
name: lastName
|
||||
description: 'Usage: lastName={lastName}'
|
||||
description: 'Usage: lastName=''{lastName}'''
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
{
|
||||
{
|
||||
"openapi": "3.0.1",
|
||||
"info": {
|
||||
"title": "OData Service for namespace Microsoft.OData.Service.Sample.TrippinInMemory.Models",
|
||||
|
@ -1370,7 +1370,7 @@
|
|||
"x-ms-docs-operation-type": "function"
|
||||
}
|
||||
},
|
||||
"/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": {
|
||||
"/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Me.Functions"
|
||||
|
@ -1381,7 +1381,7 @@
|
|||
{
|
||||
"name": "userName",
|
||||
"in": "path",
|
||||
"description": "Usage: userName={userName}",
|
||||
"description": "Usage: userName='{userName}'",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
|
@ -1522,7 +1522,7 @@
|
|||
"x-ms-docs-operation-type": "action"
|
||||
}
|
||||
},
|
||||
"/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": {
|
||||
"/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"Me.Functions"
|
||||
|
@ -1533,7 +1533,7 @@
|
|||
{
|
||||
"name": "lastName",
|
||||
"in": "path",
|
||||
"description": "Usage: lastName={lastName}",
|
||||
"description": "Usage: lastName='{lastName}'",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
|
@ -3304,7 +3304,7 @@
|
|||
"x-ms-docs-operation-type": "function"
|
||||
}
|
||||
},
|
||||
"/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": {
|
||||
"/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"NewComePeople.Functions"
|
||||
|
@ -3325,7 +3325,7 @@
|
|||
{
|
||||
"name": "userName",
|
||||
"in": "path",
|
||||
"description": "Usage: userName={userName}",
|
||||
"description": "Usage: userName='{userName}'",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
|
@ -3490,7 +3490,7 @@
|
|||
"x-ms-docs-operation-type": "action"
|
||||
}
|
||||
},
|
||||
"/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": {
|
||||
"/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"NewComePeople.Functions"
|
||||
|
@ -3511,7 +3511,7 @@
|
|||
{
|
||||
"name": "lastName",
|
||||
"in": "path",
|
||||
"description": "Usage: lastName={lastName}",
|
||||
"description": "Usage: lastName='{lastName}'",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
|
@ -5427,7 +5427,7 @@
|
|||
"x-ms-docs-operation-type": "function"
|
||||
}
|
||||
},
|
||||
"/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})": {
|
||||
"/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName='{userName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"People.Functions"
|
||||
|
@ -5448,7 +5448,7 @@
|
|||
{
|
||||
"name": "userName",
|
||||
"in": "path",
|
||||
"description": "Usage: userName={userName}",
|
||||
"description": "Usage: userName='{userName}'",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
|
@ -5613,7 +5613,7 @@
|
|||
"x-ms-docs-operation-type": "action"
|
||||
}
|
||||
},
|
||||
"/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})": {
|
||||
"/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName='{lastName}')": {
|
||||
"get": {
|
||||
"tags": [
|
||||
"People.Functions"
|
||||
|
@ -5634,7 +5634,7 @@
|
|||
{
|
||||
"name": "lastName",
|
||||
"in": "path",
|
||||
"description": "Usage: lastName={lastName}",
|
||||
"description": "Usage: lastName='{lastName}'",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
openapi: 3.0.1
|
||||
openapi: 3.0.1
|
||||
info:
|
||||
title: OData Service for namespace Microsoft.OData.Service.Sample.TrippinInMemory.Models
|
||||
description: This OData service is located at http://services.odata.org/TrippinRESTierService
|
||||
|
@ -914,7 +914,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/components/responses/error'
|
||||
x-ms-docs-operation-type: function
|
||||
'/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})':
|
||||
'/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')':
|
||||
get:
|
||||
tags:
|
||||
- Me.Functions
|
||||
|
@ -923,7 +923,7 @@ paths:
|
|||
parameters:
|
||||
- name: userName
|
||||
in: path
|
||||
description: 'Usage: userName={userName}'
|
||||
description: 'Usage: userName=''{userName}'''
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
|
@ -1012,7 +1012,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/components/responses/error'
|
||||
x-ms-docs-operation-type: action
|
||||
'/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})':
|
||||
'/Me/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')':
|
||||
get:
|
||||
tags:
|
||||
- Me.Functions
|
||||
|
@ -1021,7 +1021,7 @@ paths:
|
|||
parameters:
|
||||
- name: lastName
|
||||
in: path
|
||||
description: 'Usage: lastName={lastName}'
|
||||
description: 'Usage: lastName=''{lastName}'''
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
|
@ -2238,7 +2238,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/components/responses/error'
|
||||
x-ms-docs-operation-type: function
|
||||
'/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})':
|
||||
'/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')':
|
||||
get:
|
||||
tags:
|
||||
- NewComePeople.Functions
|
||||
|
@ -2254,7 +2254,7 @@ paths:
|
|||
x-ms-docs-key-type: Person
|
||||
- name: userName
|
||||
in: path
|
||||
description: 'Usage: userName={userName}'
|
||||
description: 'Usage: userName=''{userName}'''
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
|
@ -2359,7 +2359,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/components/responses/error'
|
||||
x-ms-docs-operation-type: action
|
||||
'/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})':
|
||||
'/NewComePeople/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')':
|
||||
get:
|
||||
tags:
|
||||
- NewComePeople.Functions
|
||||
|
@ -2375,7 +2375,7 @@ paths:
|
|||
x-ms-docs-key-type: Person
|
||||
- name: lastName
|
||||
in: path
|
||||
description: 'Usage: lastName={lastName}'
|
||||
description: 'Usage: lastName=''{lastName}'''
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
|
@ -3691,7 +3691,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/components/responses/error'
|
||||
x-ms-docs-operation-type: function
|
||||
'/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName={userName})':
|
||||
'/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.GetFriendsTrips(userName=''{userName}'')':
|
||||
get:
|
||||
tags:
|
||||
- People.Functions
|
||||
|
@ -3707,7 +3707,7 @@ paths:
|
|||
x-ms-docs-key-type: Person
|
||||
- name: userName
|
||||
in: path
|
||||
description: 'Usage: userName={userName}'
|
||||
description: 'Usage: userName=''{userName}'''
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
|
@ -3812,7 +3812,7 @@ paths:
|
|||
default:
|
||||
$ref: '#/components/responses/error'
|
||||
x-ms-docs-operation-type: action
|
||||
'/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName={lastName})':
|
||||
'/People/{UserName}/Microsoft.OData.Service.Sample.TrippinInMemory.Models.UpdatePersonLastName(lastName=''{lastName}'')':
|
||||
get:
|
||||
tags:
|
||||
- People.Functions
|
||||
|
@ -3828,7 +3828,7 @@ paths:
|
|||
x-ms-docs-key-type: Person
|
||||
- name: lastName
|
||||
in: path
|
||||
description: 'Usage: lastName={lastName}'
|
||||
description: 'Usage: lastName=''{lastName}'''
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
|
|
Loading…
Reference in a new issue