.NET di Linux: Lebih Sederhana Dari Kelihatannya

Diterbitkan: 2022-08-16

Mengembangkan solusi .NET di Linux selalu menjadi tantangan karena Microsoft Visual Studio membutuhkan Windows untuk bekerja. Setelah mengerjakan beberapa proyek .NET, saya memutuskan untuk menguji batas pengembangan .NET di Linux. Tutorial sederhana ini berfokus pada aplikasi ASP.NET MVC dengan SQL Server untuk menunjukkan betapa elegan dan efektifnya pengembangan .NET pada OS pilihan saya.

Pengembangan lingkungan

Pertama, kita harus memastikan alat .NET dan SDK yang terkait dengan rasa khusus Linux kita diinstal menggunakan panduan standar Microsoft.

Lingkungan pengembangan pilihan saya terdiri dari lingkungan pengembangan terintegrasi berjendela (IDE), manajemen basis data yang kuat dan alat kueri, basis data itu sendiri, dan alat untuk membangun dan menerapkan. Saya menggunakan alat berikut untuk mencapai fungsionalitas yang solid dan memungkinkan pengalaman pengkodean yang indah:

  • IDE: Kode Visual Studio
  • Manajemen basis data dan alat kueri: DBeaver
  • Basis data: Microsoft SQL Server (Instalasi Linux)
  • Alat pembuatan: .NET SDK Command Line Interface (CLI)
  • Mesin virtual dan kontainer: Docker

Pastikan alat-alat ini dipasang dengan benar sebelum Anda melanjutkan dengan aplikasi sampel kami.

Perancah Proyek

Dalam contoh aplikasi ini, kami akan menyoroti pengembangan dan fungsionalitas ASP.NET melalui serangkaian kasus penggunaan untuk sistem manajemen inventaris toko sepatu hipotetis. Seperti halnya aplikasi .NET baru, kita perlu membuat solusi dan kemudian menambahkan proyek ke dalamnya. Kami dapat memanfaatkan alat .NET SDK CLI untuk merancah solusi baru kami:

 mkdir Shoestore && cd Shoestore dotnet new sln

Selanjutnya, buat proyek ASP.NET yang berisi kelas utama eksplisit demi kesederhanaan, karena struktur proyek ini paling akrab bagi pengembang ASP.NET. Mari buat proyek kita menggunakan pola MVC:

 mkdir Shoestore.mvc && cd Shoestore.mvc dotnet new mvc --use-program-main=true

Selanjutnya, tambahkan proyek ke dalam solusi:

 # Go to the root of the solution cd .. dotnet sln add Shoestore.mvc/

Kami sekarang memiliki solusi default dan proyek ASP.NET yang terkandung di dalamnya. Sebelum melanjutkan, pastikan semuanya dibangun:

 cd Shoestore.mvc/ dotnet restore dotnet build

Praktik pengembangan yang baik mendorong penempatan layanan utama dan runtime aplikasi ke dalam container Docker untuk meningkatkan penerapan dan portabilitas. Oleh karena itu, mari kita buat container Docker sederhana untuk mendukung aplikasi kita.

Portabilitas Aplikasi

Gambar Docker biasanya mereferensikan gambar induk Docker lain sebagai titik awal yang diterima untuk persyaratan penting seperti OS dan solusi dasar, termasuk database. Mengikuti praktik terbaik Docker ini, buat file Dockerfile dan Docker Compose untuk konfigurasi layanan yang tepat sambil merujuk gambar induk yang diterbitkan Microsoft. Kami akan menggunakan tahapan Docker untuk menjaga gambar kami tetap kecil. Tahapan memungkinkan kita untuk menggunakan .NET SDK saat membangun aplikasi kita sehingga runtime ASP.NET diperlukan hanya saat aplikasi kita berjalan.

