Replies: 3 comments 6 replies
-
I have a couple of follow-up questions. Question 1
In which scenario would an exception be thrown? There were already very few cases (ex: Great care is taken to avoid exceptions. Very few things are exceptional. An Question 2
Do you have the world's simplest setup or example of this? This appears to imply you used a custom I'm not sure I agree with implicitly changing versions in a request. Versions should be explicit from the client and exactly match to the server. That's the only way to reason about things deterministically. If one or more preview versions happens to be the same as the official release, why not just define that the real service supports both versions? The client doesn't know how you've mapped things on the server. A trivial example: [ApiVersion("2023-01-01")]
[ApiVersion("2023-01-01-preview")]
[Route("my/api")]
public class MyApiController : ControllerBase
{
} Requesting If you really want to remap things, it can also be done without having to resort to changing the routing. Since your app is aware of the versions it does and doesn't support, you can use the world's simplest middleware: internal sealed class ApiStatusMapper
: Dictionary<ApiVersion, Dictionary<String, String>>
{
public ApiStatusMapper()
{
var comparer = StringCompare.OrdinalIgnoreCase;
this[new(new DateOnly(2022, 01, 01))] = new(comparer)
{
[string.Empty] = "obsolete",
};
this[new(new DateOnly(2023, 01, 01))] = new(comparer)
{
["preview"] = string.Empty,
};
}
}
builder.Services.AddSingleton<ApiStatusMapper>();
var app = builder.Build();
app.Use((context, next) => {
var feature = context.ApiVersioningFeature();
if ( feature.RawRequestedApiVersions.Count == 1 &&
feature.RequestedApiVersion is {} version )
{
var mapper = context.RequestServices.GetRequiredService<ApiStatusMapper>();
if ( mapper.TryGetValue( version, out var statuses ) &&
statuses.TryGetValue( version.Status ?? string.Empty, out var status ) )
{
feature.RequestedApiVersion = new( version.GroupVersion.Value, status );
}
}
return next(context);
}); As long as it's registered fairly early in the pipeline, that should allow:
without having to mess around with routing. |
Beta Was this translation helpful? Give feedback.
-
@commonsensesoftware Might be helpful to explain why we want to do this... When we introduce a new preview version of an API, e.g. We are a large company with a lot of products and microservices and so we maintain common libraries for them. These include a MatcherPolicy that handled this and could do it without specific knowledge of services' version models. I think the suggestion to use middleware above would require each service to supply their own mappings (as versions will vary between services), which is a fair bit of work to introduce and maintain. Is there no way to get it working as it worked before? edit: I can put together a minimal repro if it helps |
Beta Was this translation helpful? Give feedback.
-
Thanks @commonsensesoftware, looks like there are some really great extension points in this library! To clarify, we do want to report the preview version, but not the “dummy” preview versions we would be adding to deprecated and stable version controllers if we followed your suggestion. I don’t doubt we could tweak some of your above examples to work the way we need, but to clarify, the current solution we arrived at doesn’t muck around with routing. We use the simple middleware you suggested to alter the incoming requested version ahead of the default routing, only instead of a hardcoded mapping dictionary, we use the description provider to help us. This works for all our current implementations and doesn’t require them to make any changes (e.g. decorate controllers with additional versions). If we find issues, I’ll certainly take a look at the above again. Thanks for your time and for explaining things so clearly. |
Beta Was this translation helpful? Give feedback.
-
In version 5.0.0 we were able to use custom selectors and policies to specify how the version is selected so that when an api moved from preview to release calls would continue to be handled i.e. using a custom poiicy, requesting 2020-01-01-preview would match to version 2020-01-01. However it looks like the behaviours changed to allow the request to be rejected with a 4xx error instead of an exception later on in the process so ideally it would be good to have a method to override the feature check that uses the jump table.
A use case would be when swapping over slots so versions might change
2022-01-01 => 2022-01-01-obsolete
2023-01-01-preview => 2023-01-01
Requests using the preview api now fail despite the custom policy supporting the status change
Beta Was this translation helpful? Give feedback.
All reactions