Search code examples
c#asp.net-web-apiasp.net-web-api-routing

WebApi versioning a single controller


I am just starting to get into WebApi and what I am trying to understand is if you can have 1 controller that handles multiple versions.

so instead of having a v1/v2 folders where v2 has a copy of the controller in v1 but the logic in v2 is different from v1

Can you have 1 controller that what will handle all api versions?

I have seen reference to [APiVersion(...)] attribute on a controller but when I try to implement what I thought is right nothing gets called

Example:

[ApiVersion("1.0")]
[ApiVersion("2.0")]
[Route("api/v{version:apiVersion}/login")]
public class LoginController : ApiController
{

    [HttpGet]
    [MapToApiVersion("1.0")]
    [Route("login/{username}/{password}")]
    [ResponseType(typeof(LoginResult))]
    public LoginResult GetLoginInfo(string username, string password)
    {
        //v1 logic
    }

    [HttpGet]
    [MapToApiVersion("2.0")]
    [Route("login/{username}/{password}")]
    [ResponseType(typeof(LoginResult))]
    public LoginResult GetLoginInfo2(string username, string password)
    {
        //v2 logic
    }
}

I used this answer as a reference but it does not seem to work. Is using actions the way to solve this?

Ideally I would just like to be able to change the version number anywhere that it gets called instead of changing the action name but I don't know if that's possible


Solution

  • One approach could be to just make sure the routes do not clash by putting the version directly in the route of the single controller.

    public class LoginController : ApiController {
    
        [HttpGet]
        [Route("~/api/v1/login/{username}/{password}")]
        [ResponseType(typeof(LoginResult))]
        public LoginResult GetLoginInfo(string username, string password) {
            //v1 logic
        }
    
        [HttpGet]
        [Route("~/api/v2/login/{username}/{password}")]
        [ResponseType(typeof(LoginResult))]
        public LoginResult GetLoginInfo2(string username, string password) {
            //v2 logic
        }
    } 
    

    Now if a new version is added, just include that version number in the route.

    [HttpGet]
    [Route("~/api/v3/login/{username}/{password}")]
    [ResponseType(typeof(LoginResult))]
    public LoginResult GetLoginInfo3(string username, string password) {
        //v3 logic
    }
    

    Keep it Simple...