Buat Shoestore.mvc Shoesstore.mvc dengan isi sebagai berikut:

 # Shoestore\Shoestore.mvc\Dockerfile # Build stage FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /shoestore COPY Shoestore.mvc/*.csproj ./ # Restore project packages RUN dotnet restore COPY Shoestore.mvc/* ./ # Create a release build RUN dotnet build -c Release -o /app/build # Run the application and make it available on port 80 FROM mcr.microsoft.com/dotnet/aspnet:6.0 WORKDIR /app EXPOSE 80 # Assets and views COPY Shoestore.mvc/Views ./Views COPY Shoestore.mvc/wwwroot ./wwwroot COPY --from=build /app/build ./ ENTRYPOINT [ "dotnet", "Shoestore.mvc.dll" ]

Selanjutnya, kita akan membuat file docker-compose.yml di direktori root solusi kita. Awalnya, itu hanya akan berisi referensi ke .Dockerfile layanan aplikasi kami :

 # Shoestore/docker-compose.yml version: "3.9" services: web: build: context: . dockerfile: Shoestore.mvc/Dockerfile ports: - "8080:80"

Mari kita juga mengonfigurasi lingkungan kita dengan file .dockerignore untuk memastikan bahwa hanya artefak build yang disalin ke gambar kita.

Dengan layanan aplikasi kami sekarang dimatikan dan lingkungan eksekusinya siap dijalankan, kami perlu membuat layanan basis data kami dan menghubungkannya ke konfigurasi Docker kami.

Layanan Basis Data

Menambahkan Microsoft SQL Server ke konfigurasi Docker kami sangatlah mudah, terutama karena kami menggunakan image Docker yang disediakan Microsoft tanpa mengubahnya. Tambahkan blok konfigurasi berikut ke bagian bawah file docker-compose.yml untuk mengonfigurasi database:

 db: image: "mcr.microsoft.com/mssql/server" environment: SA_PASSWORD: "custom_password_123" ACCEPT_EULA: "Y" ports: - "1433:1433"

Di sini, ACCEPT_EULA mencegah penginstalan terhenti, dan pengaturan ports kami memungkinkan port SQL Server default melewati tanpa terjemahan. Dengan itu, file Compose kami mencakup layanan aplikasi dan database kami.

Sebelum menyesuaikan kode aplikasi, mari kita verifikasi bahwa lingkungan Docker kita berfungsi:

 # From the root of the solution docker compose up --build

Dengan asumsi tidak ada kesalahan yang muncul selama startup, aplikasi sampel kami yang tidak lengkap harus tersedia melalui browser web di alamat lokal http://localhost:8080 .

Alat Pembuatan Kode

Sekarang kita bisa fokus pada bagian yang menyenangkan: menyesuaikan kode aplikasi dan memastikan bahwa data aplikasi tetap ada di database Microsoft SQL Server. Kami akan menggunakan alat Entity Framework (EF) dan .NET SDK untuk menghubungkan aplikasi ke database dan membuat perancah model aplikasi, tampilan, pengontrol, dan konfigurasi yang diperlukan EF.

Sebelum kita dapat menentukan alat yang kita butuhkan, kita harus membuat file tool-manifest :

 # From the root of the solution dotnet new tool-manifest

Tambahkan alat EF dan SDK ke file ini dengan perintah sederhana ini:

 dotnet tool install dotnet-ef dotnet tool install dotnet-aspnet-codegenerator

Untuk memverifikasi pemasangan alat ini dengan benar, jalankan dotnet ef . Jika unicorn muncul, berarti mereka telah terpasang dengan benar. Selanjutnya, jalankan dotnet aspnet-codegenerator untuk menguji alat ASP.NET; outputnya harus berupa blok penggunaan CLI umum.

Sekarang kita dapat menggunakan alat-alat ini untuk membuat aplikasi kita.

MVC: Model

Tugas pertama dalam membangun aplikasi kita adalah membuat model. Karena model ini akan ditambahkan ke database nanti, kami akan menyertakan paket MS SQL Server dan EF dalam proyek kami:

 cd Shoestore.mvc/ dotnet add package Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore dotnet add package Microsoft.EntityFrameworkCore.SqlServer dotnet add package Microsoft.EntityFrameworkCore.Tools dotnet restore

Selanjutnya, buat objek konteks database EF yang menentukan model mana yang ditambahkan ke database, dan memungkinkan kode kita untuk dengan mudah mengakses dan menanyakan data tersebut dari database.

