Search code examples
asp.net-mvc-5asp.net-mvc-routingasp.net-web-api2asp.net-mvc-areas

web api 2 area routes


I am using asp.net mvc 5 and web api 2. For the asp.net mvc 5 project I have everything working... but new I am trying to add web api 2 routes... when I am using areas.

I have the web api 2 controller working at the project root:

 //this is working 
   namespace EtracsWeb.Controllers
    {
        public class TestController : ApiController
        {
            //localhost:port/api/test ...this is working
            [HttpGet]
            public HttpResponseMessage Get()
            {

                return new HttpResponseMessage()
                {
                    Content = new StringContent("GET: Test message")
                };
            }

        }
    }

So I am assuming my Global.asax, my routeconfig.cs and my webapiconfig.cs are correct ... (not shown)...

But now I am trying to get the web api 2 in my AREAS working...

I have read everything I could find on the web and this seems like it should work:

namespace EtracsWeb.Areas.WorkOrder
{
    public class WorkOrderAreaRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "WorkOrder";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {

            context.Routes.MapHttpRoute(
                    name: "AuditModel_Api",
                    routeTemplate: "WorkOrder/api/AuditModelApi/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );

        //default
            context.Routes.MapHttpRoute(
                    name: "WorkOrder_Api",
                    routeTemplate: "WorkOrder/api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );

            context.MapRoute(
                 "WorkOrder_default",
                "WorkOrder/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional }
            );
        }
    }
}

My controller code is:

namespace EtracsWeb.Areas.WorkOrder.ApiControllers
{
    public class AuditModelApiController : ApiController
    {
        IManufacturerStopOrderModelService auditModelService = new WorkOrder.Services.VWAuditModelService(UserSession.EtracsUserID, UserSession.ProgramID, UserSession.EtracsSessionID, UserSession.ConnectionString);

        [HttpGet]
        [Route("AuditModelApi")]
        public HttpResponseMessage Get()
        {

            return new HttpResponseMessage()
            {
                Content = new StringContent("GET: Test message")
            };
        }

        [Route("AuditModelApi/AuditModels")]
        public IEnumerable<VwAuditModel1> GetAuditModels()
        {
                return auditModelService.GetModels();
        }

        public IHttpActionResult UpdateAuditMode()
        {
            //example of what can be returned ... NotFound, Ok ... look into uses...

            VwAuditModel1 result = new VwAuditModel1();
            return Ok(result);

            return NotFound();
        }
    }
}

I have tried the controller with and without the attribute naming [Route]... and I can't get either get to work...

Both the simple case

    public HttpResponseMessage Get()

and the "real" case

  public IEnumerable<VwAuditModel1> GetAuditModels()

return the same result. From the browser, using

http://localhost:64167/WorkOrder/api/AuditModelApi

and

http://localhost:64167/WorkOrder/api/AuditModelApi/AuditModels

I get the following:

<Error>
<Message>
No HTTP resource was found that matches the request URI 'http://localhost:64167/WorkOrder/api/AuditModelApi/AuditModels'.
</Message>
<MessageDetail>
No route providing a controller name was found to match request URI 'http://localhost:64167/WorkOrder/api/AuditModelApi/AuditModels'
</MessageDetail>
</Error>

Solution

  • You need to get the HttpConfiguration instance from the GlobalConfiguration object and call the MapHttpAttributeRoutes() method from inside the RegisterArea() method of the AreaRegistration.cs.

        public override void RegisterArea(AreaRegistrationContext context) 
        {
            GlobalConfiguration.Configuration.MapHttpAttributeRoutes();
    
            //... omitted code  
        }
    

    Finally you must in the WebApiConfig remove config.MapHttpAttributes() method or you will get 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 }
            );
        }
    }