이 게시물은 Tutorial: Create a web API with ASP.NET Core | Microsoft Docs 의 튜토리얼을 공부하며 작성한 발췌 번역입니다.
스캐폴딩에 필요한 NuGet 패키지 추가
스캐폴딩 엔진 설치
scaffold
Controller/TodoItemsController.cs
수정
[HttpPost]
public async Task<ActionResult<TodoItem>> PostTodoItem(TodoItem todoItem)
{
_context.TodoItems.Add(todoItem);
await _context.SaveChangesAsync();
//return CreatedAtAction("GetTodoItem", new { id = todoItem.Id }, todoItem);
return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, todoItem);
}
[HttpPost] 애트리뷰트가 붙은 HTTP POST 메소드
HTTP 리퀘스트의 body에서 to-do item의 값을 가져옴.
CreatedAtAction
메소드
성공했을 경우 HTTP 201 status code
응답에 Location
헤더를 붙임. 그 헤더는 새롭게 만들어진 to-do item의 URI를 지정함.
하드코딩을 피하기 위해 "GetTodoItem"
에서 nameof
키워드를 사용하는 것으로 바꿈.
웹 API를 테스트하기 위해 툴을 설치한다.
dotnet tool install -g Microsoft.dotnet-httprepl
테스트
방금 post에서 입력한 정보가 1이 되어서 get으로 가져와진다.
GET 엔드포인트는 2가지가 구현되어있다.
GET /api/todoitems
GET /api/todoitems/{id}
두번째꺼는 앞서 시험해봄. 첫번째껄 해보자
전체 json 목록이 출력된다.
이 앱은 현재 메모리를 데이터베이스로 삼고 있음. 앱이 중단되고 다시 시작되면 앞서 POST로 저장해둔 데이터가 사라진다.
Controller/TodoItemsController.cs
수정
[Route("api/[controller]")]
[ApiController]
public class TodoItemsController : ControllerBase
[controller]
부분은 관례상 컨트롤러 클래스의 이름으로 지정한다. 이대 컨트롤러라는 문자열은 뺀다. 이 앱의 경우 이름은 "TodoItems"가 된다.
If the [Http![G]()et]
attribute has a route template (for example, [HttpGet("products")]
), append that to the path. This sample doesn't use a template.
GetTodoItems
and GetTodoItem
메소드의 리턴값 자료형은 ActionResult<T>
형이다.
ASP.NET Core는 자동으로 개체를 JSON으로 직렬화(시리얼라이즈)하고, JSON을 응답하는 메시지 body에 쓴다.
이 반환 자료형에 대한 응답 코드는 200 OK. 처리되지않은 오류의 경우 5xx 코드가 된다.
ActionResult
반환 유형은 광범위한 HTTP 상태 코드를 나타낼 수 있습니다. 예를 들어, GetTodoItem
두 가지 다른 상태 값을 반환할 수 있습니다.
item
HTTP 200 응답 으로 결과를 반환 합니다.HTTP put 메소드를 살펴보자.
[HttpPut("{id}")]
public async Task<IActionResult> PutTodoItem(long id, TodoItem todoItem)
{
if (id != todoItem.Id)
{
return BadRequest();
}
_context.Entry(todoItem).State = EntityState.Modified;
try
{
await _context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException)
{
if (!TodoItemExists(id))
{
return NotFound();
}
else
{
throw;
}
}
return NoContent();
}
앞서 본 POST와 유사하다. 정상 작동 시 응답은 204 (No Content)이다.
HTTP 세부사항에 따라, PUT 요청은 변경 부분만 작게 하는 게 아니고 전체를 변경하도록 요구한다. 부분적 업데이트는 HTTP PATCH를 사용함.
뒤에서 테스트할 때 에러가 발생하면 GET을 통해 현재 데이터베이스에 아이템이 들어가 있는 지 확인하자.
생략
현재 샘플 앱은 전체 TodoItem
오브젝트를 보여준다. 프로덕션의 앱은 보통 입력으로 들어오는 데이터와 모델의 일부로 보여주는 데이터를 제한한다. 몇가지 이유가 있는데, 보안이 가장 큰 이유이다. 모델의 일부는 주로 DTO (Data Transfer Object 데이터 전송 모델)나 input model, view model이라고 부른다. 이 지면에서는 DTO라고 부른다.
DTO는 이럴 때 쓰인다.
오버포스팅 방지
클라이언트에 보여주고 싶지 않은 property를 숨길 때
payload 사이즈를 줄이기 위해 property 생략 시
nested object가 포함된 object graph를 flatten할 때. flattened 된 object graph가 클라이언트에게 더 편리할 수 있다.
튜토리얼대로 코드를 변경한다.
secret 필드를 POST, GET 할 수 있는지 확인한다.
post -h Content-Type=application/json -c "{"name":"walk dog","isComplete":true, "Secret":"oh"}
결과는 아래와 같다.
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json; charset=utf-8
Date: Thu, 02 Dec 2021 08:02:04 GMT
Server: Kestrel
Transfer-Encoding: chunked
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-7eda8bec404c05b9f14b90096c3b4d6f-94d2def71d17f9e0-00",
"errors": {
"$": [
"The JSON value could not be converted to TodoApi.Models.TodoItemDTO. Path: $ | LineNumber: 0 | BytePositionInLine: 3."
],
"todoItemDTO": [
"The todoItemDTO field is required."
]
}
}
실패!
이렇게 웹 API 만들기가 끝났다.
더 공부할 것은 이것들이 있다.
자습서: JavaScript를 사용하여 ASP.NET Core 웹 API 호출을 참조하세요 .
ASP.NET Core ID는 ASP.NET Core 웹앱에 UI(사용자 인터페이스) 로그인 기능을 추가합니다. 웹 API 및 SPA를 보호하려면 다음 중 하나를 사용하십시오.
IdentityServer4는 ASP.NET Core용 OpenID Connect 및 OAuth 2.0 프레임워크입니다. IdentityServer4는 다음 보안 기능을 활성화합니다.
자세한 내용은 IdentityServer4 시작을 참조하십시오 .