Friday, April 8, 2016

Attribute Routing in ASP.NET Web API 2

Attribute Routing in ASP.NET Web API 2

Concert crowd

In the last article we’ve seen how can we inject multiple parameters to Web API method the same can be achieve using route attribute in Web API. Though there were little challenges which I will also describe in this article which may reduce your development time for sure. Excerpt from asp.net about routing,
"Routing is how Web API matches a URI to an action. Web API 2 supports a new type of routing, called attribute routing. As the name implies, attribute routing uses attributes to define routes. Attribute routing gives you more control over the URIs in your web API. For example, you can easily create URIs that describe hierarchies of resources.The earlier style of routing, called convention-based routing, is still fully supported. In fact, you can combine both techniques in the same project".

The website also stated why Attribute Routing is required,
"The first release of Web API used convention-based routing. In that type of routing, you define one or more route templates, which are basically parameterized strings. When the framework receives a request, it matches the URI against the route template. One advantage of convention-based routing is that templates are defined in a single place, and the routing rules are applied consistently across all controllers".

Enabling Attribute Routing
To enable attribute routing, call MapHttpAttributeRoutes during configuration. This extension method is defined in the System.Web.Http.HttpConfigurationExtensions class. Kindy have a look at the code shown below as well as an image depicted below:

  1. namespace WebApiDemo 
  2.     public static class WebApiConfig 
  3.     { 
  4.         public static void Register(System.Web.Http.HttpConfiguration config) 
  5.         { 
  6.             config.MapHttpAttributeRoutes(); 
  7.             config.Routes.MapHttpRoute( 
  8.                 name: "DefaultApi", 
  9.                 routeTemplate: "api/{controller}/{action}/{id}", 
  10.                 defaults: new
  11.                 { 
  12.                     id = RouteParameter.Optional 
  13.                 } 
  14.             ); 
  15.         } 
  16.     } 

Here, I’ve a simple controller Employees which has the following Action Methods defined below and performs a set of statement like fetch a record from collection.GetDetails() action method takes one parameter and has its own specific routes while GetEmployeeByID() action method takes two parameters as arguments and has its own defined route.
GetDetails

  1. [Route("api/{employees}/{id}")] 
  2. public Employee GetDetails(int id) 
  3. return listEmp.First(e => e.ID == id); 

GetEmployeeByID

  1. [HttpGet] 
  2. [Route("api/{employees}/{id}/{userName}")] 
  3. [ActionName("GetEmployeeByID")] 
  4. public Employee Get(int id, string userName) 
  5. return listEmp.First(e => e.ID == id); 
  6.     SqlDataReader reader = null; 
  7.     SqlConnection myConnection = newSqlConnection(); 
  8.     myConnection.ConnectionString = @ "Server=.;Database=DBCompany;User ID=sa;Password=db@1234;"; 
  9.     SqlCommand sqlCmd = newSqlCommand(); 
  10.     sqlCmd.CommandType = CommandType.Text; 
  11.     sqlCmd.CommandText = "Select * from tblEmployee where EmployeeId=" + id + ""; 
  12.     sqlCmd.Connection = myConnection; 
  13.     myConnection.Open(); 
  14.     reader = sqlCmd.ExecuteReader(); 
  15.     Employee emp = null; 
  16. while (reader.Read()) 
  17.     { 
  18.         emp = new Employee(); 
  19.         emp.EmployeeId = Convert.ToInt32(reader.GetValue(0)); 
  20.         emp.Name = reader.GetValue(1).ToString(); 
  21.         emp.ManagerId = Convert.ToInt32(reader.GetValue(2)); 
  22.     } 
  23. return emp; 
  24.     myConnection.Close(); 
  25. } 

I run my application and verify that whether API is up or not. Kindly find given below image to identify this.
api
It shows API is running and ready to perform some action. Along with this I’ve Postman running aside where I paste the specific url. which meets the requirement as shown below:
normal
As soon as I click on the Send button it will go to the respective controller’s action to execute set of statements. This is the best benefits of Attribute routing is you can set any route as per you convenient. Like in the above URl there is no action method defined still it finds the right action method.This type of URI is difficult to create using convention-based routing(traditional routing model). Although it can be done, the results don’t scale well if you have many controllers or resource types
The output will be like given image shown below:
output
The same way you would have action which takes multi arguments than you can set the Attribute routing in such a way in below code segment.it makes it simple to understand and easily to execute.

  1. [HttpGet] 
  2. [Route("api/{employees}/{id}/{userName}")] 
  3. [ActionName("GetEmployeeByID")] 
  4. public Employee Get(int id, string userName) 
  5. }

I run an application again and verify that whether API is up or not. Kindly find given below image to identify this.
api
It shows API is running and ready to perform some action. Along with this I’ve Postman running aside where I paste the specific url (http://localhost:57888/api/employees/4/SachinKalia) which meets the requirement as shown below:
api
As soon as user click on send button it should reach to anticipated action method.
code
And the output will be like given below:
body
Attribute routing makes things easy and can create complex route in simpler way.
way
However there islittle issue which I confronted and would like to share with you. If you create route in such a way, that keeps parameter {controller} like in following route[Route("api/{controller}/{id}")]it prompts an error like “A direct route cannot use the parameter 'controller'. Specify a literal path in place of this parameter to create a route to a controller”. In simple words it should be a literal value.it throws same issue if you keep parameter {action} in route.
code
code
Which may consume your potential time during development?
way
Kindly add the following line in Global.asax file to initialize object as give below:

  1. GlobalConfiguration.Configuration.EnsureInitialized();  

If you don’t put this line in Global.asax file it throws an error as given below in screen shot.
code

Reference

You may downlaod the code from the given link here : Attribute Routing in ASP.NET Web API 2

0 comments :

Post a Comment