2012-06-18 5 views
36

In der gleichen Lösung gibt es eine ASP.NET MVC4-Anwendung Slick.App und Klassenbibliothek Awesome.Mvc.Lib. Awesome.Mvc.Lib enthält eine Controller-Klasse.Controller in separater Assembly und Routing

public class ShinnyController : Controller 
{ 
    [HttpGet] 
    public string Index() 
    { 
     return "Hello, from Awesome.Mvc.Lib"; 
    } 
} 

Wenn ich die Anwendung und Punkt die Referenz fügen Sie einfach Brower von Slick.App zu Awesome.Mvc.Lib, führen zu /shinny, ich werde die Antwort tatsächlich sehen, „Hallo, von Awesome.Mvc.Lib“.

Das ist etwas, was ich überhaupt nicht erwarte. Die ganze Zeit dachte ich, dass ASP.NET MVC die Namespaces respektiert, in die die Controller gesteckt wurden. So werden die Controller aus anderen Namespaces nicht angezeigt, zumindest bevor ich nicht danach gefragt habe.

Ich habe versucht, die Standardroutenregistrierung zu ändern, um Namespaces-Parameter zu verwenden.

routes.MapRoute(
     name: "Default", 
     url: "{controller}/{action}/{id}", 
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
     namespaces: new [] { "Slick.App.Controllers" } 
    ); 

Dennoch stimmt die ShinnyController-Route immer noch mit '/ shinny' überein.

Ich habe Bedenken, das ist richtig Standardverhalten. Meine Frage ist, wie explizit zu sagen, welche Controller ausgesetzt sind und verhindern, dass Standardroute Controller in separaten Klassenbibliothek übereinstimmen?

Antwort

30

Die Namespaces-Liste auf der Strecke gibt nur Priorität bestimmten Namensraum über die anderen, die nicht aufgeführt sind:

new [] {"Namespace1", "Namespace2"} 

nicht geben höhere Priorität namespace1, wie man erwarten würde, aber nur gibt beiden Namespaces Priorität gegenüber den anderen.

Dies bedeutet, dass die Namespaces in der Liste zuerst nach Controllern durchsucht werden. Wenn keine Übereinstimmung gefunden wird, werden die restlichen verfügbaren Controller mit diesem Namen verwendet.

Sie können die Verwendung von nicht priorisierten Controller unterdrücken, indem dies zu tun:

var myRoute = routes.MapRoute(
     name: "Default", 
     url: "{controller}/{action}/{id}", 
     defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
     namespaces: new [] { "Slick.App.Controllers" } 
    ); 

myRoute.DataTokens["UseNamespaceFallback"] = false; 
3

Sie von DefaultControllerFactory wie dies erben können:

public class CustomControllerFactory : DefaultControllerFactory 
{ 
    protected override Type GetControllerType(System.Web.Routing.RequestContext requestContext, string controllerName) 
    { 
     var type = base.GetControllerType(requestContext, controllerName); 

     if (type != null && IsIngored(type)) 
     { 
      return null; 
     } 

     return type; 
    } 

    public static bool IsIngored(Type type) 
    { 
     return type.Assembly.GetCustomAttributes(typeof(IgnoreAssemblyAttribute), false).Any() 
      || type.GetCustomAttributes(typeof(IgnoreControllerAttribute), false).Any(); 
    } 
} 

Dann werden einige Änderungen an Global.asax

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

     RegisterGlobalFilters(GlobalFilters.Filters); 
     RegisterRoutes(RouteTable.Routes); 

     ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory()); 
    } 

Und hier sind Sie! Jeder mit IgnoreControllerAttribute markierte Typ ist nicht sichtbar. Sie können sogar die gesamte Baugruppe ausblenden.

Wenn Sie einige Konfiguration basiert Verhalten benötigen, ist es keine große Sache, alle notwendigen Änderungen vorzunehmen;)

+1

Unfortunatelly, das ist nicht genau das, was mein Problem ist. Mein Problem ist, dass ich keinen Zugriff auf die Host-Anwendung habe, daher würde die Erstellung einer benutzerdefinierten Controller-Factory für mich nicht funktionieren. –

+0

@alexanderb: Nein, Sie können dies mit folgendem Befehl tun: [assembly: System.Web.PreApplicationStartMethod (typeof (MvcTools.Hooks.PreApplicationStartCode), "Start"]], siehe folgenden Link: http: //blog.davidebbo. com/2011/02/register-your-http-modules-at-runtime.html Dort in Start, tun Sie dies: System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory (YOUR_ControllerFactory)); Alles, was Sie tun müssen, ist, dass die Host-Anwendung Ihre DLL lädt, was Sie mit einem web.config-Eintrag erreichen können;) –

Verwandte Themen