ASP.NET Web API + Entity Framework + Microsoft SQL Server + Angular. Bagian 1





pengantar



Kursus singkat tentang cara membuat aplikasi web sederhana menggunakan teknologi ASP.NET Core, Entity Framework, DBMS Microsoft SQL Server, dan kerangka kerja Angular. Kami akan menguji API Web melalui aplikasi Postman .



Kursus ini terdiri dari beberapa bagian:



  1. Bangun API Web dengan ASP.NET Web API dan Entity Framework Core.
  2. Implementasi antarmuka pengguna di Angular.
  3. Menambahkan otentikasi ke aplikasi.
  4. Perluas model aplikasi dan jelajahi fitur tambahan dari Entity Framework.


Bagian 1. Membangun Web API dengan ASP.NET Web API dan Entity Framework Core



Sebagai contoh, kami akan mempertimbangkan aplikasi klasik dari daftar tugas. Untuk mengembangkan aplikasinya, saya akan menggunakan Visual Studio 2019 (prosesnya mirip di Visual Studio 2017).



Pembuatan proyek



Buat proyek ASP.NET Core Web Application baru di Visual Studio:







Beri nama aplikasi dan tentukan jalur ke direktori dengan proyek tersebut:







Dan pilih template aplikasi API:







Model



Mari buat katalog Model dan tambahkan kelas TodoItem.cs pertama ke katalog baru, yang objeknya akan menjelaskan beberapa tugas daftar tugas dalam aplikasi:



public class TodoItem
{
    public int Id { get; set; }
    public string TaskDescription { get; set; }
    public bool IsComplete { get; set; }
}


Kami akan menggunakan Sql Server sebagai DBMS, dan database akan diakses melalui Entity Framework Core, dan pertama-tama kami akan menginstal framework melalui pengelola paket NuGet bawaan:







Salah satu pendekatan untuk bekerja dengan Kerangka Kerja Entitas adalah pendekatan "Kode-Pertama". Inti dari pendekatan ini adalah bahwa berdasarkan model aplikasi (dalam kasus kami, model tersebut mewakili satu kelas - TodoItem.cs), struktur database (tabel, kunci utama, tautan) dibentuk, semua pekerjaan ini terjadi "di belakang layar" dan langsung dengan Kami tidak bekerja dengan SQL. Prasyarat untuk kelas model adalah adanya bidang kunci utama, secara default Kerangka Kerja Entitas mencari bidang bilangan bulat yang namanya terdapat substring "id" dan membentuk kunci utama berdasarkan itu. Anda dapat mengganti perilaku ini menggunakan atribut khusus atau menggunakan kapabilitas Fluent API.



Komponen utama dalam bekerja dengan Entity Framework adalah kelas konteks database, tempat data dalam tabel sebenarnya diakses:



public class EFTodoDBContext : DbContext
{
    public EFTodoDBContext(DbContextOptions<EFTodoDBContext> options) : base(options) 
    { }
    public DbSet<TodoItem> TodoItems{ get; set; }
}


Kelas dasar DbContext membuat konteks database dan menyediakan akses ke fungsionalitas Kerangka Entitas.



Kami akan menggunakan SQL Server 2017 Express untuk menyimpan data aplikasi . String koneksi disimpan dalam file JSON yang disebut appsettings.json:



{
  "ConnectionStrings": {
    "DefaultConnection": "Server=.\\SQLEXPRESS;Database=Todo;Trusted_Connection=true"
  }
}


Selanjutnya, Anda perlu mengubah kelas Startup.cs dengan menambahkan kode berikut ke metode ConfigureServices ():



services.AddDbContext<EFTodoDBContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));


Metode AddDbContext () mengonfigurasi layanan yang disediakan oleh Entity Framework Core untuk kelas konteks database EFTodoDBContext. Argumen ke metode AddDbContext () adalah ekspresi lambda yang menerima objek opsi yang mengonfigurasi database untuk kelas konteks. Dalam kasus ini, database dikonfigurasi menggunakan metode UseSqlServer () dan menentukan string koneksi.



Mari tentukan operasi dasar untuk bekerja dengan tugas-tugas di antarmuka ITodoRepository:



 public interface ITodoRepository
 {
    IEnumerable<TodoItem> Get();
    TodoItem Get(int id);
    void Create(TodoItem item);
    void Update(TodoItem item);
    TodoItem Delete(int id);
 }


Antarmuka ini memungkinkan kita untuk tidak memikirkan implementasi spesifik dari gudang data, mungkin kita belum benar-benar memutuskan pilihan kerangka kerja DBMS atau ORM, sekarang tidak masalah, kelas yang menjelaskan akses data akan mewarisi dari antarmuka ini.

