asp.net mvc umieszcza kontrolery w osobnym projekcie

107

Właśnie uczę się asp.net mvc i próbuję dowiedzieć się, jak przenieść moje kontrolery do osobnego projektu. Zwykle, gdy wcześniej projektowałem aplikacje internetowe asp.net, utworzyłem jeden projekt dla moich modeli, inny dla mojej logiki, a potem była sieć Web.

Teraz, gdy uczę się asp.net mvc, miałem nadzieję, że będę postępować zgodnie z podobnym wzorcem i umieszczać modele i kontrolery w osobnych projektach, a po prostu zostawić widoki / skrypty / css w sieci Web. Część dotycząca modeli była łatwa, ale nie rozumiem, jak sprawić, by moje kontrolery w osobnym projekcie zostały „znalezione”. Chciałbym również wiedzieć, czy jest to wskazane. Dzięki!

Aaron Palmer
źródło

Odpowiedzi:

92

Przede wszystkim z pewnością dobrym pomysłem jest umieszczenie modelu w osobnym projekcie. Jak odkryłeś, jest to trywialne.

Jeśli chodzi o kontrolery i widoki, nie widzę żadnej oczywistej korzyści z oddzielania ich dla większości podstawowych projektów, chociaż możesz mieć szczególną potrzebę zrobienia tego w konkretnej aplikacji.

Jeśli zdecydujesz się to zrobić, będziesz musiał powiedzieć platformie, jak znaleźć kontrolery. Podstawowym sposobem na to jest dostarczenie własnej fabryki ControllerFactory. Możesz spojrzeć na kod źródłowy DefaultControllerFactory, aby dowiedzieć się, jak to się robi. Podpisanie tej klasy i zastąpienie metody GetControllerType (string controllerName) może wystarczyć, aby wykonać to, o co prosisz.

Po utworzeniu własnej niestandardowej fabryki ControllerFactory dodaj następujący wiersz do Application_Start w global.asax, aby wskazać platformie, gdzie ją znaleźć:

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

Aktualizacja: Przeczytaj ten post i posty, do których prowadzi, aby uzyskać więcej informacji. Zobacz także komentarz Phila Haacka do tego posta o:

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

... co nie jest kompletnym rozwiązaniem, ale prawdopodobnie wystarczające w prostych przypadkach.

Craig Stuntz
źródło
2
Dzięki Craig! To jest dokładnie to, czego szukałem. Czy te informacje są w ogóle dostępne w sieci? Szukałem go w Google bez większego szczęścia. StackOverflow znów się pojawia!
Aaron Palmer
11
Zgadzam się, kontrolery obsługują dane wejściowe użytkownika, manipulują modelem, a następnie przekazują dane do widoku. Zazwyczaj są one bardzo specyficzne dla aplikacji. Każda logika, która nie jest specyficzna dla aplikacji, może być lepsza w bibliotece lub modelu. Ale ogólnie kontrolerzy powinni być przy projekcie internetowym.
Haacked
2
Mam kontroler błędów i widoki, które są identyczne między dwiema aplikacjami. Dla mnie sensowne jest posiadanie ich w jednym zestawie, z którego mogą korzystać obie aplikacje.
Sailing Judo
3
Czy nie jest łatwiej przetestować kontrolery i używać IoC, gdy kontrolery są w osobnym projekcie - to byłby główny powód
Samuel Goldenbaum
1
@Chev, myślę, że to nie robi różnicy. Testowalność twoich kontrolerów ma więcej wspólnego z tym, jak je kodujesz , a nie gdzie mieszkają.
Craig Stuntz
19

Chociaż rozsądne jest utworzenie własnej fabryki ControllerFactory, wydaje mi się, że wygodniej jest zdefiniować wszystkie moje kontrolery w każdym projekcie, ale wyprowadzić je z kontrolerów w moim projekcie współdzielonym:

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...
   }
}

Ma to dodatkową zaletę, że masz miejsce na umieszczenie logiki kontrolera, która różni się w zależności od projektu. Ponadto innym programistom łatwiej jest szybko znaleźć logikę kontrolera, ponieważ kontrolery istnieją w standardowym miejscu.

Jeśli chodzi o to, czy jest to wskazane, myślę, że tak jest. Stworzyłem wspólną logikę zarządzania kontami, którą chcę udostępniać między projektami, które w przeciwnym razie mają bardzo różną logikę biznesową. Dlatego udostępniam moje konto i kontrolery administratora, ale inne kontrolery są specyficzne dla swoich projektów.

Ten facet
źródło
1
To działało bardzo dobrze, ale musiałem wyeliminować część nadmiarowego kodu, aby zapobiec błędowi routingu
Ken Mc
Cześć, jak mogę zarządzać routingiem w tego typu projektach? chcę użyć routingu atrybutów ...
محمد
Możesz używać routingu atrybutów tak, jak zwykle.
ThisGuy
2
Nie jestem pewien, dlaczego to nie ma więcej pozytywnych głosów ... o wiele bardziej eleganckiej niż zaakceptowana odpowiedź, myślę. Dzięki!
jleach
To nie działa dla mnie. Czy możesz powiedzieć, czy to .Net Core czy .Net Framework?
Homayoun Behzadian,
4
  • Dodaj bibliotekę klas do projektu MVC.
  • W klasie dodaj następujący kod (For u'r Controller Code)

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

    }

  • W folderze widoku projektu mvc dodaj folder dla kontaktu i utwórz plik Call.cshtml. Wyświetl folder

  • Dodaj odwołanie do projektu biblioteki klas do głównego projektu MVC.

Odniesienie

  • Wreszcie, aby odwołać się do przestrzeni nazw kontrolera kontaktów do konfiguracji trasy.

RouteConfig

RandyMohan
źródło
3
To trochę niefortunne, że masz przestrzeń nazw o takiej samej nazwie jak kontroler.
Mariusz Jamro
3

Mój problem został rozwiązany po zaktualizowaniu System.Web.Mvcodwołania NuGet, więc MvcWebsite i Class Library używają tej samej System.Web.Mvcwersji

Nie ma potrzeby dodawania domyślnych przestrzeni nazw

Homayoun Behzadian
źródło
Problem polegał na tym, że MvcWebsite nie zgłosił wyjątku, podczas gdy obecny zestaw mvc ma niższą wersję niż zestaw mvc, do którego odwołuje się biblioteka klas
Homayoun Behzadian
1

Najprostszą formą separacji, której używam, jest zachowanie widoków „tak jak jest” w oryginalnym projekcie MVC, ale usunięcie kontrolerów. Następnie w nowym projekcie ClassLibrary Dodaj klasy Controller i upewnij się, że dziedziczą po Controller.

Silnik routingu MVC automatycznie przekieruje do kontrolerów w ClassLibrary, a kontrolery automatycznie skonstruują widoki z oryginalnego projektu MVC, pod warunkiem, że masz odpowiednie odniesienia i zastosowania.

Używam tej architektury do implementacji modułu Html Reports, który można skompilować i wdrożyć niezależnie od głównego rozwiązania. Nareszcie jestem wolny od SSRS!

Jamie
źródło