locked
How action methods are getting mapped to request RRS feed

  • Question

  • User264732274 posted

    i just read a article where i got some confusion. the article url is http://www.c-sharpcorner.com/UploadFile/2b481f/how-to-consume-Asp-Net-web-api/

    here is the web api controller code

    public class VehicalController : ApiController
    
        {
    
            List<Vehical> model = new List<Vehical>()
    
            {
    
               new Vehical()
    
               {
    
                   Vehical_ID = 101,
    
                   Va_Cmp = "Tvera",
    
                   V_Colr = "White",
    
               },
    
               new Vehical()
    
               { 
    
                   Vehical_ID = 102,
    
                   Va_Cmp = "Toyota",
    
                   V_Colr = "Gray",
    
               },
    
               new Vehical()
    
               {
    
                   Vehical_ID = 1002,
    
                   Va_Cmp = "BMW",
    
                   V_Colr = "Red",
    
               },
    
               new Vehical()
    
               {
    
                   Vehical_ID = 1002,
    
                   Va_Cmp = "Hyundai",
    
                   V_Colr = "Black",
    
               }
    
            };
    
            public IEnumerable<Vehical> GetAllVehicals()
    
            {
    
                return model;
    
            }
    
            public Vehical GetVehicalById(int id)
    
            {
    
                var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
    
                if (car == null)
    
                {
    
                    throw new HttpResponseException(HttpStatusCode.NotFound);
    
                }
    
              return car;
    
            } 
    
          
    
        }

    when user request api/vehical then GetAllVehicals() action is getting invoke and when user request api/vehical/102 then GetVehicalById action is getting called.

    i just do not understand how this url like /vehical is getting mapped to GetAllVehicals() action method and same way how /vehical/102 is getting mapped to GetVehicalById() action.

    please help me to understand because in mvc we always mention action method name. in mvc no action method is ever invoke based on url signature. so i am bit confuse.

    looking for great explanation. thanks

    Wednesday, March 2, 2016 2:45 PM