Buat direktori Data untuk menampung kode khusus EF dan buat file Data/ApplicationDBContext.cs dengan konten berikut:

 // Shoestore/Shoestore.mvc/Data/ApplicationDBContext.cs using Microsoft.EntityFrameworkCore; namespace Shoestore.mvc.Data; public class ApplicationDBContext : DbContext { public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options):base(options){} }

Selanjutnya, konfigurasikan string koneksi database, yang harus cocok dengan kredensial yang kami konfigurasikan di Dockerfile kami. Setel konten Shoestore/Shoestore.mvc/appsettings.json ke yang berikut:

 { "Logging": { "LogLevel": { "Default": "Information", "Microsoft.AspNetCore": "Warning" } }, "AllowedHosts": "*", "ConnectionStrings": { "Shoestore": "Server=db;Database=master;User=sa;Password=custom_password_123;" } }

Dengan string koneksi database yang dikonfigurasi dan kode konteks database, kami siap untuk mengkodekan fungsi Main aplikasi kami. Kami akan menyertakan penanganan pengecualian basis data untuk menyederhanakan debugging sistem. Selain itu, karena bug .NET dalam kode yang dihasilkan menyebabkan wadah Docker salah menyajikan tampilan kami, kami harus menambahkan kode khusus ke konfigurasi layanan tampilan kami. Ini akan secara eksplisit mengatur jalur file ke lokasi tampilan kami di gambar Docker kami:

 using Microsoft.EntityFrameworkCore; using Shoestore.mvc.Data; namespace Shoestore.mvc; // ... public static void Main(string[] args) { var builder = WebApplication.CreateBuilder(args); // Associate our EF database context and configure it with our connection string var connectionString = builder.Configuration.GetConnectionString("Shoestore"); builder.Services.AddDbContext<ApplicationDBContext>( options => options.UseSqlServer(connectionString)); // Middleware to catch unhandled exceptions and display a stack trace builder.Services.AddDatabaseDeveloperPageExceptionFilter(); // Add services to the container. // ASP.NET has a known issue where the final built app doesn't know where the view // files are (in the Docker container). // The fix is to specifically add view locations. builder.Services .AddControllersWithViews() .AddRazorOptions(options => { options.ViewLocationFormats.Add("/{1}/{0}.cshtml"); options.ViewLocationFormats.Add("/Shared/{0}.cshtml"); });

Lewati ke pernyataan IsDevelopment if dalam file yang sama untuk menambahkan titik akhir migrasi database ke sistem kami saat berada dalam mode pengembangan. Tambahkan pernyataan else dengan kode berikut:

 // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { // Leave the contents of the if block alone. These are hidden for clarity. } else { app.UseMigrationsEndPoint(); }

Selanjutnya, jalankan tes cepat untuk memastikan paket baru dan pengeditan kode sumber dikompilasi dengan benar:

 // Go to mvc directory cd Shoestore.mvc dotnet restore dotnet build

Sekarang, mari kita isi model dengan bidang yang diperlukan dengan membuat file Shoestore.mvc\Models\Shoe.cs :

 namespace Shoestore.mvc.Models; public class Shoe { public int ID { get; set; } public string? Name { get; set; } public int? Price { get; set; } public DateTime CreatedDate { get; set; } }

EF menghasilkan SQL berdasarkan model terkait, file konteksnya, dan kode EF apa pun di aplikasi kita. Hasil SQL kemudian diterjemahkan dan dikembalikan ke kode kita, sesuai kebutuhan. Jika kita menambahkan model Shoe kita ke konteks database kita, EF akan tahu bagaimana menerjemahkan antara MS SQL Server dan aplikasi kita. Mari kita lakukan ini di file konteks database, Shoestore/Shoestore.mvc/Data/ApplicationDBContext.cs :

 using Microsoft.EntityFrameworkCore; using Shoestore.mvc.Models; namespace Shoestore.mvc.Data; public class ApplicationDBContext : DbContext { public ApplicationDBContext(DbContextOptions<ApplicationDBContext> options) : base(options) { } private DbSet<Shoe>? _shoe { get; set; } public DbSet<Shoe> Shoe { set => _shoe = value; get => _shoe ?? throw new InvalidOperationException("Uninitialized property" + nameof(Shoe)); } }

