Sunday, January 5, 2014

Attribute Routing in Web API 2

With the release of Web API 2 there are few improved & new features been introduced. Those are

  1. External Authentication
  2. Enabling cross origin request
  3. Use OWIN to host Web API in an Azure worker Role
  4. IHttpActionResult, a New Way to Create Responses in Web API
  5. Attribute Routing
  6. Using $select, $expand, and $value in Web API OData

In this blog I am going to talk about Attribute routing in detail.

Before Web API 2 comes for routing in web API what we have used in conventional routing. In this normally what we have in a single API controller

ex:- Employee Controller

  1. Get(int Id) // Get Employee By Id
  2. Get() // Get All Employees
  3. Post()
  4. Put()
  5. Delete()

You can get more details on conventional routing here

The constraint here is if we want to get Leave Records by Employee Id we will have to create a different controller. We cannot have that in the same controller. Attribute Routing solves this issue. Attribute routing supports some of the URI patterns which are commonly used in REST API’s which are not supported by Conventional Routing.

Party smile

API Versioning

If you have different versions of your API you can specify that in the URI template so the request will be routed to the correct version of the code.  

ex :-

/api/v1/employees
/api/v2/employees

 

Overloaded URI segments

ex :-

/api/employees/1
/api/employees/onsite

Here first one will return employee by ID 1 and second one will return collection of employees who are in onsite.

Multiple parameter types

ex :-

/api/employees/1
/api/employees/2013/06/16

Here 1 is int and other one takes a date time as parameter.

 

Enabling Attribute Routing

Add the following code inside class WebApiConfig. You can find it here.

image

 

public static class WebApiConfig

{

public static void Register(HttpConfiguration config)

{

config.MapHttpAttributeRoutes();

}

}

 

Adding Route Attribute

Following is an example of adding routing attribute

public class EmployeeController : ApiController

{

[Route("customers/{employeeId}/leaves")]

public IEnumerable<Leave> GetLeaveByEmploeeId(int employeeId)

{ ... }

}

 

Route Prefixes

Most of the methods in the controller has a common part in all the URL Templates.

ex:-

public class EmployeesController : ApiController

{

[Route("api/employees")]

public IEnumerable<Employee> GetEmployees() { ... }

[Route("api/employees/{id:int}")]

public Employee GetEmployee(int id) { ... }

[Route("api/employees")]

public HttpResponseMessage CreateEmployee(Employee employee) { ... }

}

 

For this kind of a controller you can use Route Prefix As below.

[RoutePrefix("api/employees")]

public class EmployeesController : ApiController

{

[Route("")]

public IEnumerable<Employee> GetEmployees() { ... }

[Route("{id:int}")]

public Employee GetEmployee(int id) { ... }

[Route("")]

public HttpResponseMessage CreateEmployee(Employee employee) { ... }

}

Route Prefix Can include Parameters as well.

Ex:-

  [RoutePrefix("customers/{employeeId}")]

public class EmployeeController : ApiController

{

[Route("orders")]

public IEnumerable<Leave> Get(int employeeId) { ... }

}

If in case if you want to use a different URL template for a selected method inside a controller which has a route prefix you can override it as below.

[RoutePrefix("api/employees")]

public class BooksController : ApiController

{

[Route("~/api/employees/{emploeeId:int}/leaves")]

public IEnumerable<Leave> GetLeavesByEmployeeId(int authorId) { ... }

}

 

Route Constraints

Route constraints let you restrict how the parameters in the route template are matched. The general syntax is "{parameter:constraint}".

Ex:

[Route("users/{id:int}"]
public User GetUserById(int id) { ... }

[Route("users/{name}"]
public User GetUserByName(string name) { ... }

Here, the first route will only be selected if the "id" segment of the URI is an integer. Otherwise, the second route will be chosen.

Following are the constraints supported.




































































alpha


Matches uppercase or lowercase Latin alphabet characters (a-z, A-Z)


{x:alpha}


bool


Matches a Boolean value.


{x:bool}


datetime


Matches a DateTime value.


{x:datetime}


decimal


Matches a decimal value.


{x:decimal}


double


Matches a 64-bit floating-point value.


{x:double}


float


Matches a 32-bit floating-point value.


{x:float}


guid


Matches a GUID value.


{x:guid}


int


Matches a 32-bit integer value.


{x:int}


length


Matches a string with the specified length or within a specified range of lengths.


{x:length(6)}


long


Matches a 64-bit integer value.


{x:long}


max


Matches an integer with a maximum value.


{x:max(10)}


maxlength


Matches a string with a maximum length.


{x:maxlength(10)}


min


Matches an integer with a minimum value.


{x:min(10)}


minlength


Matches a string with a minimum length.


{x:minlength(10)}


range


Matches an integer within a range of values.


{x:range(10,50)}


regex


Matches a regular expression.


{x:(^\d{3}-\d{3}-\d{4}$)}


 

Optional URI Parameters and Default Values


If you want to make a URL parameter optional then that is also supported in Web API 2. In such a method you can set the default value of the parameter inside the URL template itself.


public class BooksController : ApiController


{


[Route("api/books/locale/{lcid=1033}")]


public IEnumerable<Book>


GetBooksByLocale(int lcid) { ... }


}


Above features have given us the same REST API URL template experience in web API as well.


Happy Coding !!!!

No comments :

Post a Comment