ASP.NET Web API + Attribute based Routing

2013/08/28

10 comments

ASP.NET Web API + Attribute based Routing

this post is talking about ASP.NET Web API feature which enable to extend the resource oriented paradigm of Http REST base API toward a service oriented API.

be aware that the post is speaking of a pre release feature, therefore it might be subject to API changes, actually I have spent lot of time lately in order to set it right, because changed has occurs recently (with out a decent documentation).

a few words about REST (Representational state transfer) API. Http was construct over the notion of resources,  represented by URL. you can query resource content using ‘GET’ verb, create new resource using ‘POST’ verb, updating it using the ‘PUT’ verb and delete a resource using ‘DELETE’ verb.

WebAPI, Attribute, Routing, ASP.NET, HttpGet

traditionally ASP.NET Web API was following this concept quit strictly.
you should have a class which represent a resource and having the ‘GET’, ‘POST’, ‘PUT’ and ‘DELETE’ verb in order to manipulate the resource.

for example:

Code Snippet
  1. public class UsersController : ApiController
  2. {
  3.     // GET api/users
  4.     public IEnumerable<string> Get() { /*…*/ }
  5.     // GET api/users/5
  6.     public string Get(int id) { /*…*/ }
  7.     // POST api/users
  8.     public void Post([FromBody]string value) { /*…*/ }
  9.     // PUT api/users/5
  10.     public void Put(int id, [FromBody]string value) { /*…*/ }
  11.     // DELETE api/users/5
  12.     public void Delete(int id) { /*…*/ }
  13. }

having users which can be query by ‘GET’ verb like at lines 4, 6.
or insert a user using ‘POST’ verb like at line 8.

but sometimes we like to have less restrictive design, were you can use the same class for expressing broader scenarios.
for example, having the option to update the user (id = 5) using PUT of [api/user/5] and confirm the user data using PUT of [api/user/5/confirm].

for those scenario and more, ASP.NET team was adding the Attribute based Routing (which is actually start as external contribution of Timothy McCall)

using the Attribute based Routing you can have a greater API flexibility:

Code Snippet
  1. public class UsersController : ApiController
  2. {
  3.     // GET api/users
  4.     public IEnumerable<string> Get() { /*…*/ }
  5.     // GET api/users/5
  6.     public string Get(int id) { /*…*/ }
  7.     // POST api/users
  8.     public void Post([FromBody]string value) { /*…*/ }
  9.     // PUT api/users/5
  10.     public void Put(int id, [FromBody]string value) { /*…*/ }
  11.     // PUT api/users/5/confirm
  12.     [Route("api/users/{id}/confirm")]
  13.     public void PutConfirm(int id, [FromBody]string value) { /*…*/ }
  14.     // DELETE api/users/5
  15.     public void Delete(int id) { /*…*/ }
  16. }

as you can see in line 12, you can decorate a method with a routing pattern.

you can either use the verb naming convention (methods start with Get, Post, Put, Delete) or decorate the method with AcceptVerbs attribute.

Code Snippet
  1. [RoutePrefix("api/users/v1")]
  2. public class UsersController : ApiController
  3. {
  4.     // PUT api/users/v1/5/confirm
  5.     [Route("{id}/confirm")]
  6.     [AcceptVerbs("POST", "PUT")]
  7.     public void Confirm(int id, [FromBody]string value) { /*…*/ }
  8.     // DELETE api/users/v1/5
  9. }

actually it is much wider then this:

you can have the class decorated with a routing prefix, so you can
have concept like versioning easily supported:

