Skip to content

Commit cb7a153

Browse files
Update examples to show extracting a related key from a URI
1 parent 244d179 commit cb7a153

File tree

8 files changed

+100
-13
lines changed

8 files changed

+100
-13
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
namespace ApiVersioning.Examples;
2+
3+
using Microsoft.AspNet.OData.Extensions;
4+
using Microsoft.OData.UriParser;
5+
using System.Web.Http;
6+
7+
internal static class ODataExtensions
8+
{
9+
public static IReadOnlyDictionary<string, object> GetRelatedKeys( this ApiController controller, Uri uri )
10+
{
11+
var request = controller.Request;
12+
var pathHandler = request.GetPathHandler();
13+
var serviceRoot = controller.Url.CreateODataLink();
14+
var path = pathHandler.Parse( serviceRoot, uri.AbsoluteUri, request.GetRequestContainer() );
15+
var keys = new Dictionary<string, object>( StringComparer.OrdinalIgnoreCase );
16+
17+
if ( path.Segments.OfType<KeySegment>().FirstOrDefault<KeySegment>() is KeySegment segment )
18+
{
19+
foreach ( var pair in segment.Keys )
20+
{
21+
keys.Add( pair.Key, pair.Value );
22+
}
23+
}
24+
25+
return keys;
26+
}
27+
28+
public static object GetRelatedKey( this ApiController controller, Uri uri ) => controller.GetRelatedKeys( uri ).Values.SingleOrDefault();
29+
}

examples/AspNet/OData/OpenApiODataWebApiExample/V3/AcmeController.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ public class AcmeController : ODataController
3737
/// <param name="link">The product identifier.</param>
3838
/// <returns>None</returns>
3939
[HttpPost]
40-
public IHttpActionResult CreateRef( string navigationProperty, [FromBody] Uri link ) => StatusCode( NoContent );
40+
public IHttpActionResult CreateRef( string navigationProperty, [FromBody] Uri link )
41+
{
42+
var relatedKey = this.GetRelatedKey( link );
43+
return StatusCode( NoContent );
44+
}
4145

4246
/// <summary>
4347
/// Unlinks a product from a supplier.

examples/AspNet/OData/OpenApiODataWebApiExample/V3/ProductsController.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,11 @@ public IHttpActionResult GetRefToSupplier( [FromODataUri] int key, string naviga
189189
public IHttpActionResult CreateRefToSupplier(
190190
[FromODataUri] int key,
191191
string navigationProperty,
192-
[FromBody] Uri link ) => StatusCode( NoContent );
192+
[FromBody] Uri link )
193+
{
194+
var relatedKey = this.GetRelatedKey( link );
195+
return StatusCode( NoContent );
196+
}
193197

194198
/// <summary>
195199
/// Unlinks a supplier from a product.

examples/AspNet/OData/OpenApiODataWebApiExample/V3/SuppliersController.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,11 @@ public IQueryable<Product> GetProducts( [FromODataUri] int key ) =>
133133
public IHttpActionResult CreateRefToProducts(
134134
[FromODataUri] int key,
135135
string navigationProperty,
136-
[FromBody] Uri link ) => StatusCode( NoContent );
136+
[FromBody] Uri link )
137+
{
138+
var relatedKey = this.GetRelatedKey( link );
139+
return StatusCode( NoContent );
140+
}
137141

