2012-06-18 18 views
36

nella stessa soluzione, v'è un'applicazione Slick.App e libreria di classi ASP.NET MVC4 Awesome.Mvc.Lib. Awesome.Mvc.Lib contiene una classe di controller.controller in assembly separato e di routing

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

Se ho appena aggiungere il riferimento da Slick.App a Awesome.Mvc.Lib, eseguire l'applicazione e punto di Brower a /shinny, io effettivamente vedere la risposta "Ciao, da Awesome.Mvc.Lib".

Questo è qualcosa che non mi aspetto affatto. Per tutto il tempo ho pensato che ASP.NET MVC rispetti gli spazi dei nomi in cui sono posizionati i controller. Quindi, i controller di altri spazi dei nomi non sono esposti, almeno prima che non me lo chiedessi.

ho cercato di modificare la registrazione percorso di default, utilizzare il parametro namespace.

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

Tuttavia, il percorso di ShinnyController corrisponde ancora a "/ shinny".

Ho un problema questo è giusto comportamento predefinito. La mia domanda è, come dire esplicitamente quali controller sono esposti e impedire che la route predefinita corrisponda ai controller in una libreria di classi separata?

risposta

30

L'elenco spazi dei nomi sulla rotta dà solo priorità a determinati spazi dei nomi nel corso degli altri, che non sono elencate:

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

non dà maggiore priorità alla namespace1 come ci si aspetterebbe, ma solo dà la priorità a entrambi gli spazi dei nomi rispetto agli altri.

Questo significa che gli spazi dei nomi nella lista sono prima cercati per i controller e poi, se nessuna corrispondenza viene trovato il resto dei controller disponibili con quel nome vengono utilizzati.

È possibile eliminare l'uso di controllori non prioritarie in questo modo:

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

È possibile ereditare da DefaultControllerFactory come questo:

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(); 
    } 
} 

Poi alcune modifiche per Global.asax

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

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

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

Ed eccovi qui! Qualsiasi tipo contrassegnato con IgnoreControllerAttribute non sarà visibile. Puoi persino nascondere l'intero assemblaggio.

Se avete bisogno di qualche comportamento configurazione basata, non è una gran cosa per fare tutte le modifiche necessarie;)

+1

Purtroppo, questo non è esattamente quello che è il mio problema è. Il mio problema è che non ho alcun accesso all'applicazione host, quindi la creazione della factory controller personalizzata non funzionerebbe per me. –

+0

@alexanderb: No, si può fare questo, utilizzare questo: [assembly: System.Web.PreApplicationStartMethod (typeof (MvcTools.Hooks.PreApplicationStartCode), "Start")], si veda questo link: http: //blog.davidebbo. com/2011/02/register-your-http-modules-at-runtime.html All'inizio si esegue questa operazione: System.Web.Mvc.ControllerBuilder.Current.SetControllerFactory (YOUR_ControllerFactory)); Tutto quello che devi fare è ottenere l'applicazione host per caricare la tua DLL, che puoi ottenere tramite una voce web.config;) –

Problemi correlati