REST API dengan C# dan AspNet dengan mudah daripada menulisnya dari awal dan berulang -ulang dalam proyek yang berbeda. 
REST API Controller dengan CRUD penuh hanya berisi 20 baris kode (~ 10 adalah impor)GET metode memiliki dukungan paging bawaan ;GET Method memiliki penyortiran dan filter dengan parameter kueri;Create , Update dan Delete ) pada level antarmuka controller &&IModelManager ); Dukungan EntityFramework yang baik (lihat Kelas EfModelManager ). Lihat aplikasi WeatherControl yang memiliki 2 proyek API Web:Wissance.WeatherControl.WebApi menggunakan EntityFramework ;Wissance.WeatherControl.WebApi.V2 menggunakan EdgeDb .Konsep kunci:
Controller adalah kelas yang menangani HTTP-requests untuk REST Resource .REST Resource sama dengan Entity class / Database TableREST Resource menghasilkan JSON dengan DTO sebagai output. Kami berasumsi hanya menggunakan satu kelas DTO dengan semua metode REST . Kelas DTO :
OperationResultDto mewakili hasil operasi yang mengubah data dalam DB;PagedDataDto mewakili bagian (halaman) dari objek yang sama (jenis apa pun); Kelas Controllers - Kelas Abstrak
BasicReadController ) berisi 2 metode:GET /api/[controller]/?[page={page}&size={size}&sort={sort}&order={order}] Untuk mendapatkan PagedDataDto<T> Sekarang kami juga memiliki kemungkinan untuk mengirim sejumlah param , Anda hanya perlu menyalakan EfModelManager . Kami juga meneruskan sortir (nama kolom) && order ( asc atau desc ) ke kelas manajer, EfModelManager memungkinkan untuk mengurutkan berdasarkan kolom apa pun . Swagger untuk menampilkan penggunaan parameter kueri !!!1.6.0 dimungkinkan untuk melihat semua parameter dalam Swagger dan menggunakannya.GET /api/[controller]/{id} untuk mendapatkan satu objek dengan idCRUD Lengkap ( BasicCrudController ) = Pengontrol Baca Dasar ( BasicReadController ) + Create , Update , dan Delete operasi:POST /api/[controller] - Untuk pembuatan objek baruPUT /api/[controller]/{id} - Untuk mengedit objek dengan idDELETE /api/[controller]/{id} - Untuk Hapus Objek oleh IDCRUD penuh dengan operasi curah (operasi atas beberapa objek sekaligus), kelas dasar - BasicBulkCrudController = Pengontrol Bacaan Dasar ( BasicReadController ) + BulkCreate , BulkUpdate dan Operasi BulkDelete :POST /api/bulk/[controller] - Untuk pembuatan objek baruPUT /api/bulk/[controller] - Untuk mengedit objek yang lewat di badan permintaanDELETE /api/bulk/[controller]/{idList} - Untuk menghapus banyak objek dengan ID.Kelas pengontrol mengharapkan semua operasi akan dilakukan menggunakan kelas manajer (setiap pengontrol harus memiliki manajer sendiri)
Kelas Manajer - Kelas yang mengimplementasikan logika bisnis aplikasi
IModelManager - Antarmuka yang menjelaskan operasi dasarEfModelManager - adalah kelas abstrak yang berisi implementasi operasi Get and DeleteEfSoftRemovableModelManager adalah kelas abstrak yang berisi implementasi operasi Get and Delete dengan model yang dapat dilepas lunak ( IsDeleted = true telah dihapus) Contoh seberapa cepat curah vs non-bulk: 
Elapsed time in Non-Bulk REST API with EF is 0.9759984016418457 secs.
Elapsed time in Bulk API with EF is 0.004002094268798828 secs.
Akibatnya kami mendapat hampir ~ 250 x API lebih cepat.
Hanya ada satu persyaratan : semua kelas entitas untuk penyimpanan kegigihan yang digunakan dengan pengontrol & manajer harus mengimplementasikan IModelIdentifiable<T> dari Wissance.WebApiToolkit.Data.Entity . Jika toolkit ini harus digunakan dengan EntityFramework , Anda harus memperoleh Anda Manajer Sumber Daya dari EfModelManager , itu memiliki metode bawaan untuk:
get many itemget one item by iddelete item by id Contoh lengkap disebutkan dalam Bagian 6 (lihat di bawah). Tetapi jika Anda mulai membangun API REST Resource baru, Anda harus mengikuti:
model ( entity ) yang mengimplementasikan IModelIdentifiable<T> dan kelas DTO untuk representasi TI ( untuk soft remeD juga menambahkan IModelSoftRemovable Implementasi), yaitu: public class BookEntity : IModelIdentifiable < int >
{
public int Id { get ; set ; }
public string Title { get ; set ; }
public string Authors { get ; set ; } // for simplicity
public DateTimeOffset Created { get ; set ; }
public DateTimeOffset Updated { get ; set ; }
}
public class BookDto
{
public int Id { get ; set ; }
public string Title { get ; set ; }
public string Authors { get ; set ; }
}Model menjadi DTO yaitu: public static class BookFactory
{
public static BookDto Create ( BookEntity entity )
{
return new BookDto
{
Id = entity . Id ,
Title = entity . Title ,
Authors = entity . Authors ;
} ;
}
}IModelContext yang membuat Anda BookEntity sebagai kelas implementasi DbSet dan itu yang juga berasal dari DbContext ( EF Abstract Class ): public interface IModelContext
{
DbSet < BookEntity > Books { get ; set ; }
}
public MoidelContext : DbContext < ModelContext > , IModelContext
{
// todo: not mrntioned here constructor, entity mapping and so on
public DbSet < BookEntity > Books { get ; set ; }
}ModelContext sebagai DbContext via DI Lihat Kelas StartupController dan pasangan kelas manajer, yaitu pertimbangkan di sini penuh CRUD [ ApiController ]
public class BookController : BasicCrudController < BookDto , BookEntity , int , EmptyAdditionalFilters >
{
public BookController ( BookManager manager )
{
Manager = manager ; // this is for basic operations
_manager = manager ; // this for extended operations
}
private BookManager _manager ;
}
public class BookManager : EfModelManager < BookEntity , BookDto , int , EmptyAdditionalFilters >
{
public BookManager ( ModelContext modelContext , ILoggerFactory loggerFactory ) : base ( modelContext , BookFactory . Create , loggerFactory )
{
_modelContext = modelContext ;
}
public override async Task < OperationResultDto < StationDto > > CreateAsync ( StationDto data )
{
// todo: implement
}
public override async Task < OperationResultDto < StationDto > > UpdateAsync ( int id , StationDto data )
{
// todo: implement
}
private readonly ModelContext _modelContext ;
} Parameter generik terakhir dalam contoh di atas - EmptyAdditionalFilters adalah kelas yang memegang parameter tambahan untuk dicari untuk dilihat di Swagger, cukup tentukan kelas baru yang mengimplementasikan Ie IReadFilterable IE:
public class BooksFilterable : IReadFilterable
{
public IDictionary < string , string > SelectFilters ( )
{
IDictionary < string , string > additionalFilters = new Dictionary < string , string > ( ) ;
if ( ! string . IsNullOrEmpty ( Title ) )
{
additionalFilters . Add ( FilterParamsNames . TitleParameter , Title ) ;
}
if ( Authors != null && Authors . Length > 0 )
{
additionalFilters . Add ( FilterParamsNames . AuthorsParameter , string . Join ( "," , Authors ) ) ;
}
return additionalFilters ;
}
[ FromQuery ( Name = "title" ) ] public string Title { get ; set ; }
[ FromQuery ( Name = "author" ) ] public string [ ] Authors { get ; set ; }
}Anda dapat menemukan paket nuget di sini
[ ApiController ]
public class StationController : BasicCrudController < StationDto , StationEntity , int , EmptyAdditionalFilters >
{
public StationController ( StationManager manager )
{
Manager = manager ; // this is for basic operations
_manager = manager ; // this for extended operations
}
private StationManager _manager ;
} public class StationManager : EfModelManager < StationEntity , StationDto , int >
{
public StationManager ( ModelContext modelContext , ILoggerFactory loggerFactory ) : base ( modelContext , StationFactory . Create , loggerFactory )
{
_modelContext = modelContext ;
}
public override async Task < OperationResultDto < StationDto > > CreateAsync ( StationDto data )
{
try
{
StationEntity entity = StationFactory . Create ( data ) ;
await _modelContext . Stations . AddAsync ( entity ) ;
int result = await _modelContext . SaveChangesAsync ( ) ;
if ( result >= 0 )
{
return new OperationResultDto < StationDto > ( true , ( int ) HttpStatusCode . Created , null , StationFactory . Create ( entity ) ) ;
}
return new OperationResultDto < StationDto > ( false , ( int ) HttpStatusCode . InternalServerError , "An unknown error occurred during station creation" , null ) ;
}
catch ( Exception e )
{
return new OperationResultDto < StationDto > ( false , ( int ) HttpStatusCode . InternalServerError , $ "An error occurred during station creation: { e . Message } " , null ) ;
}
}
public override async Task < OperationResultDto < StationDto > > UpdateAsync ( int id , StationDto data )
{
try
{
StationEntity entity = StationFactory . Create ( data ) ;
StationEntity existingEntity = await _modelContext . Stations . FirstOrDefaultAsync ( s => s . Id == id ) ;
if ( existingEntity == null )
{
return new OperationResultDto < StationDto > ( false , ( int ) HttpStatusCode . NotFound , $ "Station with id: { id } does not exists" , null ) ;
}
// Copy only name, description and positions, create measurements if necessary from MeasurementsManager
existingEntity . Name = entity . Name ;
existingEntity . Description = existingEntity . Description ;
existingEntity . Latitude = existingEntity . Latitude ;
existingEntity . Longitude = existingEntity . Longitude ;
int result = await _modelContext . SaveChangesAsync ( ) ;
if ( result >= 0 )
{
return new OperationResultDto < StationDto > ( true , ( int ) HttpStatusCode . OK , null , StationFactory . Create ( entity ) ) ;
}
return new OperationResultDto < StationDto > ( false , ( int ) HttpStatusCode . InternalServerError , "An unknown error occurred during station update" , null ) ;
}
catch ( Exception e )
{
return new OperationResultDto < StationDto > ( false , ( int ) HttpStatusCode . InternalServerError , $ "An error occurred during station update: { e . Message } " , null ) ;
}
}
private readonly ModelContext _modelContext ;
}Hanya 2 kelas yang sangat sederhana ^^ menggunakan webapitoolkit
Pertimbangkan kami ingin menambahkan metode pencarian ke pengontrol kami:
[ HttpGet ]
[ Route ( "api/[controller]/search" ) ]
public async Task < PagedDataDto < BookDto > > > SearchAsync ( [ FromQuery ] string query , [ FromQuery ] int page , [ FromQuery ] int size )
{
OperationResultDto < Tuple < IList < BookDto > , long > > result = await Manager . GetAsync ( page , size , query ) ;
if ( result == null )
{
HttpContext . Response . StatusCode = ( int ) HttpStatusCode . InternalServerError ;
}
HttpContext . Response . StatusCode = result . Status ;
return new PagedDataDto < TRes > ( pageNumber , result . Data . Item2 , GetTotalPages ( result . Data . Item2 , pageSize ) , result . Data . Item1 ) ;
} Kami memiliki proyek tambahan untuk melindungi API dengan Keycloak OpenId-Connect . lulus IHttpContextAccessor ke kelas Manager dan periksa sesuatu seperti ini: ClaimsPrincipal principal = _httpContext.HttpContext.User;
Anda dapat melihat artikel kami tentang penggunaan toolkit: