Ok - took a bit of investiation but found what my problem was. In hindsite sometimes its better to backtrack just to work from the beginning which is what I had to do. Found that indeed Attribute Routing does work with the latest WEB API [V2.x] with very minimal operation - in general making sure the MapHttpAttributeRoutes operation on the used HttpConfiguration is called - and before the regular mapping - which is a little ambiguous in the docs.
My main issue really dealt with functionality I had added which broke the Attribute Routing mechanism. The first one dealt with designing my controllers in a hiearchical fashion - where I had base classes where core actions where placed then derived ones from those. When Attribute routing was applied to base actions they where not getting activated via Attribute Routing because it seems that looking at the base classes from an explicit controller is not done. My guess is that using OO concepts this would be the case. Found out that there needs to be a modification done when calling HttpConfiguration that provides a DefaultDirectRouteProvider object to the function where retrieal of base actions can be called:
public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
protected override IReadOnlyList<IDirectRouteFactory> GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
{
return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>(inherit: true);
}
}
I found this in another SO response
.NET WebAPI Attribute Routing and inheritance
where this was described as upcoming functionality - which looks to be in the release now.
My second issue dealt with a customized DefaultHttpControllerSelector which evaluated for version stamps provided within the namespace, Found the functionality online but it did not take into consideration when evaluating an Attribute Route. Fixed just by calling the base operation when an Attribute Route was being used.
public HttpControllerDescriptor SelectController(HttpRequestMessage request)
{
IHttpRouteData routeData = request.GetRouteData();
if (routeData == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
string namespaceName = string.Empty;
// Get the namespace and controller variables from the route data.
if (routeData.GetType() == typeof(HttpRouteData))
{
namespaceName = GetRouteVariable<string>(routeData, NamespaceKey);
if (namespaceName == null)
{
throw new HttpResponseException(HttpStatusCode.NotFound);
}
}
else
return base.SelectController(request);
For the mostpart that's what was required to get things working properly. Sometimes making assumptions can get you into to deep doo doo.
Peter