Code Snippet
  1. [RoutePrefix("api/users/v1")]
  2. public class UsersController : ApiController
  3. {
  4.     // GET api/users/v1
  5.     [Route]
  6.     public IEnumerable<string> Get() { /*…*/ }
  7.     // GET api/users/v1/5
  8.     [Route]
  9.     public string Get(int id) { /*…*/ }
  10.     // POST api/users
  11.     [Route]
  12.     public void Post([FromBody]string value) { /*…*/ }
  13.     // PUT api/users/v1/5
  14.     [Route]
  15.     public void Put(int id, [FromBody]string value) { /*…*/ }
  16.     // PUT api/users/v1/5/confirm
  17.     [Route("{id}/confirm")]
  18.     public void PutConfirm(int id, [FromBody]string value) { /*…*/ }
  19.     // DELETE api/users/v1/5
  20.     [Route]
  21.     public void Delete(int id) { /*…*/ }
  22. }

be aware that most of the Attribute based Routing samples available today on the web, is using old attribute like [PUT] or [HttpPut] which is no longer supported on the latest bit (currently available from the ASP.NET nightly build, http://www.myget.org/F/aspnetwebstacknightly/), those attributes ware replaced with [Route] attribute.

other functionality available with the Attribute based Routing are:

  • you can have type and / or range restriction
Code Snippet
  1. [Route("users/{id:int}"]
  2. public User GetUserById(int id) { … }
  3.  
  4. [Route("users/{name}"]
  5. public User GetUserByName(string name) { … }

see the following restriction list (taken from: http://www.asp.net/web-api/overview/web-api-routing-and-actions/attribute-routing-in-web-api-2)

Constraint Description Example
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)}
{x:length(1,20)}
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}$)}
Last thing

to get it operate and running you have to have the following statement on WebApiConfig (line 5 and 13)

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

Summary

Attribute based Routing is actually capable for much more, it is having more handy features and it is a great improvement to the basic Web API.

still, it is only available thought a NuGet nightly build, but it will be part of the next ASP.NET Web API release, so stay tune for it.

Add comment
facebook linkedin twitter email

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

10 comments

  1. blogg asia2013/11/22 ב 10:52

    It is perfect time to make some plans for the future and
    it is time to be happy. I have read this submit and if I could I want to recommend you few attention-grabbing things or advice.
    Maybe you could write next articles referring to this article.

    I want to read more things about it!

    Reply
  2. Cheap Furla2013/11/25 ב 11:36

    you’re in point of fact a just right webmaster. The site loading velocity is incredible. It seems that you’re doing any distinctive trick. In addition, The contents are masterpiece. you’ve performed a excellent task in this topic!

    Reply
  3. viajes2013/11/25 ב 23:32

    You’ll be in truth fantastic site owner. The website launching stride is astounding. Evidently you are carrying out any exclusive tip. Also, The actual contents are mona lisa. you must have done a wonderful job within this subject matter!

    Reply
  4. Michael Kors Vaskor2013/12/21 ב 16:40

    magnificent submit, very informative. I wonder why the opposite experts of this sector don’t understand this. You must proceed your writing. I am sure, you have a great readers’ base already!

    Reply
  5. WyattHToby2016/06/15 ב 04:26

    Very descriptive post, I liked that bit. Will there be a
    part 2?

    my blog post … WyattHToby

    Reply
    1. Bnaya Eshet
      Bnaya Eshet2016/08/02 ב 08:48

      sorry but no plans to do part 2 any time soon

      Reply
  6. ElmaTNasif2016/08/05 ב 01:21

    Thanks to my dad who told me on the subject of this site, this website is truly remarkable.

    Feel free to surf to my site: ElmaTNasif

    Reply
  7. HoaEFlorin2016/09/23 ב 12:56

    hello!,I enjoy your writing so much! percentage we communicate extra approximately your post on AOL?
    I need a professional on this space to fix my problem.
    Can be that’s you! Having a look ahead to peer you.

    Feel free to surf to my web page :: HoaEFlorin

    Reply
  8. Bocchini sesso 3gp2016/10/19 ב 09:23

    Hello! This is my 1st comment here so I just wanted to give a quick shout out and say I genuinely enjoy readding through
    your posts. Cann you suggest any other blogs/websites/forums that go
    over the same topics? Thanks!

    My blog post – Bocchini sesso 3gp

    Reply