We have an object called customer which is enhanced over the time to support new properties. We want to support both customer object version via API. I have written a few ways to support different versions but can’t achieve something simple as point (iii).
Here is the example of 2 different customer object versions that needs to be supported.
public class Customer
{
public string Name { get; set; }
}
public class CustomerVersion2 : Customer
{
public string Company { get; set; }
}
Now what is the best way to support both of the Customer object versions?
Following are the few scenarios I came up with for the web api controller implementation.
(i)
public class CustomerController : ApiController
{
public HttpResponseMessage GetCustomerById(int id)
1 Every method needs to check for version tag and return the concrete object respectively
2 The response type is of HTTPResposeMessage type therefore it doesn't know the actual returned object until the method is executed. Because of this I cannot use the 3rd party tools to generate help for me.
(ii)
We have to support all the previous exposure of web api for the new version as well therefore new CustomerVersion2Controller inherits all the exposures from base one. Here we don't have “if else” logic in every method instead the logic sits at higher level
to divert the call to specific controller version. Ref:
http://seroter.wordpress.com/2012/09/25/versioning-asp-net-web-api-services-using-http-headers/
public class CustomerController : ApiController
{
public virtual HttpResponseMessage GetCustomerById(int id)
1 The response type is of HTTPResposeMessage type therefore it doesn't know the actual returned object until the execution time. Because of this I cannot use the 3rd party tools to generate help for me.
(iii)
Following would be ideal but doesn’t work for obvious reason (error - multiple actions were found that matched the request)
public class CustomerController : ApiController
{
public Customer GetCustomerById(int id)
{
return restService.GetCustomerById(id);
}
}
public class CustomerVersion2Controller : CustomerController
{
public new CustomerVersion2 GetCustomerById(int id)
{
return restService.GetCustomerById(id);
}
}
Disadvantages:
1 Error - multiple actions were found that matched the request
(iv)
In this option we don’t inherit the controller, instead we guide the request in such a way that if we can’t serve the request using the requested version then we try to serve it using the previous version controller.
public class CustomerController : ApiController
{
public Customer GetCustomerById(int id)
{
return restService.GetCustomerById(id);
}
}
public class CustomerVersion2Controller : ApiController
{
public CustomerVersion2 GetCustomerById(int id)
{
return restService.GetCustomerById(id);
}
}
Disadvantages:
1 Error – Visibility to inheritance is lost.
Please advice what is the best way to resolve the inheritance issue or any other approach that should be taken.
What formats so you support? If you only support JSON and will never remove a property, just ignore versioning. If you need additional, more rigid, media types, consider minting your own, e.g. application/vnd.customer.1+json, and negotiate the returned value
with the accept header.
i support xml and json format as they are out of the box. I have to support versioning for my existing clients. i am already negotiating the returned value base on one of the header tag. I think i couldn't explain the issue very well before. i am trying
to have a consistent interface for all the different versions of API. One way to acheive this is by applying a common interface to both the different version of contollers (in my case customerController and CustomerVersion2Controller) . But by doing so i cannot
return the concrete model, instead i have to return a base type or HttpResponseMessage.
eg
first controller:
class CustomerController : ICustomer
public Customer GetById(int id)
Second Controller:
class CustomerVersion2Controller : ICustomer
public Customer GetById(int id)
As you can see that i have applied an interface so that i can be consistent between two different version controllers, unfortunately i loose my concrete exposure in case of second Controller.
that is public CustomerVersion2 GetById(int id)
I can clearly see that i can't have both the consistency and the concrete model types, so was just speculating if there is any other way to do so. some magic that i am not aware of :)
GauravGoyal
Member
3 Points
9 Posts
What is the best way to implement different versions of resources via WEB API? I have tried a few...
Feb 13, 2013 04:31 AM|LINK
We have an object called customer which is enhanced over the time to support new properties. We want to support both customer object version via API. I have written a few ways to support different versions but can’t achieve something simple as point (iii).
Here is the example of 2 different customer object versions that needs to be supported.
public class Customer
{
public string Name { get; set; }
}
public class CustomerVersion2 : Customer
{
public string Company { get; set; }
}
Now what is the best way to support both of the Customer object versions?
Following are the few scenarios I came up with for the web api controller implementation.
(i)
public class CustomerController : ApiController
{
public HttpResponseMessage GetCustomerById(int id)
{
if (RequestedVersion == "Version2")
{
var restService = new CustomerVersion2Service();
HttpResponseMessage response = request.CreateResponse<CustomerVersion2>(HttpStatusCode.OK, restService.GetCustomerById(id));
return response;
}
else
{
var restService = new CustomerService();
HttpResponseMessage response = Request.CreateResponse<Customer>(HttpStatusCode.OK, restService.GetCustomerById(id));
return response;
}
}
}
Disadvantages:
1 Every method needs to check for version tag and return the concrete object respectively
2 The response type is of HTTPResposeMessage type therefore it doesn't know the actual returned object until the method is executed. Because of this I cannot use the 3rd party tools to generate help for me.
(ii)
We have to support all the previous exposure of web api for the new version as well therefore new CustomerVersion2Controller inherits all the exposures from base one. Here we don't have “if else” logic in every method instead the logic sits at higher level to divert the call to specific controller version. Ref: http://seroter.wordpress.com/2012/09/25/versioning-asp-net-web-api-services-using-http-headers/
public class CustomerController : ApiController
{
public virtual HttpResponseMessage GetCustomerById(int id)
{
HttpResponseMessage response = Request.CreateResponse<Customer>(HttpStatusCode.OK, restService.GetCustomerById(id));
return response;
}
}
public class CustomerVersion2Controller : CustomerController
{
public override HttpResponseMessage GetCustomerById(int id)
{
var restService = new CustomerVersion2Service();
HttpResponseMessage response = Request.CreateResponse<CustomerVersion2>(HttpStatusCode.OK, restService.GetCustomerById(id));
return response;
}
}
Disadvantages:
1 The response type is of HTTPResposeMessage type therefore it doesn't know the actual returned object until the execution time. Because of this I cannot use the 3rd party tools to generate help for me.
(iii)
Following would be ideal but doesn’t work for obvious reason (error - multiple actions were found that matched the request)
public class CustomerController : ApiController
{
public Customer GetCustomerById(int id)
{
return restService.GetCustomerById(id);
}
}
public class CustomerVersion2Controller : CustomerController
{
public new CustomerVersion2 GetCustomerById(int id)
{
return restService.GetCustomerById(id);
}
}
Disadvantages:
1 Error - multiple actions were found that matched the request
(iv)
In this option we don’t inherit the controller, instead we guide the request in such a way that if we can’t serve the request using the requested version then we try to serve it using the previous version controller.
public class CustomerController : ApiController
{
public Customer GetCustomerById(int id)
{
return restService.GetCustomerById(id);
}
}
public class CustomerVersion2Controller : ApiController
{
public CustomerVersion2 GetCustomerById(int id)
{
return restService.GetCustomerById(id);
}
}
Disadvantages:
1 Error – Visibility to inheritance is lost.
Please advice what is the best way to resolve the inheritance issue or any other approach that should be taken.
panesofglass
Member
730 Points
237 Posts
Re: What is the best way to implement different versions of resources via WEB API? I have tried a...
Feb 13, 2013 11:04 AM|LINK
GauravGoyal
Member
3 Points
9 Posts
Re: What is the best way to implement different versions of resources via WEB API? I have tried a...
Feb 17, 2013 09:34 AM|LINK
i support xml and json format as they are out of the box. I have to support versioning for my existing clients. i am already negotiating the returned value base on one of the header tag. I think i couldn't explain the issue very well before. i am trying to have a consistent interface for all the different versions of API. One way to acheive this is by applying a common interface to both the different version of contollers (in my case customerController and CustomerVersion2Controller) . But by doing so i cannot return the concrete model, instead i have to return a base type or HttpResponseMessage.
eg
first controller:
class CustomerController : ICustomer
public Customer GetById(int id)
Second Controller:
class CustomerVersion2Controller : ICustomer
public Customer GetById(int id)
As you can see that i have applied an interface so that i can be consistent between two different version controllers, unfortunately i loose my concrete exposure in case of second Controller.
that is public CustomerVersion2 GetById(int id)
I can clearly see that i can't have both the consistency and the concrete model types, so was just speculating if there is any other way to do so. some magic that i am not aware of :)