W MVC można podać listę namespace przy deklaracji route, dla których dany route ma być wykorzystywany.

Czasami jest to wystarczające, ale czasami… możemy natrafić na sytuację, że posiadając dwa różne namespace jak na przykład Moje.Controllers i Twoje.Controllers i route na Moje.Controllers, dostaniemy kontroler z przestrzeni nazw Twoje.Controllers.

Dzieje się tak, kiedy MVC nie jest wstanie znaleźć danego kontrolera odpowiadającemu parametrom route. Jeżeli takiego nie ma, to następuje fallback i przeszukanie innych przestrzeni nazw.

Czyli jeżeli nie zostanie znaleziony kontroler i akcja w przestrzeni nazw Moje.Controllers to nastąpi przeszukanie Twoje.Controllers i jeżeli zostanie znaleziony tam odpowiedni kontroler, to ON zostanie zwrócony.

Rozwiązaniem problemu jest dodanie parametru UseNamespaceFallback i ustawienie go na false.

Niestety, by móc go ustawić należy stworzyć własne extension method dla MapRoute inaczej nie da się go ustawić, lub ja nie wiem jak go ustawić ;)

Dla przykładu taka metoda może wyglądać tak jak kod poniżej. Jedna przyjmuje fallback ale ustawia go wyłącznie kiedy jest podany namespace (inaczej jak nie jest i ustawicie fallback na false to nic nie dostaniecie), albo opcja druga, która zakłada, że jak podajesz namespace to automatycznie ustawia fallback na false).

NOTE: metoda MapRoute i jej domyślna zawartość (wszystko oprócz UseNamespaceFallback) wzięta z kodu MVC – R# + F12 ;)

public static Route MapRoute(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces, bool fallback)
{
    if(routes == null)
    {
        throw new ArgumentNullException("routes");
    }
    if(url == null)
    {
        throw new ArgumentNullException("url");
    }

    Route route = new Route(url, new MvcRouteHandler())
    {
        Defaults = new RouteValueDictionary(defaults),
        Constraints = new RouteValueDictionary(constraints),
        DataTokens = new RouteValueDictionary()
    };

    if((namespaces != null) && (namespaces.Length > 0))
    {
        route.DataTokens["Namespaces"] = namespaces;
        route.DataTokens["UseNamespaceFallback"] = fallback;
    }

    routes.Add(name, route);

    return route;
}

public static Route MapRouteWithFallback(this RouteCollection routes, string name, string url, object defaults, object constraints, string[] namespaces)
{
    if(routes == null)
    {
        throw new ArgumentNullException("routes");
    }
    if(url == null)
    {
        throw new ArgumentNullException("url");
    }

    Route route = new Route(url, new MvcRouteHandler())
    {
        Defaults = new RouteValueDictionary(defaults),
        Constraints = new RouteValueDictionary(constraints),
        DataTokens = new RouteValueDictionary()
    };

    if((namespaces != null) && (namespaces.Length > 0))
    {
        route.DataTokens["Namespaces"] = namespaces;
        route.DataTokens["UseNamespaceFallback"] = false; // deafult is true
    }

    routes.Add(name, route);

    return route;
}