Mari implementasikan repositori, yang, seperti disebutkan sebelumnya, akan mewarisi dari ITodoRepository dan menggunakan EFTodoDBContext sebagai sumber data:



public class EFTodoRepository : ITodoRepository
{
    private EFTodoDBContext Context;
    public IEnumerable<TodoItem> Get()
    {
        return Context.TodoItems;
    }
    public TodoItem Get(int Id)
    {
        return Context.TodoItems.Find(Id);
    }
    public EFTodoRepository(EFTodoDBContext context)
    {
        Context = context;
    }
    public void Create(TodoItem item)
    {
        Context.TodoItems.Add(item);
        Context.SaveChanges();
    }
    public void Update(TodoItem updatedTodoItem)
    {
        TodoItem currentItem = Get(updatedTodoItem.Id);
        currentItem.IsComplete = updatedTodoItem.IsComplete;
        currentItem.TaskDescription = updatedTodoItem.TaskDescription;

        Context.TodoItems.Update(currentItem);
        Context.SaveChanges();
        }

    public TodoItem Delete(int Id)
    {
        TodoItem todoItem = Get(Id);

        if (todoItem != null)
        {
            Context.TodoItems.Remove(todoItem);
            Context.SaveChanges();
        }

        return todoItem;
    }    
}


Kontroler



Pengontrol, yang implementasinya akan dijelaskan di bawah ini, tidak akan tahu apa-apa tentang konteks data EFTodoDBContext, tetapi hanya akan menggunakan antarmuka ITodoRepository dalam pekerjaannya, yang memungkinkan pengubahan sumber data tanpa mengubah pengontrol. Pendekatan Adam Freeman dalam bukunya "Entity Framework Core 2 for ASP.NET Core MVC for professional" disebut pola "Storage".



Pengontrol mengimplementasikan penangan untuk metode permintaan HTTP standar: GET, POST, PUT, DELETE, yang akan mengubah status tugas kami yang dijelaskan di kelas TodoItem.cs.



Tambahkan kelas TodoController.cs ke direktori Controllers dengan konten berikut:



[Route("api/[controller]")]
public class TodoController : Controller
{
    ITodoRepository TodoRepository;

    public TodoController(ITodoRepository todoRepository)
    {
        TodoRepository = todoRepository;
    }

    [HttpGet(Name = "GetAllItems")]
    public IEnumerable<TodoItem> Get()
    {
        return TodoRepository.Get();
    }

    [HttpGet("{id}", Name = "GetTodoItem")]
    public IActionResult Get(int Id)
    {
        TodoItem todoItem = TodoRepository.Get(Id);

        if (todoItem == null)
        {
            return NotFound();
        }

        return new ObjectResult(todoItem);
    }

    [HttpPost]
    public IActionResult Create([FromBody] TodoItem todoItem)
     {
        if (todoItem == null)
        {
            return BadRequest();
        }
        TodoRepository.Create(todoItem);
        return CreatedAtRoute("GetTodoItem", new { id = todoItem.Id }, todoItem);
    }

    [HttpPut("{id}")]
    public IActionResult Update(int Id, [FromBody] TodoItem updatedTodoItem)
    {
        if (updatedTodoItem == null || updatedTodoItem.Id != Id)
        {
            return BadRequest();
        }

        var todoItem = TodoRepository.Get(Id);
        if (todoItem == null)
        {
            return NotFound();
        }

        TodoRepository.Update(updatedTodoItem);
        return RedirectToRoute("GetAllItems");
    }

    [HttpDelete("{id}")]
    public IActionResult Delete(int Id)
    {
        var deletedTodoItem = TodoRepository.Delete(Id);

        if (deletedTodoItem == null)
        {
            return BadRequest();
        }

        return new ObjectResult(deletedTodoItem);
    }
 }


Sebelum definisi kelas, atribut yang menjelaskan template rute untuk mengakses pengontrol ditentukan: [Route ("api / [controller]")]. TodoController akan dapat diakses melalui rute berikut: https: // <host ip>: <port> / api / todo. [Controller] menentukan nama kelas controller dalam huruf kecil, menghilangkan bagian "Controller".



