Is there a way to perform parameter type based overloading of an Action method ? i.e. Is it possible to do the following in a Controller
public class MyController : ApiController { public Foo Get(int id) { //whatever } public Foo Get(string id) { //whatever } public Foo Get(Guid id) { //whatever } }
If so, what changes need to be made to the Route table.
Method overloading can be done in a web service with the following things: By changing the number of parameters used. By changing the order of parameters. By using different data types for the parameters.
If we have to overload the action Method in asp.net MVC then we can not do it directly. We have to change the ActionName like this code snippet. Now to run the controller GetEmpName action method with just give the URL like this: http://localhost:49389/Home/GetEmpName.
Overloading methods is a strong concept in API design, especially when your API is a fluent API or DSL (Domain Specific Language). This is the case for jOOQ, where you often want to use the exact same method name for various means of interaction with the library.
This is a very common interview question as well: Is it possible to overload a web method in a web service? The answer is yes, you need to use MessageName property for this.
This kind of scenario is not well supported by the standard routing methods.
You may want to use attribute based routing instead as this gives you a lot more flexibility.
Specifically look at the route constraints where you can route by the type:
// Type constraints [GET("Int/{x:int}")] [GET("Guid/{x:guid}")]
Anything else will turn into a bit of a hack... e.g.
If you did attempt it using standard routing you would probably need to route to the correct action via it's name, then use reg ex's constraints (e.g. guid) to route to the required default action.
Controllers:
public class MyController : ApiController { [ActionName("GetById")] public Foo Get(int id) { //whatever } [ActionName("GetByString")] public Foo Get(string id) { //whatever } [ActionName("GetByGUID")] public Foo Get(Guid id) { //whatever } }
Routes:
//Should match /api/My/1 config.Routes.MapHttpRoute( name: "DefaultDigitApi", routeTemplate: "api/{controller}/{id}", defaults: new { action = "GetById" }, constraints: new { id = @"^\d+$" } // id must be digits ); //Should match /api/My/3ead6bea-4a0a-42ae-a009-853e2243cfa3 config.Routes.MapHttpRoute( name: "DefaultGuidApi", routeTemplate: "api/{controller}/{id}", defaults: new { action = "GetByGUID" }, constraints: new { id = @"^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$" } // id must be guid ); //Should match /api/My/everything else config.Routes.MapHttpRoute( name: "DefaultStringApi", routeTemplate: "api/{controller}/{id}", defaults: new { action = "GetByString" } );
Updated
I would normally use a POST if doing a FromBody (perhaps use the FromUri with the model instead) but your requirements could be met by adding the following.
For the controller
[ActionName("GetAll")] public string Get([FromBody]MyFooSearch model) { if (model != null) { //search criteria at api/my } //default for api/my } //should match /api/my config.Routes.MapHttpRoute( name: "DefaultCollection", routeTemplate: "api/{controller}", defaults: new { action = "GetAll" } );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With