asp.net mvc inserisce i controller in un progetto separato


107

Sto solo imparando asp.net mvc e sto cercando di capire come spostare i miei controller in un progetto separato. In genere, quando ho progettato le app Web asp.net in precedenza, ho creato un progetto per i miei modelli, un altro per la mia logica e poi c'era il Web.

Ora che sto imparando asp.net mvc, speravo di seguire uno schema simile e inserire i modelli e i controller ciascuno nei propri progetti separati e lasciare semplicemente le visualizzazioni / script / css nel web. La parte relativa ai modelli è stata facile, ma quello che non capisco è come "trovare" i miei controller in un progetto separato. Inoltre, vorrei sapere se è consigliabile. Grazie!

Risposte:


92

Prima di tutto, è sicuramente una buona idea inserire il tuo modello in un progetto separato. Come hai scoperto, questo è banale.

Per quanto riguarda i controller e le viste, non vedo alcun vantaggio evidente nel separarli per la maggior parte dei progetti di base, sebbene potresti avere una particolare necessità di farlo in una particolare applicazione.

Se scegli di farlo, dovrai dire al framework come trovare i tuoi controller. Il modo di base per farlo è fornire il proprio ControllerFactory. Puoi dare un'occhiata al codice sorgente di DefaultControllerFactory per avere un'idea di come farlo. Sottotitolare questa classe e sovrascrivere il metodo GetControllerType (string controllerName) potrebbe essere sufficiente per ottenere ciò che stai chiedendo.

Dopo aver creato il tuo ControllerFactory personalizzato, aggiungi la seguente riga a Application_Start in global.asax per dire al framework dove trovarlo:

ControllerBuilder.Current.SetControllerFactory(new MyControllerFactory());

Aggiornamento: leggi questo post e i post a cui si collega per maggiori informazioni. Vedi anche il commento di Phil Haack su quel post su:

ControllerBuilder.Current.DefaultNamespaces.Add(
    "ExternalAssembly.Controllers");

... che non è una soluzione completa, ma forse abbastanza buona per casi semplici.


2
Grazie Craig! Questo è esattamente quello che stavo cercando. Queste informazioni esistono anche sul web? Ho cercato su Google dappertutto senza molta fortuna. StackOverflow arriva di nuovo!
Aaron Palmer il

11
Sono d'accordo, i controller gestiscono l'input dell'utente, manipolano il modello, quindi passano i dati alla vista. In genere sono molto specifici per un'applicazione. Qualsiasi logica non specifica dell'app potrebbe essere migliore in una libreria o nel modello. Ma i controller in generale dovrebbero essere con il progetto web.
Haacked

2
Ho un controller degli errori e visualizzazioni identiche tra due app. Per me ha senso averli in un singolo assembly che entrambe le app possono utilizzare.
Judo in barca a vela

3
Non è più facile testare i controller e utilizzare IoC quando i controller si trovano in un progetto separato - questo sarebbe il motivo principale
Samuel G,

1
@Chev, non credo che faccia alcuna differenza lì. La testabilità dei tuoi controller ha più a che fare con il modo in cui li codifichi , non con il luogo in cui vivono.
Craig Stuntz

19

Sebbene sia ragionevole creare il proprio ControllerFactory, ho trovato più conveniente definire tutti i miei controller in ogni progetto, ma derivarli dai controller nel mio progetto condiviso:

namespace MyProject1.Controllers
{
   public class MyController : MySharedProject.Controllers.MyController
   {
      // nothing much to do here...
   }
}

namespace MySharedProject.Controllers
{
   public abstract class MyController : System.Web.Mvc.Controller
   {
      // all (or most) of my controller logic here...
   }
}

Questo ha l'ulteriore vantaggio di avere un posto dove mettere la logica del controller che differisce da progetto a progetto. Inoltre, è più facile per altri sviluppatori trovare rapidamente la logica del controller perché i controller esistono nella posizione standard.

Per quanto riguarda se questo sia consigliabile, penso che lo sia assolutamente. Ho creato alcune logiche di gestione degli account comuni che voglio condividere tra progetti che altrimenti hanno logiche di business molto diverse. Quindi condivido il mio account e i controller di amministrazione, ma gli altri controller sono specifici per i rispettivi progetti.


1
Funzionava molto bene, ma ho dovuto eliminare del codice ridondante per evitare un errore di instradamento
Ken Mc

Ciao, come posso gestire il routing in questo tipo di progetto? voglio utilizzare il routing degli attributi ...
محمد

Puoi usare il routing degli attributi proprio come faresti normalmente.
ThisGuy

2
Non sono sicuro del motivo per cui questo non ha più voti positivi ... molto più elegante della risposta accettata, penso. Grazie!
jleach

Questo non funziona per me. Potresti dire che si tratta di .Net Core o .Net Framework?
Homayoun Behzadian

4
  • Aggiungi la libreria di classi per il tuo progetto mvc.
  • Nella classe aggiungi il seguente codice (For u'r Controller Code)

    namespace ContactController
    {
    public class ContactController : Controller
    {
        public ActionResult Call()
        {
            ViewBag.Title = "Inside MyFirst Controller.";
            return View();
        }
    }

    }

  • Nella cartella della vista del progetto mvc aggiungi la cartella per Contact e crea un file Call.cshtml. Vedi cartella

  • Aggiungere il riferimento al progetto della libreria di classi nel progetto MVC principale.

Riferimento

  • Infine, per fare riferimento allo spazio dei nomi del controller di contatto in Route Config.

RouteConfig


3
È un po 'un peccato che tu abbia uno spazio dei nomi con lo stesso nome del controller.
Mariusz Jamro

3

Il mio problema è stato risolto dopo aver aggiornato il System.Web.Mvcriferimento NuGet in modo che MvcWebsite e Class Library utilizzino la stessa System.Web.Mvcversione

Non è necessario aggiungere spazi dei nomi predefiniti


Il problema era che MvcWebsite non generava eccezioni mentre l'attuale assembly mvc ha una versione inferiore rispetto all'assembly mvc di riferimento della libreria di classi
Homayoun Behzadian

1

La forma più semplice di separazione che utilizzo è mantenere le viste "così come sono" nel progetto MVC originale ma rimuovere i controller. Quindi in un nuovo progetto ClassLibrary aggiungi le classi Controller e assicurati che ereditino da Controller.

Il motore di routing MVC instraderà automaticamente ai controller nella ClassLibrary e i controller costruiranno automaticamente le viste dal progetto MVC originale, a condizione che i riferimenti e gli utilizzi siano corretti.

Sto usando questa architettura per implementare un modulo di report HTML che può essere compilato e distribuito separatamente dalla soluzione principale. Finalmente sono libero da SSRS!

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.