Search code examples
asp.net-mvcasp.net-mvc-4iisasp.net-mvc-routingasp.net-web-api-routing

WebApiConfig.Register Clears routes defined by RouteConfig.RegisterRoutes apon deployment


I'm on struggle street here, When I try to add API controllers it seems to destroy all my MVC base routes and area routes.

On my application start I call

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    WebApiConfig.Register(GlobalConfiguration.Configuration);
    //FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    Util.RazorDebuggingSetup();
    BundleConfig.RegisterBundles(BundleTable.Bundles); 
}

using System.Web.Mvc;

An example of an area config:

namespace **.Areas.Console
{
    public class ConsoleRegistration : AreaRegistration
    {
        public override string AreaName
        {
            get
            {
                return "Console";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context)
        {
            context.MapRoute(
                "Console_default",
                "Console/Index",
                new { controller = "base", action = "Index"}
            );

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

My WebApiConfig Class

using System.Web.Http;

namespace **.Modules.MVC
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration configuration)
        {
            configuration.Routes.MapHttpRoute(
                "API Default", 
                "api/{controller}/{id}",
                new
                {
                    id = RouteParameter.Optional
                }
            );
        }
    }
}

And the route class

using System.Web.Mvc;
using System.Web.Routing;

namespace **.Modules
{
    public class RouteConfig
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.MapRoute(
                "ErrorHandler",
                "Error/{action}/{id}",
                new { controller = "Error", action = "Generic" , id = UrlParameter.Optional }
            );

            // Ignore old Friendly URLS.
            // These should be removed.
            routes.IgnoreRoute("Account/Login");
            routes.IgnoreRoute("");
            routes.IgnoreRoute("Website/{*pathInfo}");
            routes.IgnoreRoute("Pages/{*pathInfo}");

            routes.IgnoreRoute("{*allaspx}", new { allaspx = @".*\.aspx(/.*)?" });
            routes.IgnoreRoute("{*allasp}",  new { allasp = @".*\.asp(/.*)?" });
            routes.IgnoreRoute("{*allhtml}", new { allhtml = @".*\.html(/.*)?" });
            routes.IgnoreRoute("{*allphp}",  new { allphp = @".*\.php(/.*)?" });

            //Default Mvc ignore.
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.IgnoreRoute("{*favicon}", new { favicon = @"(.*/)?favicon.ico(/.*)?" });

            //routes.MapRoute(
            //    "404-PageNotFound",
            //     "{*url}",
            //     new { controller = "Error", action = "HttpError" }
            //);
        }
    }
}

Now on my local iis everything functions as expected but when I try access urls on my production server i get the following 404.

When I turn on my route debugging i see this on local.

    • Matches Current Request: False
    • Url: r.ashx/{module}/{*path}
    • Defaults: (null)
    • Constraints: (null)
    • DataTokens: (null)
    • Matches Current Request: True
    • Url: Control/Index
    • Defaults: controller = base, action = Index
    • Constraints: (empty)
    • DataTokens: Namespaces = BookEasy.Areas.Control.*, area = Control, UseNamespaceFallback = False
    • Matches Current Request: True
    • Url: Control/{controller}/{action}/{id}
    • Defaults: action = Index, id = UrlParameter.Optional
    • Constraints: (empty)
    • DataTokens: Namespaces = BookEasy.Areas.Control.*, area = Control, UseNamespaceFallback = False
    • Matches Current Request: False
    • Url: Console/Index
    • Defaults: controller = base, action = Index
    • Constraints: (empty)
    • DataTokens: Namespaces = BookEasy.Areas.Console.*, area = Console, UseNamespaceFallback = False
    • Matches Current Request: False
    • Url: Console/{controller}/{action}/{id}
    • Defaults: action = Index, id = UrlParameter.Optional
    • Constraints: (empty)
    • DataTokens: Namespaces = BookEasy.Areas.Console.*, area = Console, UseNamespaceFallback = False
    • Matches Current Request: False
    • Url: api/{controller}/{id}
    • Defaults: id =
    • Constraints: (empty)
    • DataTokens: (null)
    • Matches Current Request: False
    • Url: Error/{action}/{id}
    • Defaults: controller = Error, action = Generic, id = UrlParameter.Optional
    • Constraints: (empty)
    • DataTokens: (empty)
    • Matches Current Request: False
    • Url: Account/Login
    • Defaults: (null)
    • Constraints: (empty)
    • DataTokens: (null)
    • Matches Current Request: False
    • Url:
    • Defaults: (null)
    • Constraints: (empty)
    • DataTokens: (null)
    • Matches Current Request: False
    • Url: Website/{*pathInfo}
    • Defaults: (null)
    • Constraints: (empty)
    • DataTokens: (null)
    • Matches Current Request: False
    • Url: Pages/{*pathInfo}
    • Defaults: (null)
    • Constraints: (empty)
    • DataTokens: (null)
    • Matches Current Request: False
    • Url: {*allaspx}
    • Defaults: (null)
    • Constraints: allaspx = ..aspx(/.)?
    • DataTokens: (null)
    • Matches Current Request: False
    • Url: {*allasp}
    • Defaults: (null)
    • Constraints: allasp = ..asp(/.)?
    • DataTokens: (null)
    • Matches Current Request: False
    • Url: {*allhtml}
    • Defaults: (null)
    • Constraints: allhtml = ..html(/.)?
    • DataTokens: (null)
    • Matches Current Request: False
    • Url: {*allphp}
    • Defaults: (null)
    • Constraints: allphp = ..php(/.)?
    • DataTokens: (null)
    • Matches Current Request: False
    • Url: {resource}.axd/{*pathInfo}
    • Defaults: (null)
    • Constraints: (empty)
    • DataTokens: (null)
    • Matches Current Request: False
    • Url: {*favicon}
    • Defaults: (null)
    • Constraints: favicon = (./)?favicon.ico(/.)?
    • DataTokens: (null)
    • Matches Current Request: True
    • Url: {*catchall}
    • Defaults: (null)
    • Constraints: (null)
    • DataTokens: (null)

Sorry for that wall of text seemed to be the best way to show the data without a table. https://meta.stackexchange.com/questions/73566/is-there-any-markdown-to-create-tables

Anyways on with the question.

And now what I see when I debug routes on my deployed server.

    • Matches Current Request: False
    • Url: r.ashx/{module}/{*path}
    • Defaults: (null)
    • Constraints: (null)
    • DataTokens: (null)
    • Matches Current Request: True
    • Url: {*catchall}
    • Defaults: (null)
    • Constraints: (null)
    • DataTokens: (null)

Some other facts.

Mvc Version = 4

IIS = 7

When I remove WebApiConfig.Register(GlobalConfiguration.Configuration); the tables match (but both miss the api/* route).

So to the core of the question. Why are these two route tables different when I add WebApiConfig.Register?

---------------- EDIT 1 ------------------

As another note the addition of WebApiConfig.Register also breaks my bundling routes :(.


Solution

  • Doing some digging I noticed this. https://stackoverflow.com/a/26972184/2560687

    IMO point one is bad as its non specific.

    Note Point 2: My local machine had these dlls in the gac but deployment machine did not. And copy local = true to the dlls and everything is working :D

    What is the correct procedure here for question answering when its a proposed answer to a different question?