Custom Method Names

by Sachin Singh


Posted on Thursday, 14 May 2020

Tags: Custom method names in web api how to map custom method names

Asp.Net Web API follows a convention to map the HTTP Request to the appropriate Method Name, which is very logical and appreciating in my point of view. What are the conventions and why am I saying it logical will be revealed soon.

Before that, try to think about some URLs of a service implemented in Web API. You will find almost every URL like
http://www.mysite.com/EmployeeService,
http://www.mysite.com/whetherService/newyork.

As you can see, there is no need to provide the method name in the URL, if you know what the Service provides you can even guess the controller name and you do not need to go through the API documentation thoroughly, and only knowing the controller name is enough too. But, this is not the only reason, the root reasoning behind is to follow the Rest principle.

We know, the Asp.Net Web API is used to create Restful services, and the Rest says that the interface must be simple which indirectly points towards the URL that it must be simple. The absence of the Method name actually supports this principle and clients do not have to worry about the method names to consume the service.

For example if a service says, I am a weather forecast service and you can use me to know the weather of any city or average weather in a particular year then the obvious URLs should be,
http://www.mysite.com/weatherservice/newyork ,
http://www.mysite.com/weatherservice/newyork/1995 etc.

And the not so obvious URLs could be
http://www.mysite.com/weatherservice/loadwheatherReport/newyork.

Such URLs indicates, there is a violation of the Rest principle and the interface is not that simple as it should be. Also, the client will have to go through the API documentation thoroughly and remember the method names.

So, the Web API follows some convention to map the method names to the HTTP requests to keep the URL simple.

What are the convention?

Following are the conventions ,which the web API follows:-
  1. If the method name is the same as the HTTP verb name, then the corresponding request will be auto-mapped to the appropriate method.
for example, Get() will be mapped with getting requests. similarly, Post() will be mapped with Post request.
  2.If the Method name is prefixed with http verb ,then also the request will be mapped depending upon the request type.
For example, getAllEmployee() will be mapped with get Request .
  3.If the method name is neither the HTTP verb like Get(), Post() nor it starts with the HTTP verb, then the request will not map with the method, and an error will be thrown.
for example, LoadEmployee() will not map with the get request http://localhost/Employee and it will throw a 405 method not allowed error, stating the requested resource doesn't support HTTP method 'Get'.

But perhaps, Microsoft web API team knew that the developers are creative people and they may name the method anything they wish, also many organizations strictly follow some naming convention so they came with solutions in the form of attributes. In short, web API provides us different attributes that are used to map custom named methods in the controller class to http verbs(request).

Attributes Maps to http verbs
[httpGet] Get
[httpPost] Post
[httpPut] Put
[httpDelete] Delete

Now ,it's time to take some examples.

Test the conventions

I am taking the same example of previous article. Here I have created a get method under Employee Controller which returns all employee from database . The URL:- http://localhost/12345/Api/Employee.


     public HttpResponseMessage Get()
        {
            try
            {
             using(TestDbContext db=new TestDbContext()){
                List Employees = db.Employees.ToList();
                if(Employees!=null){
                     return Request.CreateResponse(HttpStatusCode.OK, Employees);
                }
               return Request.CreateErrorResponse(HttpStatusCode.NotFound,"No result found");
            }
      }
            catch{
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
           
        }

Now fire a get request from a browser or any tool like Fiddler, you will notice that the request gets easily mapped even when the URL doesn't contain the method name. It is because of the convention which says a get request will be mapped to a method with the name Get().

similarly, the below get method will also be mapped because of the convention that if a method name starts with the word Get then it will be mapped to Get requests.


    public HttpResponseMessage GetAllEmployee()
        {
         try
            {
             using(TestDbContext db=new TestDbContext()){
                List Employees = db.Employees.ToList();
                if(Employees!=null){
                     return Request.CreateResponse(HttpStatusCode.OK, Employees);
                }
               return Request.CreateErrorResponse(HttpStatusCode.NotFound,"No result found");
            }
        }
            catch{
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
           
        }

Now change the method name to something else which violate the convention like below and fire a get request.


    public HttpResponseMessage LoadEmployee()
        {
        try
            {
             using(TestDbContext db=new TestDbContext()){
                List Employees = db.Employees.ToList();
                if(Employees!=null){
                     return Request.CreateResponse(HttpStatusCode.OK, Employees);
                }
               return Request.CreateErrorResponse(HttpStatusCode.NotFound,"No result found");
            }
        }
            catch{
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
           
        }

error
Error

As you can see, we are getting the expected error stating "The requested resource does not support http method 'GET'."

The solution : use attributes

Now , move towards the proposed solution and mark the method with [HttpGet] attribute. And again run the application.


   [httpGet]
   public HttpResponseMessage LoadEmployee()
        {
          try
            {
             using(TestDbContext db=new TestDbContext()){
                List Employees = db.Employees.ToList();
                if(Employees!=null){
                     return Request.CreateResponse(HttpStatusCode.OK, Employees);
                }
               return Request.CreateErrorResponse(HttpStatusCode.NotFound,"No result found");
            }
       }
            catch{
                return new HttpResponseMessage(HttpStatusCode.InternalServerError);
            }
           
        }

Now ,you can notice that even though our method name is not prefixed with 'get' ,yet it gets mapped with the get request, as the method is marked with [HttpGet] attribute.

similarly ,you can mark any method with appropriate attribute when the method name is different than the convention.