'Rest APi How to route based api versioning

I have a method called GetMessage, it is called like so:

localhost/GetMessage?id={{NewMessage}}

i have now decided to start following standard practises and ommit the "get" keyword from the route and make it like so:

localhost/message?id={{NewMessage}}

however, i do not want to break any existing clients I already have looking at the first route and force them to update. the underlying function will not change, it will just be the route.

my first solution to this problem was to do this:

picture showing the new function that just calls the old function

Although THIS WORKS i realised, i have like 35 functions just like this one, i do not wanna duplicate all those functions.

Is it not possible to add 2 [httpget] attributes to a function each with a different apiversion that would only be accessible if the header specifically has that version.

so something like this:

enter image description here

this way client will be able to upgrade in their own time when they need.

is this possible or would i have to go with my first solution?

Extra info:

my configure services method:

enter image description here



Solution 1:[1]

Generally , the method with different version has the same route, So we configure like this:

services.AddApiVersioning(o =>
    {
        o.ReportApiVersions = true;
        o.AssumeDefaultVersionWhenUnspecified = true;
        o.DefaultApiVersion = new ApiVersion(1, 0);
        o.ApiVersionReader = new HeaderApiVersionReader("x-api-version");
    });

And user add request header(x-api-version=xxxx) to access method with the specified version

But in your code, Different versions of methods have different routes, So We can't use the method mentioned above.

I use Action filters to achieve a similar effect, I write a simple demo here.

Action filters

public class Action1filter : Attribute,IActionFilter
    {
        private readonly string _header;
        private readonly string _value;
        public void OnActionExecuted(ActionExecutedContext context){}

        public void OnActionExecuting(ActionExecutingContext context  )
        {
            if ((context.HttpContext.Request.Headers.FirstOrDefault(x => x.Key == _header).Value.FirstOrDefault() != _value) || context.HttpContext.Request.Headers.FirstOrDefault(x => x.Key == _header).Value.FirstOrDefault() == null)
            {
                context.Result= new BadRequestObjectResult("");
            }          
        }     
    }

your method

 HttpGet("message"), ApiVersion("2.0"), Action1filter("version", "2.0")]
    public IActionResult GetMessage2([FromQuery] string Id)
    {
        return GetMessage(Id);
    } 
   
    [HttpGet("GetMessage"),ApiVersion("1.0",Deprecated =true), Action1filter("version", "1.0")]
   public IActionResult GetMessage([FromQuery]string Id)
    {
        return Ok(Id);
    }

I add the ActionFilter in your action, So only the request with header version=2.0 can access the method by localhost/message?id={{NewMessage}}

But you can't use this method in your second solution, Because one [Action1filter()] will work on both paths.

In my opinion, I prefer to add [Route("xxx/{version:apiVersion}")] to access method with different versions in this situation

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1