Skip to main content

WebAPI - Custom Attribute Routing - Intermediate

My photo
Assuming that there are 100 method in our controller that need to be routed properly. Implementing the previous technique might be risky, as it will introduce bug due to human error and hard for new developer to understand. In the industry this will impact the team performance and efficiency. Luckily Web API 2 have a workaround to make our code more elegant and bug risk free by implementing Custom Attribute Routing Constraint. This article will explain the basic step to produce Custom Attribute Routing Constraint components, configurations and implementations. The step to produce it is as below

1.Create the Attribute Routing Constraint Component
By Implementing IHttpRouteConstraint Interface
2. Register the Attribute Route Constraint To The WebApiConfig
config.MapHttpAttributeRoutes(customattribute)
3.Decorate the desired method with the Custom Routing Constraint Attribute in the controller.

The Requirements There is too many methods in our controller, routing strategy is very important, we need to implement Custom Route Constraint Attribute to capture parameter passed to the controller that is in a specific format. in this case {inv-companyname-}

Step 1 - Create the Attribute Routing Constraint Component
First we create a custom route constraint attribute class that inherited from IHttpRouteConstraint like below
using System.Collections.Generic;
using System.Net.Http;
using System.Web.Http.Routing;
namespace SampleCustomAttributeConstraint
{
// This example will check the incoming parameter and determine the string is Invoice type or others
// The checking will return true if its a request for invoice
public class InvoiceFormatCustomAttributeConstraint : IHttpRouteConstraint
{
// Custom Attribute to check passed parameter follow a specific invoice format
// Inherit from IHttpRouteConstraint
// Mandatory to Implement Public Bool Match Method
// That Accept 5 arguments.
public bool Match(
HttpRequestMessage request,
IHttpRoute route,
string parameterName,
IDictionary<string, object> values,
HttpRouteDirection routeDirection
)
{
object parameterPassed;
if (values.TryGetValue(parameterName, out parameterPassed) && parameterPassed != null)
{
string InvoiceFormat = "inv-companyname-";
if(parameterPassed.ToString().Contains(InvoiceFormat))
{
return true;
}
}
return false;
}
}
}
The code is a filtering mechanism that will return true or false based on the parameter sent by the caller (in this case i hard coded the string format)
Notice that we are implementing IHttpRouteConstraint that will receive some mandatory arguments that is useful in performing the filtering mechanism

Step 2 - Register the Attribute Route Constraint To The WebApiConfig
Once the class is defined ( i normally will address it as the Custom Route Constraint Attribute Component ). We need to register it to the app through the app configuration - WebApiConfig like below
using System.Web.Http;
using System.Web.Http.Routing;
namespace SampleCustomAttributeConstraint
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// add the constraint in the defaultinline constraint resolver
var constraintResolver = new DefaultInlineConstraintResolver();
constraintResolver.ConstraintMap.Add(
"InvoiceFormat",
typeof(InvoiceFormatCustomAttributeConstraint
)
);
config.MapHttpAttributeRoutes(constraintResolver);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
We start by instantiating a DefaultInlineConstraintResolver instance and add the 'component' to the instance.Note that there are 2 parameters that we pass into the method. Notice the string that we pass into the method, it is the signature that we will use in the controller in this case 'InvoiceFormat' and the second is the type of our 'component' ( in this case its InvoiceFormatCustomAttributeConstraint.

Step 2 - Decorate the desired method with the Custom Routing Constraint Attribute in the controller.
Finally we implement the Custom Attribute Route Constraint in the controller like below
[RoutePrefixAttribute("api/invoice")]
public class CustomConstantController : ApiController
{
[Route("{id:InvoiceFormat}")]
public string GetInvoice(string id)
{
return "Success - Data Format Is Invoice Format Return Invoice With ID = " + id;
}
[Route("{id}")]
public string GetOtherData(string id)
{
return "Parameter is not in Invoice Format - Return Other Type of data" + id;
}
}
As simple as adding the name of the custom attribute route constraint that we pass in in WebApiConfig.

Now the caller may request a call and send the specific invoice format in a string data type. For example
Request
http://localhost:26374/api/invoice/inv-companyname-2034798

Reply
Success - Data Format Is Invoice Format Return Invoice With ID = inv-companyname-2034798

Now the next request will hit the normal method with no Custom Attribute Route Constraint implemented on them
Request
http://localhost:26374/api/invoice/inv-wierdname-2034798

Reply
Parameter is not in Invoice Format - Return Other Type of data inv-wierdname-2034798

Conclusion
We can conclude that by implementing a Custom Attribute Route Constraint we may route the caller request to the appropriate method and this will introduce a more manageable and elegant code.

Back - Web Application > Web Api

Published on : 13-Jan-2018
Ref no : DDN-WPUB-000039

About Author

My photo
Wan Mohd Adzha MCPD,MCSD,MCSE
I am passionate about technology and of course love Durians. Certified by Microsoft as MCP Since 2011. Blogging from Malaysia

Comments