I'm having an issue with API Versioning (ASP.NET Core API 2.1). I'm trying to supplant one method of an existing controller without having to copy all of the methods in the previous version. I assumed this would work but it gives me a problem with routing conflicts. Example:
namespace MyApi.Controllers
{
[Produces("application/json")]
[Route("api/v{version:apiVersion}")]
public class BaseController : Controller
{
public string VersionNumber => GetRouteValue<string>(ControllerContext, "version");
protected static TValue GetRouteValue<TValue>(ControllerContext context, string name)
{
return (TValue)Convert.ChangeType(context.RouteData.Values[name], typeof(TValue));
}
}
}
namespace MyApi.Controllers
{
[ApiVersion("1.0")]
[ApiVersion("2.0")]
public class ValuesController : BaseController
{
[HttpGet("values", Name = "GetValuesV1.0")]
public IActionResult GetValues() => Ok(new string[] { "value 1", "value 2" });
[HttpGet("values/{value}", Name = "GetValueV1.0")]
public IActionResult GetValue(string value) => Ok( value });
}
}
namespace MyApi.Controllers.V2_0
{
[ApiVersion("2.0")]
public class ValuesController : BaseController
{
[HttpGet("values", Name = "GetValuesV2.0")]
public IActionResult GetValues() => Ok(new string[] { "value 1", "value 2", "value 3" });
}
}
I then get the error:
The method 'Get' on path 'xxx' is registered multiple times.
I want to support the method GetValue(string value) in both versions, but I don't want to duplicate the code in the new controller every time I version. I just want to supplant one single method. Is this possible, or do I have to copy the entire previous controller and every method in it? This works, but feels horrible:
namespace MyApi.Controllers
{
[Produces("application/json")]
[Route("api/v{version:apiVersion}")]
public class BaseController : Controller
{
public string VersionNumber => GetRouteValue<string>(ControllerContext, "version");
protected static TValue GetRouteValue<TValue>(ControllerContext context, string name)
{
return (TValue)Convert.ChangeType(context.RouteData.Values[name], typeof(TValue));
}
}
}
namespace MyApi.Controllers
{
[ApiVersion("1.0")]
public class ValuesController : BaseController
{
[HttpGet("values", Name = "GetValuesV1.0")]
public IActionResult GetValues() => Ok(new string[] { "value 1", "value 2" });
[HttpGet("values/{value}", Name = "GetValueV1.0")]
public IActionResult GetValue(string value) => Ok( value });
}
}
namespace MyApi.Controllers.V2_0
{
[ApiVersion("2.0")]
public class ValuesController : BaseController
{
[HttpGet("values", Name = "GetValuesV2.0")]
public IActionResult GetValues() => Ok(new string[] { "value 1", "value 2", "value 3" });
[HttpGet("values/{value}", Name = "GetValueV2.0")]
public IActionResult GetValue(string value) => Ok( value });
}
}
This now works, but I've just duplicated code for no reason. In controllers with lots of code this just feels like code smell. Is there a workaround?