Web API w rozwiązaniu MVC w osobnym projekcie

88

Tworzę nowy projekt MVC4, a badania doprowadziły mnie do przekonania, że ​​komunikacja z javascript do strony serwera jest teraz lepiej realizowana za pomocą struktury internetowego interfejsu API, a nie akcji kontrolera. Czy moje zrozumienie jest prawidłowe?

Zakładam, że mogę udostępniać wszystkie swoje atrybuty itp. Między kontrolerami internetowego interfejsu API i MVC, więc na pierwszy rzut oka nie wydaje mi się to ogromną zmianą.

Kiedy konfiguruję aplikacje, lubię rozdzielać komponenty na projekty. Planowałem mieć projekt MVC i projekt internetowego interfejsu API. Ale napotkałem problemy. Na przykład otrzymałem 2 aplikacje jako takie, oddzielną konfigurację routingu itp.

Więc moje pytanie brzmi, czy w aplikacji MVC struktura interfejsu API sieci Web powinna znajdować się w tym samym projekcie, czy też interfejs API sieci Web powinien być podzielony na własny projekt i obejść problemy?

amator
źródło

Odpowiedzi:

110

Niestety mylisz się co do tego - przypuszczam, że mogę dzielić się wszystkimi swoimi atrybutami itp. Między kontrolerami web api i mvc, więc pozornie nie wydaje mi się to ogromną zmianą.

Wiele koncepcji używanych przez Web API i MVC, mimo że na pierwszy rzut oka są podobne, w rzeczywistości nie jest zgodnych. Na przykład atrybuty interfejsu API sieci Web są, System.Web.Http.Filters.Filtera atrybuty MVC są System.Web.Mvc.Filter- i nie są one zamienne.

To samo dotyczy wielu innych koncepcji - powiązanie modelu (zupełnie inne mechanizmy), trasy (interfejs API sieci Web używa HTTPRoutes, a nie Routes, mimo że oba działają na tej samej podstawowej tabeli RouteTable), mechanizm rozpoznawania zależności (niekompatybilny) i więcej - mimo że podobne w powierzchni, są w praktyce bardzo różne. Ponadto interfejs API sieci Web nie ma koncepcji obszarów.

Ostatecznie, jeśli wszystko, co próbujesz osiągnąć, to mieć „nowy, modny” sposób obsługi treści JSON - zastanów się dwa razy, zanim pójdziesz tą ścieżką. Z pewnością nie polecałbym refaktoryzacji żadnego istniejącego kodu, chyba że naprawdę chcesz objąć HTTP i zbudować swoją aplikację w sposób RESTful.

Wszystko naprawdę zależy od tego, co budujesz. Jeśli zaczynasz nowy projekt i wszystko, czego potrzebujesz, to udostępnić trochę JSON, aby ułatwić swoją aplikację internetową - pod warunkiem, że chcesz żyć z potencjalnie zduplikowanym kodem (takim jak rzeczy, o których wspomniałem powyżej), interfejs API sieci Web może być łatwo hostowany w ten sam projekt co ASP.NET MVC.

Oddzieliłbym interfejs API sieci Web na osobny projekt tylko wtedy, gdy zamierzasz zbudować odpowiedni interfejs API dla swojej usługi online - być może do wykorzystania przez klientów zewnętrznych lub różne urządzenia - na przykład do zasilania aplikacji mobilnych.

Filip W.
źródło
2
+1 Doskonała odpowiedź. Myślałem, że początkowo zarówno MVC, jak i WebAPI mogą współdzielić część kodu, szczególnie w przypadku filtrów, powiązań modelu itp., Ale są one zupełnie inne.
VJAI
5
Tak, w takim scenariuszu po prostu uruchom nowy projekt MVC4 w programie Visual Studio, a po wyświetleniu monitu o szablon projektu (drugi ekran) po prostu wybierz interfejs API sieci Web. Spowoduje to zainstalowanie interfejsu API sieci Web firmy Nuget iw przypadku, który opisałeś, powinno być idealnie. Otrzymujesz osobny plik konfiguracyjny interfejsu API sieci Web podłączony do Global.asax. Ponadto możesz chcieć oddzielić kontrolery API do osobnego folderu (domyślnie są one razem z kontrolerami MVC). Wreszcie trasy domyślne są oczywiście konfigurowane osobno i nie kolidują ze sobą
Filip W
9
Chciałbym, żeby mój kierownik przeczytał ten post, zanim zaprojektował nasz obecny projekt.
Billdr,
2
@FilipW Dzięki za dobre wyjaśnienia. Mam również aplikację MVC i będę używać WebAPI2 do korzystania z usługi dla aplikacji na Androida. Z drugiej strony, jak mówi poniżej David Peden, bezpieczeństwo, konserwacja i wdrażanie są również bardzo ważne przy podejmowaniu decyzji o stworzeniu nowego, oddzielnego projektu dla WebAPI. W takim razie, pamiętając o nich, co byś zasugerował? Aby utworzyć nowy oddzielny projekt dla WebAPI lub użyć bieżącego projektu MVC? Z góry dziękuję.
Jack
1
Bardzo dobrze „Oddzieliłbym interfejs API sieci Web na osobny projekt tylko wtedy, gdy zamierzasz zbudować odpowiedni interfejs API dla swojej usługi online - być może do wykorzystania przez klientów zewnętrznych lub różne urządzenia - na przykład do zasilania aplikacji mobilnych”. trafia w gwóźdź w głowę i ułatwia określenie, w jaki sposób to zrobić.
ozzy432836
27

