API Web dalam solusi MVC dalam proyek terpisah

88

Saya membuat proyek MVC4 baru, dan penelitian telah membuat saya percaya bahwa berkomunikasi dari javascript ke sisi server lebih baik dicapai sekarang melalui kerangka API web daripada tindakan pengontrol. Apakah pemahaman saya benar tentang ini?

Saya berasumsi bahwa saya dapat membagikan semua atribut saya dll antara API web dan pengontrol MVC jadi secara langsung, tampaknya itu bukan perubahan besar bagi saya.

Saat saya menyiapkan aplikasi, saya suka membagi komponen menjadi proyek. Rencana saya adalah memiliki proyek MVC dan proyek API web. Tapi saya mengalami masalah. Misalnya saya telah berakhir dengan 2 aplikasi seperti itu, pengaturan perutean terpisah, dll.

Jadi pertanyaan saya adalah, dalam aplikasi MVC haruskah kerangka kerja API web berada dalam proyek yang sama, atau haruskah API web dipisahkan menjadi proyeknya sendiri dan mengatasi masalah?

amatir
sumber

Jawaban:

110

Sayangnya Anda salah tentang itu - Saya berasumsi bahwa saya dapat membagikan semua atribut saya dll antara api web dan pengontrol mvc jadi secara langsung, tampaknya itu bukan perubahan besar bagi saya.

Banyak konsep yang digunakan oleh Web API dan MVC, meskipun sekilas mirip, sebenarnya tidak kompatibel. Misalnya, atribut API Web adalah System.Web.Http.Filters.Filterdan atribut MVC adalah System.Web.Mvc.Filter- dan tidak dapat dipertukarkan.

Hal yang sama berlaku untuk banyak konsep lainnya - pengikatan model (mekanisme yang benar-benar berbeda), rute (API Web menggunakan HTTPRoutes bukan Routes, meskipun keduanya beroperasi pada RouteTable yang mendasari yang sama), resolver ketergantungan (tidak kompatibel) dan banyak lagi - meskipun serupa pada permukaan, sangat berbeda dalam praktiknya. Selain itu, API Web tidak memiliki konsep area.

Pada akhirnya, jika semua yang Anda coba capai adalah memiliki cara yang "baru, trendi" dalam menyajikan konten JSON - pikirkan dua kali sebelum mengambil jalan itu. Saya pasti tidak akan merekomendasikan refactoring kode yang ada kecuali Anda benar-benar ingin merangkul HTTP dan membangun aplikasi Anda dengan cara yang tenang.

Itu semua sangat tergantung pada apa yang Anda bangun. Jika Anda memulai proyek baru, dan yang Anda butuhkan hanyalah menyediakan beberapa JSON untuk memfasilitasi aplikasi web Anda - asalkan Anda bersedia untuk hidup dengan beberapa kode yang berpotensi duplikat (seperti hal yang saya sebutkan di atas), API Web dapat dengan mudah dihosting di dalam proyek yang sama dengan ASP.NET MVC.

Saya hanya akan memisahkan API Web ke dalam proyek terpisah jika Anda akan membangun API yang tepat untuk layanan online Anda - mungkin untuk digunakan oleh pelanggan eksternal, atau oleh berbagai perangkat - seperti mengisi aplikasi seluler Anda.

Filip W
sumber
2
+1 Jawaban yang sangat bagus. Saya pikir awalnya MVC dan WebAPI dapat berbagi beberapa kode terutama dalam hal filter, model binding, dll. Tetapi keduanya sama sekali berbeda.
VJAI
5
Ya dalam skenario seperti itu cukup mulai proyek MVC4 baru di Visual Studio, dan ketika diminta untuk template proyek (layar kedua) cukup pilih API Web. Itu akan menginstal API Web dari Nuget dan dalam kasus yang Anda jelaskan akan baik-baik saja. Apa yang Anda dapatkan adalah file konfigurasi API Web terpisah yang dicolokkan ke Global.asax. Selain itu Anda mungkin ingin memisahkan Pengontrol API ke dalam folder terpisah (secara default mereka bersama-sama dengan pengontrol MVC). Akhirnya, rute default jelas dikonfigurasi secara terpisah dan tidak saling mengganggu
Filip W
9
Saya berharap pimpinan saya membaca posting ini sebelum dia merancang proyek kami saat ini.
Billdr
2
@FilipW Terima kasih atas penjelasan yang bagus. Saya juga memiliki aplikasi MVC dan akan menggunakan WebAPI2 untuk menggunakan layanan untuk aplikasi Android. Di sisi lain, seperti yang dikatakan David Peden di bawah ini, keamanan, pemeliharaan, dan penerapan juga sangat penting saat memutuskan untuk membuat proyek terpisah baru untuk WebAPI. Dalam hal ini, dengan mengingatnya, apa yang akan Anda sarankan? Untuk membuat proyek baru yang terpisah untuk WebAPI atau menggunakan proyek MVC saat ini? Terima kasih sebelumnya.
Jack
1
Sangat bagus "Saya hanya akan memisahkan API Web ke dalam proyek terpisah jika Anda akan membuat API yang sesuai untuk layanan online Anda - mungkin untuk digunakan oleh pelanggan eksternal, atau oleh berbagai perangkat - seperti mengisi daya aplikasi seluler Anda." tepat sasaran dan memudahkan untuk menentukan cara mana yang harus dilakukan.
ozzy432836
27