Terakhir, kita akan menggunakan file migrasi database untuk memasukkan model kita ke dalam database. Alat EF membuat file migrasi khusus untuk MS SQL Server berdasarkan konteks database dan model terkaitnya (yaitu, Shoe ):

 cd Shoestore.mvc/ dotnet ef migrations add InitialCreate

Mari kita tunda menjalankan migrasi sampai kita memiliki pengontrol dan tampilan di tempatnya.

MVC: Pengontrol dan Tampilan

Kami akan membuat pengontrol kami menggunakan alat pembuatan kode ASP.NET. Alat ini sangat kuat tetapi membutuhkan kelas pembantu khusus. Gunakan paket gaya Design untuk struktur pengontrol dasar dan integrasi EF-nya. Mari kita tambahkan paket-paket ini:

 cd Shoestore.mvc\ dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design && \ dotnet add package Microsoft.EntityFrameworkCore.Design && \ dotnet restore

Sekarang, membuat pengontrol default kami semudah menjalankan perintah berikut:

 cd Shoestore.mvc\ dotnet dotnet-aspnet-codegenerator controller \ -name ShoesController \ -m Shoe \ -dc ApplicationDBContext \ --relativeFolderPath Controllers \ --useDefaultLayout \ --referenceScriptLibraries

Ketika pembuat kode membuat pengontrol kami, itu juga membuat tampilan sederhana untuk pengontrol itu. Dengan fondasi MVC kami yang lengkap, kami siap menjalankan semuanya.

Tes Migrasi dan Aplikasi

Migrasi EF biasanya merupakan urusan yang sederhana, tetapi ketika Docker terlibat, prosesnya menjadi lebih kompleks. Dalam artikel berikutnya dalam seri kami, kami akan menjelajahi jalur yang sangat berliku untuk membuat migrasi tersebut berfungsi dalam solusi Docker kami, tetapi untuk saat ini, kami hanya ingin migrasi kami berjalan.

Semua file konfigurasi dan migrasi disertakan dalam repositori kami. Mari kita mengkloning proyek lengkap ke mesin lokal kita dan melakukan migrasi:

 git clone https://github.com/theZetrax/dot-net-on-linux.git cd ./dot-net-on-linux docker composer up

Operasi docker composer membangun aplikasi kita, menjalankan migrasi, dan meluncurkan aplikasi ASP.NET kita dengan runtime .NET. Untuk mengakses solusi yang sedang berjalan, kunjungi http://localhost:8080/Shoes .

Meskipun antarmuka aplikasi kami sederhana, ini menunjukkan fungsionalitas melalui semua tingkatan, dari tampilan hingga database.

.NET di Linux Hanya Berfungsi

Lihat repositori lengkap untuk ikhtisar solusi kami. Artikel berikutnya akan membahas migrasi kami secara mendetail, serta tips dan trik untuk membuat gambar Docker kami ramping.

.NET di Linux lebih dari sekadar mimpi pipa: Ini adalah kombinasi bahasa, runtime, dan OS yang layak. Banyak pengembang yang dibesarkan di Visual Studio mungkin tidak memiliki pengalaman menggunakan .NET CLI sepenuhnya, tetapi alat ini efektif dan kuat.

Bacaan Lebih Lanjut di Blog Teknik Toptal:

  • Membangun ASP.NET Web API Dengan ASP.NET Core
  • 8 Alasan Mengapa Microsoft Stack Masih Menjadi Pilihan yang Layak
  • Cara Meningkatkan Kinerja Aplikasi ASP.NET di Web Farm Dengan Caching
  • Tutorial Elasticsearch untuk .NET Developers
  • Apa itu Kubernetes? Panduan untuk Kontainerisasi dan Penerapan

Blog Toptal Engineering mengucapkan terima kasih kepada Henok Tsegaye karena telah meninjau contoh kode yang disajikan dalam artikel ini.