IMO, bezpieczeństwo i wdrożenie powinny wpłynąć na Twoją decyzję. Na przykład, jeśli Twoja aplikacja MVC używa uwierzytelniania formularzy, ale chcesz używać uwierzytelniania podstawowego (z SSL) dla swojego interfejsu API, oddzielne projekty ułatwią Ci życie. Jeśli chcesz hostować swoją witrynę pod adresem www.example.com, ale udostępniać swoje API jako api.example.com (zamiast www.example.com/api), osobne projekty ułatwią Ci życie. Jeśli oddzielisz swoje projekty i odpowiednio je subdomeną, a zamierzasz wykorzystać własny interfejs API z aplikacji MVC, będziesz musiał dowiedzieć się, jak poradzić sobie z problemem Same Origin Policy w przypadku wywołań po stronie klienta do interfejsu API. Typowe rozwiązania tego problemu to wykorzystanie jsonp lub CORS (najlepiej, jeśli możesz).

Aktualizacja (26.03.2013): Nadchodzi oficjalna obsługa CORS: http://aspnetwebstack.codeplex.com/wikipage?title=CORS%20support%20for%20ASP.NET%20Web%20API

David Peden
źródło
Próbuję poradzić sobie z problemami związanymi z decyzją o zintegrowaniu interfejsu API sieci Web z moją aplikacją MVC lub o osobnym projekcie. Udało mi się pomyślnie wdrożyć aplikację Web API HelloWorld w subdomenie na moim hoście internetowym. Z tego oddzielnego projektu prawdopodobnie będę używał modelu z mojej aplikacji internetowej MVC i wywoływał kod w tym oddzielnym projekcie. Wydaje się, że łatwiej byłoby podążać tą ścieżką oddzielnego projektu, ale jak myślisz, jakie problemy mógłbym napotkać przy takim podejściu?
Ciaran Gallagher,
2
Osobiście nie użyłbym twojego modelu widoku jako DTO dla twojego API. Spodziewałbym się, że ta decyzja sprawi ci poważny ból na drodze, gdy twoje modele widoku i sygnatury API różnią się. SoC ( en.wikipedia.org/wiki/Separation_of_concerns ) jest bardzo ważne.
David Peden
@DavidPeden Sugerujesz utworzenie nowego oddzielnego projektu dla WebAPI. Czy to prawda? Z drugiej strony utworzę nowy osobny projekt dla WebAPI (obecnie mam w swojej aplikacji UI Layer (MVC) i Data Layer (Class Library). Więc też używam DI, ale zastanawiam się, czy mogę użyć te same encje, repozytoria, interfejsy i klasy abstrakcyjne w warstwie danych dla nowo utworzonego projektu WebAPI i jedyne, co muszę zrobić, to utworzyć kontrolery WebAPI? A może też utworzę je wszystkie (jednostki, repozytoria, interfejsy i streszczenie zajęcia) ponownie dla WebAPI? Proszę o pomoc?
Jack
1
@ H.Johnson Trudno jest udzielić ogólnych porad, które są sensowne, ale wygląda na to, że korzystasz z warstwy usług aplikacji, która hermetyzuje Twoje encje i repozytoria, które mogą być wykorzystywane przez oba interfejsy użytkownika (MVC i API).
David Peden
9

Po pewnym stopniu doświadczenia (tworzenie API dla aplikacji i dla MVC). Przeważnie robię jedno i drugie.

Tworzę osobny projekt dla wywołań API pochodzących od innych klientów lub innych urządzeń (aplikacje Android / IOS). Jednym z powodów jest to, że uwierzytelnianie jest inne, jest oparte na tokenach (aby było bezstanowe). Nie chcę mieszać tego w mojej aplikacji MVC.

W przypadku wywołań api javascript / jquery do mojej aplikacji MVC, lubię upraszczać wszystko, więc dołączam interfejs API sieci Web do mojej aplikacji MVC. Nie zamierzam używać uwierzytelniania opartego na tokenach z moimi wywołaniami javascript api, ponieważ hej, jest w tej samej aplikacji. Mogę po prostu użyć [authorize]atrybutu na punkcie końcowym API, gdy użytkownik nie jest zalogowany, nie otrzyma danych.

Ponadto, gdy masz do czynienia z koszykami i chcesz przechowywać koszyk użytkownika w sesji (nie będąc zalogowanym), musisz mieć to również w swoim API, jeśli dodajesz / usuwasz produkty za pomocą kodu javascript. To z pewnością sprawi, że twój API będzie stanowy, ale także zmniejszy złożoność twojego MVC-API.

CularBytes
źródło
4
Cóż, @Dimi, to bezużyteczna edycja, aby zdobyć kilka głosów ... Jak mogę je odrzucić?
CularBytes
Rób co chcesz. Edytuję nie głosami, ale dla najlepszego wyglądu zakładam. Śmiało.
DmitryBoyko
3
@CularBytes Nie możesz odrzucić zmian, ale możesz edytować je ponownie i cofnąć zmiany. Wymaga to procesu wzajemnej oceny poniżej 2000 powtórzeń, ale masz wystarczającą liczbę powtórzeń, aby zrobić to natychmiast. Zgadzam się, że zmiana nie dodała żadnej wartości i wycofałem ją dla Ciebie.
Dan Bechard,
5

Niedawno zrobiłem prawie to samo: zacząłem od nowego projektu aplikacji internetowej MVC 4, wybierając szablon Web API w VS2012.

Spowoduje to utworzenie interfejsu API sieci Web hostowanego w tej samej aplikacji co MVC.

Chciałem przenieść ApiControllers do osobnego projektu biblioteki klas. Było to dość łatwe, ale rozwiązanie było nieco ukryte.

W AssemblyInfo.cs projektu MVC 4 dodaj podobny wiersz kodu

[assembly: PreApplicationStartMethod(typeof(LibraryRegistrator), "Register")]

Teraz potrzebujesz klasy LibraryRegistrator (możesz ją dowolnie nazwać)

public class LibraryRegistrator
    {
        public static void Register()
        {
            BuildManager.AddReferencedAssembly(Assembly.LoadFrom(HostingEnvironment.MapPath("~/bin/yourown.dll")));
        }
    }

W projekcie MVC 4 dodaj również odniesienie do biblioteki API.

Teraz możesz dodać kontrolery Api do własnej oddzielnej biblioteki klas (yourown.dll).

fanvabra
źródło
2

Nawet jeśli Twój projekt jest tak złożony, że wymaga dwóch „front-endów”, nadal rozważałbym podzielenie webapi na osobny projekt jako ostateczność. Będziesz miał bóle głowy podczas wdrażania, a nowicjuszowi trudno byłoby zrozumieć strukturę Twojego rozwiązania. Nie wspominając o problemach z routingiem.

Chciałbym, aby przestrzeń nazw system.web była odizolowana w jednej „warstwie prezentacji”. Mimo że webapi nie jest prezentacyjne , nadal jest częścią interfejsu Twojej aplikacji. Dopóki utrzymujesz logikę w swojej domenie, a nie na kontrolerach, nie powinieneś napotykać zbyt wielu problemów. Nie zapomnij też skorzystać z obszarów.

Nacięcie
źródło
1
Moim głównym powodem, dla którego chcę oddzielnych projektów, jest to, że API nie jest tak naprawdę interfejsem. To średni poziom.
lordcheeto
6
„Trudno byłoby to zrozumieć nowicjuszowi” nie jest dobrym powodem, by wybrać jedno podejście zamiast drugiego. Zapewnij prostotę, jeśli to możliwe, ale złożone potrzeby często wymagają złożonych rozwiązań. Zamiast pisać głupi kod, aby zaspokoić potrzeby początkujących, powinniśmy szkolić początkujących, aby rozumieli i pisali inteligentny kod.
Dan Bechard,
0

Oprócz skonfigurowania oddzielnej biblioteki DLL dla Web.Api.

Tylko sugestia:

  1. Utwórz projekt
  2. Nugget WebActivatorEx
  3. Utwórz metodę klasy, która będzie wywoływana przy app_start

    [zestaw: WebActivatorEx.PostApplicationStartMethod (typeof (API.AppWebActivator), "Start")]

    [zestaw: WebActivatorEx.ApplicationShutdownMethod (typeof (API.AppWebActivator), "Shutdown")]

  4. Zarejestruj trasy web.api w metodzie startowej

    public static void Start () {GlobalConfiguration.Configure (WebApiConfig.Register); }

  5. Odwołaj projekt do projektu sieci Web. aby aktywować metodę uruchamiania.

Mam nadzieję że to pomoże.

jayson.centeno
źródło
0

Próbowałem podzielić kontrolery API na nowy projekt. Wszystko, co zrobiłem, to stworzyć nowy projekt biblioteki, przenieść kontrolery do folderu o nazwie API. Następnie dodano odwołanie do projektu biblioteki do projektu MVC.

Konfiguracja webAPI pozostaje w samym projekcie MVC. To działa dobrze.

jaicind
źródło