8

Attualmente sto lavorando a un'applicazione Web aziendale che utilizza WCF per implementare un'API REST. Utilizza un VirtualPathProvider per catturare le richieste di file * .svc (che in realtà non esistono) e quindi li costruisce al volo per caricare dinamicamente i servizi WCF associati. Ciò consente al sistema di disporre di "moduli" che possono essere aggiunti all'applicazione in fase di esecuzione senza influire sul server Web o su chi lo utilizza.Web API 2 È possibile caricare un percorso/controller a livello di codice?

Quello che mi piacerebbe sapere è se lo stesso è concettualmente possibile con Web API 2. Ho fatto qualche ricerca, ma sembra che i percorsi possano essere configurati all'avvio ... Cosa speravo poiché è un mezzo per gestire percorsi inesistenti e fondamentalmente usa il nome del controllore dalla richiesta per cercare e caricare l'assembly associato (se esiste) aggiungendo al tempo stesso una nuova rotta.

Ho appena iniziato con Web API 2, quindi speravo che gli utenti più esperti potessero intervenire. Fondamentalmente il mio team è interessato al passaggio a Web API 2 per ridurre il sovraccarico e la complessità che abbiamo riscontrato con WCF, ma questo particolare requisito potrebbe essere un rompicapo.

+0

Ho una risposta anche qui: http://stackoverflow.com/a/39155619/538387 – Tohid

risposta

9

Ok, quindi dopo molte ricerche ... Ho rintracciato la classe corretta da sovrascrivere, e ora posso verificare per richiesta se il controller è stato in grado di essere risolto, e in caso contrario, tentare di caricare il corretto assemblare in memoria (in base al nome del controller al momento) e restituire il controller associato.

Ecco il codice:

public class CustomHttpControllerSelector : DefaultHttpControllerSelector { 
    private readonly HttpConfiguration _configuration; 

    public CustomHttpControllerSelector(HttpConfiguration configuration) : base(configuration) { 
    _configuration = configuration; 
    } 

    public override HttpControllerDescriptor SelectController(HttpRequestMessage request) { 
    HttpControllerDescriptor controller; 
    try { 
     controller = base.SelectController(request); 
    } 
    catch (Exception ex) { 
     String controllerName = base.GetControllerName(request); 
     Assembly assembly = Assembly.LoadFile(String.Format("{0}pak\\{1}.dll", HostingEnvironment.ApplicationPhysicalPath, controllerName)); 
     Type controllerType = assembly.GetTypes() 
     .Where(i => typeof(IHttpController).IsAssignableFrom(i)) 
     .FirstOrDefault(i => i.Name.ToLower() == controllerName.ToLower() + "controller"); 
     controller = new HttpControllerDescriptor(_configuration, controllerName, controllerType); 
    } 
    return controller; 
    } 
} 

e, naturalmente, avresti bisogno di sostituire il servizio nel file di metodo Register del WebApiConfig in quanto tale:

config.Services.Replace(typeof(IHttpControllerSelector), new CustomHttpControllerSelector(config)); 

C'è sicuramente più lavoro per essere fatto qui, ma questo è un buon inizio. Mi consente di aggiungere dinamicamente i controller al sito Web di hosting mentre è attivo e funzionante, senza richiedere un'interruzione.

Il problema principale con questo codice è ovviamente che il controller appena caricato non viene aggiunto all'elenco dei controller registrati, quindi l'eccezione viene sempre generata e gestita su ogni richiesta (per quei controller). Sto esaminando se posso aggiungerlo o meno all'elenco registrato in qualche modo, quindi vedremo dove questo porta.