138142
/// <summary>
139143
/// Unlinks a product from a supplier.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
namespace ApiVersioning.Examples;
2+
3+
using Microsoft.AspNetCore.Mvc;
4+
using Microsoft.AspNetCore.OData.Extensions;
5+
using Microsoft.OData;
6+
using Microsoft.OData.UriParser;
7+
8+
internal static class ODataExtensions
9+
{
10+
public static IReadOnlyDictionary<string, object> GetRelatedKeys( this ControllerBase controller, Uri uri )
11+
{
12+
// REF: https://github.com/OData/AspNetCoreOData/blob/main/src/Microsoft.AspNetCore.OData/Routing/Parser/DefaultODataPathParser.cs
13+
var feature = controller.HttpContext.ODataFeature();
14+
var model = feature.Model;
15+
var serviceRoot = new Uri( new Uri( feature.BaseAddress ), feature.RoutePrefix );
16+
var requestProvider = feature.Services;
17+
var parser = new ODataUriParser( model, serviceRoot, uri, requestProvider );
18+
19+
parser.Resolver ??= new UnqualifiedODataUriResolver() { EnableCaseInsensitive = true };
20+
parser.UrlKeyDelimiter = ODataUrlKeyDelimiter.Slash;
21+
22+
var path = parser.ParsePath();
23+
var segment = path.OfType<KeySegment>().FirstOrDefault<KeySegment>();
24+
25+
if ( segment is null )
26+
{
27+
return new Dictionary<string, object>( capacity: 0 );
28+
}
29+
30+
return new Dictionary<string, object>( segment.Keys, StringComparer.OrdinalIgnoreCase );
31+
}
32+
33+
public static object GetRelatedKey( this ControllerBase controller, Uri uri ) => controller.GetRelatedKeys( uri ).Values.SingleOrDefault();
34+
}

examples/AspNetCore/OData/ODataOpenApiExample/V3/AcmeController.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,11 @@ public class AcmeController : ODataController
4444
[ProducesResponseType( Status404NotFound )]
4545
public IActionResult CreateRef(
4646
string navigationProperty,
47-
[FromBody] Uri link ) => NoContent();
47+
[FromBody] Uri link )
48+
{
49+
var relatedKey = this.GetRelatedKey( link );
50+
return NoContent();
51+
}
4852

4953
/// <summary>
5054
/// Unlinks a product from a supplier.

examples/AspNetCore/OData/ODataOpenApiExample/V3/ProductsController.cs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ public class ProductsController : ODataController
2020
{
2121
private readonly IQueryable<Product> products = new[]
2222
{
23-
NewProduct( 1 ),
24-
NewProduct( 2 ),
23+
NewProduct( 1 ),
24+
NewProduct( 2 ),
2525
NewProduct( 3 ),
2626
}.AsQueryable();
2727

@@ -191,9 +191,13 @@ public IActionResult GetRef( int key, string navigationProperty )
191191
[ProducesResponseType( Status204NoContent )]
192192
[ProducesResponseType( Status404NotFound )]
193193
public IActionResult CreateRef(
194-
int key,
195-
string navigationProperty,
196-
[FromBody] Uri link ) => NoContent();
194+
int key,
195+
string navigationProperty,
196+
[FromBody] Uri link )
197+
{
198+
var relatedKey = this.GetRelatedKey( link );
199+
return NoContent();
200+
}
197201

198202
/// <summary>
199203
/// Unlinks a supplier from a product.
@@ -206,7 +210,7 @@ public IActionResult CreateRef(
206210
[ProducesResponseType( Status204NoContent )]
207211
[ProducesResponseType( Status404NotFound )]
208212
public IActionResult DeleteRef(
209-
int key,
213+
int key,
210214
string navigationProperty,
211215
int relatedKey ) => NoContent();
212216

examples/AspNetCore/OData/ODataOpenApiExample/V3/SuppliersController.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,13 @@ public IQueryable<Product> GetProducts( int key ) =>
162162
[ProducesResponseType( Status204NoContent )]
163163
[ProducesResponseType( Status404NotFound )]
164164
public IActionResult CreateRef(
165-
int key,
166-
string navigationProperty,
167-
[FromBody] Uri link ) => NoContent();
165+
int key,
166+
string navigationProperty,
167+
[FromBody] Uri link )
168+
{
169+
var relatedKey = this.GetRelatedKey( link );
170+
return NoContent();
171+
}
168172

169173
/// <summary>
170174
/// Unlinks a product from a supplier.

0 commit comments

Comments
 (0)