IMO, keamanan, dan penerapan harus mendorong keputusan Anda. Misalnya, jika aplikasi MVC Anda menggunakan otentikasi Formulir tetapi Anda tertarik untuk menggunakan otentikasi Dasar (dengan SSL) untuk API Anda, proyek terpisah akan membuat hidup Anda lebih mudah. Jika Anda ingin menghosting situs Anda di www.example.com tetapi menghosting API Anda sebagai api.example.com (vs. www.example.com/api), proyek terpisah akan membuat hidup Anda lebih mudah. Jika Anda memisahkan proyek dan subdomainnya sesuai dengan itu dan Anda bermaksud memanfaatkan API Anda sendiri dari aplikasi MVC, Anda harus mencari cara untuk menangani masalah Kebijakan Asal yang Sama untuk panggilan sisi klien ke API Anda. Solusi umum untuk ini adalah dengan memanfaatkan jsonp atau CORS (sebaiknya jika Anda bisa).

Pembaruan (26/3/2013): Dukungan CORS resmi akan datang: http://aspnetwebstack.codeplex.com/wikipage?title=CORS%20support%20for%20ASP.NET%20Web%20API

David Peden
sumber
Saya mencoba untuk memahami masalah seputar keputusan untuk mengintegrasikan API Web dengan aplikasi MVC saya atau menjadikannya sebagai proyek terpisah. Saya berhasil menerapkan aplikasi Web API HelloWorld ke sub-domain di host web saya. Dari proyek terpisah ini, saya kemungkinan besar akan menggunakan Model dari aplikasi web MVC saya dan kode panggilan dalam proyek terpisah itu. Sepertinya mungkin lebih mudah untuk mengambil rute proyek terpisah ini, tetapi menurut Anda masalah apa yang dapat saya hadapi dengan pendekatan ini?
Ciaran Gallagher
2
Secara pribadi, saya tidak akan menggunakan model tampilan Anda sebagai DTO untuk API Anda. Saya berharap bahwa keputusan itu akan menyebabkan Anda mengalami kesulitan serius karena model tampilan dan tanda tangan API Anda berbeda. SoC ( en.wikipedia.org/wiki/Separation_of_concerns ) sangat penting.
David Peden
@DavidPeden Anda menyarankan untuk membuat proyek baru yang terpisah untuk WebAPI. Benarkah itu? Di sisi lain, saya akan membuat proyek terpisah baru untuk WebAPI (saat ini saya memiliki Lapisan UI (MVC) dan Lapisan Data (Perpustakaan Kelas) di aplikasi saya. Jadi, saya juga menggunakan DI, tetapi saya bertanya-tanya apakah saya dapat menggunakan Entitas, Repositori, Antarmuka, dan kelas Abstrak yang sama di Lapisan Data untuk proyek WebAPI yang baru dibuat dan satu-satunya hal yang harus saya lakukan adalah membuat Pengontrol WebAPI? Atau apakah saya juga membuat semuanya (Entitas, Repositori, Antarmuka, dan Abstrak kelas) lagi untuk WebAPI? Ada bantuan?
Jack
1
@ H.Johnson Sulit untuk memberikan saran umum yang bermakna tetapi sepertinya Anda akan mendapat manfaat dari memiliki lapisan layanan aplikasi yang merangkum entitas dan repositori Anda yang dapat dimanfaatkan oleh kedua UI Anda (MVC dan API).
David Peden
9

Setelah beberapa tingkat pengalaman (membuat API untuk aplikasi dan untuk MVC). Saya kebanyakan melakukan keduanya.

Saya membuat proyek terpisah untuk panggilan api yang berasal dari klien lain atau perangkat lain (aplikasi Android / IOS). Salah satu alasannya adalah karena otentikasi berbeda, itu berbasis token (agar tetap tanpa kewarganegaraan). Saya tidak ingin mencampur ini dalam aplikasi MVC saya.

Untuk panggilan javascript / jquery api saya ke aplikasi MVC saya, saya suka membuat semuanya sederhana jadi saya menyertakan api web di dalam aplikasi MVC saya. Saya tidak bermaksud untuk memiliki otentikasi berbasis token dengan panggilan api javascript saya, karena hei, itu dalam aplikasi yang sama. Saya hanya bisa menggunakan [authorize]atribut pada titik akhir API, ketika pengguna tidak masuk, dia tidak akan mendapatkan data.

Selanjutnya, ketika berurusan dengan keranjang belanja dan Anda ingin menyimpan keranjang belanja pengguna dalam satu sesi (saat tidak masuk), Anda harus memiliki ini di API Anda juga jika Anda menambahkan / menghapus produk melalui kode javascript Anda. Ini akan membuat API Anda menjadi stateful, tetapi juga akan mengurangi kompleksitas di MVC-API Anda.

CularBytes
sumber
4
Ya @Dimi, itu adalah suntingan yang tidak berguna untuk mendapatkan beberapa suara ... Bagaimana saya bisa menolak ini?
CularBytes
Lakukan apa yang kamu inginkan. Saya mengedit bukan berdasarkan suara tetapi untuk tampilan terbaik yang saya asumsikan. Lanjutkan.
DmitryBoyko
3
@CularBytes Anda tidak dapat menolak hasil edit, tetapi Anda dapat mengeditnya lagi dan mengembalikan perubahan. Ini membutuhkan proses tinjauan sejawat di bawah 2.000 perwakilan, tetapi Anda memiliki cukup perwakilan untuk melakukannya secara instan. Saya setuju bahwa suntingan tidak menambah nilai dan telah mengembalikannya untuk Anda.
Dan Bechard
5

Saya baru-baru ini melakukan hal yang hampir sama: Saya mulai dengan proyek aplikasi web MVC 4 baru dengan memilih template API Web di VS2012.

Ini akan membuat API Web yang dihosting di aplikasi yang sama dengan MVC.

Saya ingin memindahkan ApiControllers ke dalam proyek perpustakaan kelas yang terpisah. Ini cukup mudah tetapi solusinya agak tersembunyi.

Dalam AssemblyInfo.cs dari proyek MVC 4 tambahkan baris kode yang serupa

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

Sekarang Anda memerlukan LibraryRegistrator kelas (jangan ragu untuk menamainya apa saja)

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

Dalam proyek MVC 4 tambahkan juga referensi ke perpustakaan Api.

Sekarang Anda dapat menambahkan pengontrol Api ke perpustakaan kelas Anda yang terpisah (yourown.dll).

fanvabra.dll
sumber
2

Bahkan jika proyek Anda begitu kompleks sehingga menjamin dua "ujung depan" maka saya masih hanya akan mempertimbangkan membagi webapi menjadi proyek terpisah sebagai pilihan terakhir. Anda akan mengalami sakit kepala penerapan dan akan sulit bagi seorang pemula untuk memahami struktur solusi Anda. Belum lagi masalah perutean.

Saya akan bertujuan untuk menjaga namespace system.Web diisolasi dalam satu "lapisan presentasi". Meskipun webapi tidak sedang disajikan, itu masih merupakan bagian dari antarmuka aplikasi Anda. Selama Anda menyimpan logika di domain Anda dan bukan pengontrol Anda, Anda tidak akan mengalami terlalu banyak masalah. Juga, jangan lupa untuk memanfaatkan Area.

Nick
sumber
1
Alasan utama saya menginginkan proyek terpisah adalah karena API tidak benar-benar ujung depan. Itu tingkat menengah.
lordcheeto
6
"Sulit bagi seorang pemula untuk memahami" bukanlah alasan yang bagus untuk memilih satu pendekatan di atas yang lain. Sederhanakan jika memungkinkan, tentu, tetapi kebutuhan yang kompleks sering kali membutuhkan solusi yang rumit. Daripada menulis kode bodoh untuk melayani pemula, kita harus melatih pemula untuk memahami dan menulis kode pintar.
Dan Bechard
0

Selain mengatur DLL terpisah untuk Web.Api.

Hanya sebuah saran:

  1. Buat Proyek
  2. Nugget WebActivatorEx
  3. Buat Metode kelas yang akan dipanggil setelah app_start

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

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

  4. Daftarkan rute web.api di dalam Metode Mulai

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

  5. Referensi Proyek ke Proyek Web. untuk mengaktifkan Metode Mulai.

Semoga ini membantu.

jayson.centeno
sumber
0

Saya mencoba membagi pengontrol API menjadi proyek baru. Yang saya lakukan hanyalah membuat proyek perpustakaan baru, memindahkan pengontrol di dalam folder bernama API. Kemudian menambahkan referensi proyek perpustakaan ke proyek MVC.

Konfigurasi webAPI dibiarkan di proyek MVC itu sendiri. Ini bekerja dengan baik.

jaicind
sumber