Saturday, January 3, 2015

Route and Route prefix - Web API 2

Web api is the buzz in the market these days for providing rest based api's. After its first release, further versions have been released, with version 2 being the one with some of the major changes. One of the very good feature introduced was the use of Attribute based routing of the web api requests. There were other feature also, but this feature is very big and useful in itself and our discussion will be for this only, in this article. Also, this article has its reference from a great write-up on this feature by Mike Wasson, here, which explains these features.
If you have worked with initial version webapi, you must be aware of concept of routing templates for the api controllers. But in its version 2, instead of defining routing templates in WebApiConfig.cs, we can define these templates at the method level i.e. on the methods of the web api controllers. This is possible through the use of the Route and RoutePrefix attributes, added to the webapi2. This does not means that we cannot use the routing template with convention of first release of webapi along with this. Both can be used side by side. So let's discuss these.
Initial Code setup:
1. Create a new MVC web application, with web api template.
2. Add reference to the
 webapi2 libraries, using the nuget package.
3. Add the
 Postman google chrome extension (Instead of making any html or mvc page, we will be using this extension, to make the test requests to the web api)
4. In our default values controller added, clear all the methods, add a 
Employee class and a method to return list of employees. So our api controller will look like the following:

Next, open the WebApiConfig.cs file, remove the default routing templates and simply add   config.MapHttpAttributeRoutes() to enable the attribute based routing.

Run the application. As the application is started, it will also cause hosting of the web api on the same development server. Now start the Postman extension and add the web-api url with method name, to which we want to make REST based calls. Click Send and see the results we receive:

This is the result which was expected.
Route Prefix in Web API
Now, suppose we add another method to it with Route attribute as FindEmployee and we need both the methods to have a common prefix in the api request url, say Employee. So instead of adding this as prefix to Route attribute of both these methods, we add a common attribute at the class level, called RoutePrefix and set its value to required prefix i.e.Employee.  So our code now changes to:

Now, we can make request to both the controller methods with the same prefix
 Employee. See the requests below:

Override Route Prefix
Next we have a situation where we do not our second method to use the same prefix as the first method. One solution could be use of a separate api controller and add the method to it. But this is not a good solution as you may required to add more methods in future, which do not use this prefix. To achieve this, we have the option to prefix the Route attribute value with a tilde(~) sign at the method level, for which we do not want to have the common prefix. So we add the tilde sign to the second method and make a direct call to the method. See the code below:

Now let's send the request with the changed url's and see the results.

Passing parameters in GET request
Now, let's see how we can send parameters to the request url. For this, we will be required to change the Route template and add a placeholder in it, which will be replaced by the parameter from the GET request.

Now, let's send the request and debug the code:

Bingo, we get the parameter in the code. We can also have a template, where the parameter placeholder is in between the url. So we can defined the Route template something like
[Route("FindEmployee/{eid}/Test")]
Let's change our url and send the request again.

That look's great. This means we can name our url's differently and hide the actual method names from the client code.
Constraints on URL parameters
We can even restrict the template placeholder to the type of parameter it can have. For ex, we can restrict that the request will be only served if the eid is greater than 10. Otherwise the request will not work. For this, we will apply multiple constraints in the same request:
1. Type of the parameter eid must be an integer
2.
 eid should be greater than 10
Let's see how we can do this.

Simply specify the type along with the placeholder, separated by a colon(:). Now try to send the request with a value less than 10 and we get the 404 error.

Change the value to greater than equal to 10 and it starts working again.
Optional and Default parameters 
I was really about to end the discussion until I came to knew about it's another great feature, using the optional parameters. But in this case, it becomes necessary to provide a default value to that parameter, in the method definition itself. For using optional parameters, we use the question mark(?) symbol to denote that it is an optional parameter. Let's see how we can have optional parameters:

 So these were some of the great sub-features of the Route and RoutePrefix feature in web api2. Let's summarize the features we discussed:
1. We have the Route attribute at the method level, to define routing templates.
2. We can define a common prefix for all the methods of the api controller, using
 RoutePrefix attribute.
3. We can override the RoutePrefix on a method, using the
 tilde(~) sign.
4. We can easily define parameterized templates in the attribute based routing
5. We can have parameters defined in-between the api request url
6. We can add certain constraints on the url parameters, i.e. their type or the values they can have, within the template itself.
7.  We can also have optional parameters in the methods, but with the condition that they must have a default value assigned to them.
So this was about the use of the Route and RoutePrefix attributes in webapi2. Sample code is attached with this discussion. Hope you enjoyed reading it. Happy coding...!!!

2 comments:

  1. hi Jasminder Singh,
    Thanks for sharing the article. can i implement the same feature in share point as a web part? Do you have any idea regarding this..

    Regards,
    Tarun

    ReplyDelete
  2. Hi Tarun, you should be able to host it using the Self hosting. You just need to create a separate project and host it using any windows service or any dummy web application

    ReplyDelete