Skip to content

Commit ad2372a

Browse files
Handle missing ApiVersionMetadata. Fixes #891
1 parent 9da32eb commit ad2372a

File tree

2 files changed

+46
-27
lines changed

2 files changed

+46
-27
lines changed

src/AspNetCore/OData/src/Asp.Versioning.OData.ApiExplorer/ApiExplorer/ODataApiDescriptionProvider.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,12 +188,24 @@ private static bool TryMatchModelVersion(
188188
IReadOnlyList<IODataRoutingMetadata> items,
189189
[NotNullWhen( true )] out IODataRoutingMetadata? metadata )
190190
{
191-
var apiVersion = description.GetApiVersion()!;
191+
if ( description.GetApiVersion() is not ApiVersion apiVersion )
192+
{
193+
// this should only happen if an odata endpoint is registered outside of api versioning:
194+
//
195+
// builder.Services.AddControllers().AddOData(options => options.AddRouteComponents(new EdmModel()));
196+
//
197+
// instead of:
198+
//
199+
// builder.Services.AddControllers().AddOData();
200+
// builder.Services.AddApiVersioning().AddOData(options => options.AddRouteComponents());
201+
metadata = default;
202+
return false;
203+
}
192204

193205
for ( var i = 0; i < items.Count; i++ )
194206
{
195207
var item = items[i];
196-
var otherApiVersion = item.Model.GetAnnotationValue<ApiVersionAnnotation>( item.Model ).ApiVersion;
208+
var otherApiVersion = item.Model.GetAnnotationValue<ApiVersionAnnotation>( item.Model )?.ApiVersion;
197209

198210
if ( apiVersion.Equals( otherApiVersion ) )
199211
{

src/AspNetCore/OData/src/Asp.Versioning.OData/OData/ODataMultiModelApplicationModelProvider.cs

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace Asp.Versioning.OData;
66

7+
using Microsoft.AspNetCore.Http;
78
using Microsoft.AspNetCore.Mvc.ApplicationModels;
89
using Microsoft.AspNetCore.OData;
910
using Microsoft.AspNetCore.OData.Routing.Conventions;
@@ -189,41 +190,47 @@ private static void CopyApiVersionEndpointMetadata( IList<ControllerModel> contr
189190
{
190191
var selectors = actions[j].Selectors;
191192

192-
if ( selectors.Count < 2 )
193+
if ( selectors.Count > 1 && FindMetadata( selectors ) is ApiVersionMetadata metadata )
193194
{
194-
continue;
195+
NormalizeMetadata( selectors, metadata );
195196
}
197+
}
198+
}
199+
}
196200

197-
var metadata = selectors[0].EndpointMetadata.OfType<ApiVersionMetadata>().FirstOrDefault();
201+
private static ApiVersionMetadata? FindMetadata( IList<SelectorModel> selectors )
202+
{
203+
for ( var i = 0; i < selectors.Count; i++ )
204+
{
205+
var endpointMetadata = selectors[i].EndpointMetadata;
198206

199-
if ( metadata is null )
207+
for ( var j = 0; j < endpointMetadata.Count; j++ )
208+
{
209+
if ( endpointMetadata[j] is ApiVersionMetadata metadata )
200210
{
201-
continue;
211+
return metadata;
202212
}
213+
}
214+
}
203215

204-
for ( var k = 1; k < selectors.Count; k++ )
216+
return default;
217+
}
218+
219+
private static void NormalizeMetadata( IList<SelectorModel> selectors, ApiVersionMetadata metadata )
220+
{
221+
for ( var i = 0; i < selectors.Count; i++ )
222+
{
223+
var endpointMetadata = selectors[i].EndpointMetadata;
224+
225+
for ( var j = endpointMetadata.Count - 1; j >= 0; j-- )
226+
{
227+
if ( endpointMetadata[j] is ApiVersionMetadata )
205228
{
206-
var endpointMetadata = selectors[k].EndpointMetadata;
207-
var found = false;
208-
209-
for ( var l = 0; l < endpointMetadata.Count; l++ )
210-
{
211-
if ( endpointMetadata[l] is not ApiVersionMetadata )
212-
{
213-
continue;
214-
}
215-
216-
endpointMetadata[l] = metadata;
217-
found = true;
218-
break;
219-
}
220-
221-
if ( !found )
222-
{
223-
endpointMetadata.Add( metadata );
224-
}
229+
endpointMetadata.RemoveAt( j );
225230
}
226231
}
232+
233+
endpointMetadata.Insert( 0, metadata );
227234
}
228235
}
229236
}

0 commit comments

Comments
 (0)