Routing WebAPI 2 Attributes with Non-Working Scopes
I'm having trouble getting the WEBAPI 2 attribute routing to work. The routing scheme I'm looking for is /api/{product}/{controller}/{id-optional}
so /api/Vision/IdCard
. The controllers are in scope and configured as follows:
namespace DataServices.Controllers.Vision
{
[RoutePrefix("api/vision")]
public class IdCardController : BaseApiController
{
[System.Web.Mvc.RequireHttps]
[Route("idcard")]
public IdCardViewModel Get(HttpRequestMessage request)
{...}
Whenever I do this, I get a 404 . I included the namespace as the scope is in its own namespace. Are scopes supported in WEBAPI attribute routing?
EDIT: The WebApiConfig looks like this:
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
source to share
The scope functionality is not available in the Asp.Net Web API project and is harder to maintain with a custom way, such as a namespace based controller. I have checked many issues with controller and namespace based routing, for example single action method is available on namespace based routing as well as default routing. Thus, the custom implementation does not diminish our requirements.
To solve this problem, we can use a simple way to manage controller routing like:
//Remove default routing registration
/*config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);*/
And only use attribute based routing like
[RoutePrefix("api/user/home")]
public class UserHomeController : ApiController
{
[Route]
public string Get()
{
return "Test user GET";
}
}
And for different area / module controllers
[RoutePrefix("api/admin/home")]
public class AdminHomeController : ApiController
{
[Route]
public string Get()
{
return "Test admin GET";
}
}
The advantages of this approach are:
- No need for custom logic like namespace based scope, custom routing handler, so its the best way to code it.
- You just need to add the [Route] attribute to the action to the API accessibility
source to share
You need to get an HttpConfiguration instance from the GlobalConfiguration object and call the MapHttpAttributeRoutes () method from the RegisterArea AreaRegistration.cs method.
public override void RegisterArea(AreaRegistrationContext context)
{
GlobalConfiguration.Configuration.MapHttpAttributeRoutes();
//... omitted code
}
This must be done for each Region. Finally, you must remove the config.MapHttpAttributes () method in 'WebApiConfig' or get a duplicate exception.
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
// Web API routes
//config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
source to share
Where does an MVC project start? Then I think you should delete the ApiAreaRegistration.cs file generated when the area was created. It is found at the root of your Api area and will conflict with your attribute routes as it will match an MVC route (not WebApi) like "api / {controller} / {action} / {id}" before it finds your specific routes ...
Hope it helps!
source to share
Try playing with the initialization order in Application_Start
this way:
//Config WebAPI(2) where you call config.MapHttpAttributeRoutes();
-
GlobalConfiguration.Configure (WebApiConfig.Register);
-
AreaRegistration.RegisterAllAreas ();
- FilterConfig.RegisterGlobalFilters (GlobalFilters.Filters);
- RouteConfig.RegisterRoutes (RouteTable.Routes);
- BundleConfig.RegisterBundles (BundleTable.Bundles);
Ordering is very important (if I reverse the scopeRegister with WebApiConfig => WebAPI 2Routing doesn't work
source to share