Sebelum setiap metode didefinisikan dalam TodoController, atribut khusus dari formulir ditentukan: [<metode HTTP> ("parameter", Name = "alias metode")]. Atribut menentukan permintaan HTTP mana yang akan diproses dengan metode ini, parameter yang diteruskan dalam URI permintaan dan alias metode yang dapat digunakan untuk mengirim ulang permintaan. Jika Anda tidak menentukan atributnya, maka secara default kerangka kerja MVC akan mencoba menemukan metode yang paling sesuai di pengontrol untuk memproses permintaan berdasarkan nama metode dan parameter yang ditentukan dalam permintaan, jadi jika Anda tidak menentukan atribut untuk metode Get () di pengontrol TodoController, lalu dalam permintaan HTTP menggunakan metode GET: https: // <host ip>: <port> / api / todo, infrastruktur akan menentukan metode Get () dari pengontrol untuk memproses permintaan.



Dalam konstruktornya, pengontrol menerima referensi ke objek berjenis ITodoRepository, tetapi sejauh ini infrastruktur MVC tidak mengetahui objek mana yang akan diganti saat membuat pengontrol. Kita perlu membuat layanan yang secara unik menyelesaikan ketergantungan ini, untuk ini kita akan membuat beberapa perubahan pada kelas Startup.cs dengan menambahkan kode berikut ke metode ConfigureServices ():



services.AddTransient<ITodoRepository, EFTodoRepository>();


Metode AddTransient <ITodoRepository, EFTodoRepository> () mendefinisikan layanan yang membuat instance baru dari kelas EFTodoRepository setiap kali instance tipe ITodoRepository diperlukan, misalnya dalam sebuah controller.



Kode lengkap untuk kelas Startup.cs:



public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllers();
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_3_0);
        services.AddDbContext<EFTodoDBContext>(options => options.UseSqlServer(Configuration["ConnectionStrings:DefaultConnection"]));
        services.AddTransient<ITodoRepository, EFTodoRepository>();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseHttpsRedirection();
        app.UseRouting();
        app.UseAuthorization();
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }
 }


Migrasi



Agar Entity Framework menghasilkan database dan tabel dari model, Anda harus menggunakan proses migrasi database. Migrasi adalah sekumpulan perintah yang mempersiapkan database untuk bekerja dengan Entity Framework. Mereka digunakan untuk membuat dan menyinkronkan database. Perintah dapat dijalankan di Package Manager Console dan di Power Shell (Developer Power Shell). Kita akan menggunakan Package Manager Console, untuk bekerja dengan Entity Framework kita perlu menginstal paket Microsoft.EntityFrameworkCore.Tools:







Luncurkan Package Manager Console dan jalankan perintah Add-Migration Initial :











Direktori baru akan muncul dalam proyek - Migrasi, di mana kelas migrasi akan disimpan, berdasarkan objek mana dalam database yang akan dibuat setelah perintah Update-Database dijalankan:







Web API sudah siap, dengan menjalankan aplikasi di IIS Express lokal, kita dapat menguji operasi pengontrol.



Menguji WebAPI



Mari kita buat kumpulan permintaan baru di Postman yang disebut TodoWebAPI:







Karena database kita kosong, mari kita uji pembuatan tugas baru terlebih dahulu. Di pengontrol, metode Create () bertanggung jawab untuk membuat tugas, yang akan memproses permintaan HTTP yang dikirim oleh metode POST dan akan berisi objek TodoItem berseri dalam format JSON di badan permintaan. Atribut [FromBody] sebelum parameter todoItem dalam metode Create () memberi tahu kerangka kerja MVC untuk mendeserialisasi objek TodoItem dari badan permintaan dan meneruskannya sebagai parameter ke metode. Mari buat permintaan di Postman yang akan mengirim permintaan ke webAPI untuk membuat tugas baru:







Metode Create () setelah berhasil membuat tugas mengalihkan permintaan ke metode Get () dengan alias "GetTodoItem" dan meneruskan Id dari tugas yang baru dibuat sebagai parameter, sebagai hasilnya kami akan menerima objek tugas yang dibuat dalam format JSON sebagai tanggapan atas permintaan tersebut.



Dengan mengirim permintaan HTTP menggunakan metode PUT dan menentukan objek yang sudah dibuat di URI Id (https: // localhost: 44370 / api / todo / 1), dan dalam tubuh permintaan meneruskan objek dengan beberapa perubahan dalam format JSON, kami akan mengubah objek ini di database :







Dengan permintaan HTTP dengan metode GET tanpa menentukan parameter, kami akan menerima semua objek dalam database:







Permintaan HTTP dengan metode DELETE dan menentukan Id objek di URI (https: // localhost: 44370 / api / todo / 2), akan menghapus objek dari database dan mengembalikan JSON dengan tugas jarak jauh:







Itu saja, pada bagian selanjutnya kita akan mengimplementasikan antarmuka pengguna menggunakan kerangka JavaScript Angular.



All Articles