C# 및 AspNet 사용하여 REST API 구축하는 데 도움이됩니다. 
CRUD 있는 REST API Controller 에는 20 줄 의 코드가 포함되어 있습니다 (~ 10은 가져 오기)GET 방법은 내장 페이징 지원이 있습니다.GET 매개 변수별로 정렬 및 필터가 내장되어 있습니다.Create , Update 및 Delete )로 벌크 작업을 지원합니다.IModelManager 인터페이스)와 함께 작동하도록 지원합니다. 우수한 내장 EntityFramework 지원 ( EfModelManager 클래스 참조). 2 개의 웹 API 프로젝트가있는 WeatherControl 앱을 참조하십시오.Wissance.WeatherControl.WebApi EntityFramework 사용합니다.Wissance.WeatherControl.WebApi.V2 EdgeDb 사용합니다.주요 개념 :
Controller 는 REST Resource 위해 HTTP-requests 처리하는 클래스입니다.REST Resource Entity class / Database Table 과 동일합니다.REST Resource 의 모든 작업은 출력으로 DTO 사용하여 JSON 생성합니다. 우리는 모든 REST 방법과 함께 하나의 DTO 클래스 만 사용한다고 가정합니다. DTO 클래스 :
OperationResultDto DB의 데이터를 변경하는 작동 결과를 나타냅니다.PagedDataDto 동일한 객체 (모든 유형)의 부분 (페이지)을 나타냅니다. Controllers 클래스 - 초록 클래스
BasicReadController )에는 두 가지 방법이 포함되어 있습니다.GET /api/[controller]/?[page={page}&size={size}&sort={sort}&order={order}] 이제 PagedDataDto<T> EfModelManager 려면 이제 쿼리 매개 변수를 수많은 쿼리 매개 변수 를 보낼 가능성이 있습니다. 또한 정렬 (열 이름) && order ( asc 또는 desc )를 관리자 클래스로 전달합니다. EfModelManager 모든 열별로 정렬 할 수 있습니다. Swagger 정보를 무시해야합니다 !!!1.6.0 부터 Swagger 의 모든 매개 변수를보고 사용할 수 있습니다.id 로 하나의 개체를 얻으려면 GET /api/[controller]/{id}CRUD Controller ( BasicCrudController ) = BASIC READ CONTROLER ( BasicReadController ) + 작업 Create , Update 및 Delete :POST /api/[controller] - 새로운 객체 생성을 위해PUT /api/[controller]/{id} - id로 객체를 편집하려면DELETE /api/[controller]/{id} - id 씩 삭제하려면 삭제합니다BasicBulkCrudController = BASIC READ CONTROLER ( BasicReadController ) + BulkCreate , BulkUpdate 및 BulkDelete 작업으로 전체 CRUD :POST /api/bulk/[controller] - 새로운 개체 생성의 경우PUT /api/bulk/[controller] - 요청 본문을 전달하는 개체 편집DELETE /api/bulk/[controller]/{idList} - id 씩 여러 객체를 삭제하려면.컨트롤러 클래스는 모든 작업이 관리자 클래스를 사용하여 수행 될 것으로 예상합니다 (각 컨트롤러는 자체 관리자가 있어야합니다).
관리자 클래스 - 응용 프로그램의 비즈니스 논리를 구현하는 클래스
IModelManager 기본 작업을 설명하는 인터페이스EfModelManager Get and Delete 작업 구현이 포함 된 초록 클래스입니다.EfSoftRemovableModelManager 소프트 탈착식 모델로 Get and Delete 작업의 구현을 포함하는 초록 클래스입니다 ( IsDeleted = true MEMENT 모델이 제거) 벌크가 아닌 대량 비율의 예 : 
Elapsed time in Non-Bulk REST API with EF is 0.9759984016418457 secs.
Elapsed time in Bulk API with EF is 0.004002094268798828 secs.
결과적으로 우리는 거의 ~ 250 x 더 빠른 API 얻었습니다.
요구 사항은 하나뿐입니다 . 컨트롤러 및 관리자와 함께 사용하는 모든 지속성 저장소에 대한 모든 엔티티 클래스는 Wissance.WebApiToolkit.Data.Entity 에서 IModelIdentifiable<T> 구현해야합니다. 이 툴킷이 EntityFramework 와 함께 사용해야하는 경우 EfModelManager 의 리소스 관리자를 도출해야합니다.
get manyby id get oneby id 항목을 delete 전체 예는 섹션 6에 언급되어 있습니다 (아래 참조). 그러나 새로운 REST Resource API 구축하기 시작하면 다음을 수행해야합니다.
IModelIdentifiable<T> 및 DTO 클래스 구현 model ( entity ) 클래스를 만듭니다 ( 소프트 제거의 경우 IModelSoftRemovable 구현을 추가 ), 즉 : 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 DTO IE로 변환하는 공장 기능 (예 : 정적 클래스의 정적 기능)을 만듭니다. public static class BookFactory
{
public static BookDto Create ( BookEntity entity )
{
return new BookDto
{
Id = entity . Id ,
Title = entity . Title ,
Authors = entity . Authors ;
} ;
}
}DbSet ( EF Abstract Class )에서 파생 된 구현 클래스 인 It BookEntity DbContext 있는 IModelContext 인터페이스를 작성하십시오. 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 ; }
}DI 를 통해 DbContext 로 ModelContext 인젝션으로 구성하도록 구성하십시오.Controller 클래스 및 관리자 클래스 쌍 생성, 즉 여기에서 전체 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 ;
} 위의 예제의 마지막 일반 매개 변수 - EmptyAdditionalFilters Swagger에서 볼 수있는 추가 매개 변수를 보유하는 클래스입니다. IReadFilterable 구현하는 새로운 클래스를 지정하십시오.
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 ; }
}Nuget-Package를 여기에서 찾을 수 있습니다
[ 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 ;
}webapitoolkit을 사용하는 매우 간단한 수업 ^^
컨트롤러에 메소드 검색을 추가하고 싶다고 생각합니다.
[ 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 ) ;
} Keycloak OpenId-Connect 로 API 보호하기위한 추가 프로젝트가 있습니다. IHttpContextAccessor Manager 클래스로 통과하고 다음과 같은 내용을 확인하십시오. ClaimsPrincipal principal = _httpContext.HttpContext.User;
툴킷 사용에 관한 기사를 볼 수 있습니다.