Answers

  • User753101303 posted

    Hi,

    Basically :
    - /api/vehical allows to find the controller (VehicalController)
    - this is an HTTP get request so it looks at GetXXX methods
    - there is only a single method that takes a parameter and a single one that doesn't take a parameter so in the end  you always end up with a single method that could be called. So no problem.

    If you add another GetVehicalById2(int id) method then you'll have an error for /api/vehical/102 as then it will find two matching methods.

    Edit: you could also swap names ie have GetVehicalsById() which return all vehicles and GetAllVehicles(int id) which would return a particular vehicle. As you'll see it still works..It doesn't care about the name and is still able to select the proper method based on the parameters.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, March 2, 2016 6:55 PM
  • User36583972 posted

    Hi sudip_inn,

    Web API looks at the HTTP method, and then looks for an action whose name begins with that HTTP method name. For example, with a GET request, Web API looks for an action that starts with "Get...", such as "GetContact" or "GetAllContacts".  This convention applies only to GET, POST, PUT, and DELETE methods.

    You can enable other HTTP methods by using attributes on your controller. You can explicitly specify the name of the method (if you do not set the default route).

    I have made a sample on my side. The following code for your reference.

    WebApiConfig:

     public static void Register(HttpConfiguration config)
            {
                //.....
                // Web API routes
                config.MapHttpAttributeRoutes();
    
                config.Routes.MapHttpRoute(
                    name: "WithActionApi",
                    routeTemplate: "api/{controller}/{action}/{id}",
                     defaults: new { id = RouteParameter.Optional }
                 );
            }

    Specify the name of the method by [ActionName ( "")] attribute:

    public class VehicalController : ApiController
        {
            List<Vehical> model = new List<Vehical>()
            {
               new Vehical()
               {
                   Vehical_ID = 101,
                   Va_Cmp = "Tvera",
                   V_Colr = "White",
               },
               new Vehical()
               {
                   Vehical_ID = 102,
                   Va_Cmp = "Toyota",
                   V_Colr = "Gray",
               },
    
               new Vehical()
               {
                   Vehical_ID = 1002,
                   Va_Cmp = "BMW",
                   V_Colr = "Red",
               },
            
               new Vehical()
               {
                   Vehical_ID = 1002,
                   Va_Cmp = "Hyundai",
                   V_Colr = "Black",
               }
            };
    
            [HttpGet]
            [AllowAnonymous]
            [ActionName("GetVehicalById")]
            public Vehical GetVehicalById(int id)
            {
                var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
                if (car == null)
                {
                    throw new HttpResponseException(HttpStatusCode.NotFound);
                }
                return car;
            }
    
            [HttpGet]
            [AllowAnonymous]
            [ActionName("GetVehicalById2")]
            public Vehical GetVehicalById2(int id)
            {
                var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
                if (car == null)
                {
                    throw new HttpResponseException(HttpStatusCode.NotFound);
                }
                return car;
            }
        }
    
        public class Vehical
        {
            public int Vehical_ID { get; set; }
            public string Va_Cmp { get; set; }
            public string V_Colr { get; set; }
        }

    Icon:

    Best Regards,

    Yohann Lu

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 3, 2016 1:54 AM
  • User36583972 posted

    Hi sudip_inn,

    Why [ActionName("GetVehicalById")]
    ActionName attribute u used ? because action name attribute is used to specify different name for action but in your code you use the same action name.

    You can define a different ActionName according to your own favorite. Like the following method.

    [HttpGet]
            [AllowAnonymous]
            [ActionName("Method1")]
            public Vehical GetVehicalById(int id)
            {
                var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
                if (car == null)
                {
                    throw new HttpResponseException(HttpStatusCode.NotFound);
                }
                return car;
            }
    
            [HttpGet]
            [AllowAnonymous]
            [ActionName("Test2")]
            public Vehical GetVehicalById2(int id)
            {
                var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
                if (car == null)
                {
                    throw new HttpResponseException(HttpStatusCode.NotFound);
                }
                return car;
            }
    

    you said : "Web API looks at the HTTP method, and then looks for an action whose name begins with that HTTP method name. For example, with a GET request, Web API looks for an action that starts with "Get...", such as "GetContact" or "GetAllContacts". "

    This rule takes effect only after you set the default route (as the below).

     config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                 );

    Http Methods:
    https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

    suppose my action name in web api is AuthenticateCode then how this action can be mapped to any url. what will be url would look like ?

    If you have an action name in Web API is AuthenticateCode, You can implement different access paths through the following methods.

    1: default route(http methods)
    Method definition:

       [HttpGet]
            public IEnumerable<Vehical> AuthenticateCode()
            {
                return model;
            }

    Or:

      public IEnumerable<Vehical> GetAuthenticateCode()
            {
                return model;
            }

    Access path:
    http://localhost:29679/api/Vehical

    2: ActionName attribute

     Method definition:

       [HttpGet]
            [AllowAnonymous]
            [ActionName("AuthenticateCode")]
            public IEnumerable<Vehical> TestCode()
            {
                return model;
            }

    Access path:
    http://localhost:29679/api/Vehical/AuthenticateCode

    3: Attribute Routing
      Method definition:

     [HttpGet]
            [AllowAnonymous]
            [Route("Vehical/AuthenticateCode")]
            public IEnumerable<Vehical> TestCode()
            {
                return model;
            }

    Access path:

    http://localhost:29679/Vehical/AuthenticateCode

    More detailed information about Attribute Routing in the below:

    http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

    Best Regards,

    Yohann Lu

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 3, 2016 11:02 AM

All replies

  • User2050872319 posted

    Hi sudip_inn,

    You need to use route definitions for this. Please read the following articles on this:

     http://www.asp.net/web-api/overview/web-api-routing-and-actions/routing-in-aspnet-web-api

    http://www.asp.net/web-api/overview/web-api-routing-and-actions

    it explains pretty well how to define your routes.

    But for your case, I'd set up the following routes:

    public class VehicalController : ApiController {
    
    [HttpGet]
    [Route("vehical")]
    public IEnumerable<Vehical> GetAllVehicals() {
       return model;
    }
    
    [HttpGet]
    [Route("vehical/{id:int})"]
    public Vehical GetVehicalById(int id) {
    
       var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
       if (car == null)
       {
           throw new HttpResponseException(HttpStatusCode.NotFound);
       }
       return car;
    }       
    }


    Wednesday, March 2, 2016 6:26 PM
  • User753101303 posted

    Hi,

    Basically :
    - /api/vehical allows to find the controller (VehicalController)
    - this is an HTTP get request so it looks at GetXXX methods
    - there is only a single method that takes a parameter and a single one that doesn't take a parameter so in the end  you always end up with a single method that could be called. So no problem.

    If you add another GetVehicalById2(int id) method then you'll have an error for /api/vehical/102 as then it will find two matching methods.

    Edit: you could also swap names ie have GetVehicalsById() which return all vehicles and GetAllVehicles(int id) which would return a particular vehicle. As you'll see it still works..It doesn't care about the name and is still able to select the proper method based on the parameters.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, March 2, 2016 6:55 PM
  • User264732274 posted

    u said "If you add another GetVehicalById2(int id) method then you'll have an error for /api/vehical/102 as then it will find two matching methods."

    suppose i have two httpget functions in controller with different name. here u said i will get error. so tell me what to do to prevent error?

    GetVehicalById(int id)

    GetVehicalById2(int id)

    how to issue url as a result GetVehicalById will be called and also tell me what url i need to type to call GetVehicalById2 ?

    i am new in web api and that is why i am stuck.

    Wednesday, March 2, 2016 7:58 PM
  • User264732274 posted

    instead of attribute routing how to define route ?

    suppose i have two httpget functions in controller with different name.

    GetVehicalById(int id)

    GetVehicalById2(int id)

    how to issue url as a result GetVehicalById will be called and also tell me what url i need to type to call GetVehicalById2 ?

    Wednesday, March 2, 2016 8:00 PM
  • User36583972 posted

    Hi sudip_inn,

    Web API looks at the HTTP method, and then looks for an action whose name begins with that HTTP method name. For example, with a GET request, Web API looks for an action that starts with "Get...", such as "GetContact" or "GetAllContacts".  This convention applies only to GET, POST, PUT, and DELETE methods.

    You can enable other HTTP methods by using attributes on your controller. You can explicitly specify the name of the method (if you do not set the default route).

    I have made a sample on my side. The following code for your reference.

    WebApiConfig:

     public static void Register(HttpConfiguration config)
            {
                //.....
                // Web API routes
                config.MapHttpAttributeRoutes();
    
                config.Routes.MapHttpRoute(
                    name: "WithActionApi",
                    routeTemplate: "api/{controller}/{action}/{id}",
                     defaults: new { id = RouteParameter.Optional }
                 );
            }

    Specify the name of the method by [ActionName ( "")] attribute:

    public class VehicalController : ApiController
        {
            List<Vehical> model = new List<Vehical>()
            {
               new Vehical()
               {
                   Vehical_ID = 101,
                   Va_Cmp = "Tvera",
                   V_Colr = "White",
               },
               new Vehical()
               {
                   Vehical_ID = 102,
                   Va_Cmp = "Toyota",
                   V_Colr = "Gray",
               },
    
               new Vehical()
               {
                   Vehical_ID = 1002,
                   Va_Cmp = "BMW",
                   V_Colr = "Red",
               },
            
               new Vehical()
               {
                   Vehical_ID = 1002,
                   Va_Cmp = "Hyundai",
                   V_Colr = "Black",
               }
            };
    
            [HttpGet]
            [AllowAnonymous]
            [ActionName("GetVehicalById")]
            public Vehical GetVehicalById(int id)
            {
                var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
                if (car == null)
                {
                    throw new HttpResponseException(HttpStatusCode.NotFound);
                }
                return car;
            }
    
            [HttpGet]
            [AllowAnonymous]
            [ActionName("GetVehicalById2")]
            public Vehical GetVehicalById2(int id)
            {
                var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
                if (car == null)
                {
                    throw new HttpResponseException(HttpStatusCode.NotFound);
                }
                return car;
            }
        }
    
        public class Vehical
        {
            public int Vehical_ID { get; set; }
            public string Va_Cmp { get; set; }
            public string V_Colr { get; set; }
        }

    Icon:

    Best Regards,

    Yohann Lu

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 3, 2016 1:54 AM
  • User264732274 posted

    Why [ActionName("GetVehicalById")] ActionName attribute u used ? because action name attribute is used to specify different name for action but in your code you use the same action name.

    you said : "Web API looks at the HTTP method, and then looks for an action whose name begins with that HTTP method name. For example, with a GET request, Web API looks for an action that starts with "Get...", such as "GetContact" or "GetAllContacts". "

    suppose my action name in web api is AuthenticateCode then how this action can be mapped to any url. what will be url would look like ?

    please guide me with example for unconventional action name. thanks

    Thursday, March 3, 2016 9:26 AM
  • User36583972 posted

    Hi sudip_inn,

    Why [ActionName("GetVehicalById")]
    ActionName attribute u used ? because action name attribute is used to specify different name for action but in your code you use the same action name.

    You can define a different ActionName according to your own favorite. Like the following method.

    [HttpGet]
            [AllowAnonymous]
            [ActionName("Method1")]
            public Vehical GetVehicalById(int id)
            {
                var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
                if (car == null)
                {
                    throw new HttpResponseException(HttpStatusCode.NotFound);
                }
                return car;
            }
    
            [HttpGet]
            [AllowAnonymous]
            [ActionName("Test2")]
            public Vehical GetVehicalById2(int id)
            {
                var car = model.FirstOrDefault((I) => I.Vehical_ID == id);
                if (car == null)
                {
                    throw new HttpResponseException(HttpStatusCode.NotFound);
                }
                return car;
            }
    

    you said : "Web API looks at the HTTP method, and then looks for an action whose name begins with that HTTP method name. For example, with a GET request, Web API looks for an action that starts with "Get...", such as "GetContact" or "GetAllContacts". "

    This rule takes effect only after you set the default route (as the below).

     config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                 );

    Http Methods:
    https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html

    suppose my action name in web api is AuthenticateCode then how this action can be mapped to any url. what will be url would look like ?

    If you have an action name in Web API is AuthenticateCode, You can implement different access paths through the following methods.

    1: default route(http methods)
    Method definition:

       [HttpGet]
            public IEnumerable<Vehical> AuthenticateCode()
            {
                return model;
            }

    Or:

      public IEnumerable<Vehical> GetAuthenticateCode()
            {
                return model;
            }

    Access path:
    http://localhost:29679/api/Vehical

    2: ActionName attribute

     Method definition:

       [HttpGet]
            [AllowAnonymous]
            [ActionName("AuthenticateCode")]
            public IEnumerable<Vehical> TestCode()
            {
                return model;
            }

    Access path:
    http://localhost:29679/api/Vehical/AuthenticateCode

    3: Attribute Routing
      Method definition:

     [HttpGet]
            [AllowAnonymous]
            [Route("Vehical/AuthenticateCode")]
            public IEnumerable<Vehical> TestCode()
            {
                return model;
            }

    Access path:

    http://localhost:29679/Vehical/AuthenticateCode

    More detailed information about Attribute Routing in the below:

    http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2

    Best Regards,

    Yohann Lu

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, March 3, 2016 11:02 AM