[ASP.NET Core] ASP.Net Core 를 활용해서 API 서버 구축하기
카테고리: ASP .NET Core
태그: ASP.NET Core C# Unity Web
이전 프로젝트에서는 서버사이드 PHP를 사용하여 Http 통신을 하였습니다.
이번에는 ASP.NET Core를 사용하여 API 서버를 만들어서 데이터를 주고 받고 할 수 있도록 만들었습니다.
현재는 동작이되고, CRUD 가 되는 기본적인 상태입니다.
DataBase와 연결
ASP.NET Core에서 DB와 연결하기 위해서는 다음과 같은 세팅을 해줘야 합니다.
appsettings.json
우선, 데이터베이스 서버의 Connection String
을 기입합니다.
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"MySqlServer": "your_database_string"
}
}
Program.cs
appsettings.json
을 기입하였다면, Program.cs
스크립트로 와서 DB 연결 코드를 추가합니다.
해당 코드를 삽입하면, 데이터베이스 서버와 연결이 완료 됩니다 .
builder.Services.AddDbContext<MySqlContext>
(options => options.UseMySql(builder.Configuration.GetConnectionString("MySqlServer"),
ServerVersion.AutoDetect(builder.Configuration.GetConnectionString("MySqlServer")))
);
Model 클래스 만들기
이제 데이터베이스의 테이블과 매핑되는 Model
클래스를 만듭니다.
이 클래스는 데이터베이스의 테이블에 있는 컬럼과 같게 만들어야 합니다.
대소문자는 구분하지 않지만, 이름이 다르면 인식하지 못하니 그점을 주의합니다.
🗅 class User
using System.ComponentModel.DataAnnotations;
namespace MyApi.Models
{
public class User
{
[Key]
public int Id { get; set; }
[StringLength(255)]
public string? UserName { get; set; }
[Phone]
public string? phone_number { get; set; }
[Range(1,100)]
public int? Age { get; set; }
}
}
Context
이제 해당 DB의 Context
를 가져와서, 테이블과 매핑합니다.
현재 저는 user
테이블과 test
테이블 두가지 테이블을 만들어 놨습니다.
해당 Context 안에 User
와 TestItem
을 넣어 테이블의 컨텍스트를 만들어 줍니다.
🗅 class MySqlContext
using Microsoft.EntityFrameworkCore;
namespace MyApi.Models
{
public class MySqlContext:DbContext
{
public MySqlContext(DbContextOptions<MySqlContext> options): base(options)
{
}
public DbSet<User> User { get; set; } = null!;
public DbSet<TestItem> Test { get; set; } = null!;
}
}
Controller
이제 Controller
를 만들어 실제 데이터를 주고받는 로직을 구현합니다.
Controller
에서는 일반 Model
클래스를 바로 사용하는 것이 아닌, DTO(Data Transfer Object)
를 만들어서, 필요한 정보만 담아서 보냅니다.
🗅 class UserDTO
using System.ComponentModel.DataAnnotations;
namespace MyApi.Models
{
public class UserDTO
{
[Key]
public int Id { get; set; }
[StringLength(255)]
public string? UserName { get; set; }
[Phone]
public string? phone_number { get; set; }
[Range(1, 100)]
public int? Age { get; set; }
}
}
DTO를 만들었다면, Controller에 스크립트를 작성합니다.
Restful API
에 맞게 Get
, Post
, Put
, Patch
, Delte
메서드를 만듭니다.
🗅 class UserController
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using TodoApi.Models;
namespace MyApi.Controllers
{
[Route("api/users")]
[ApiController]
public class UserController : ControllerBase
{
private readonly MySqlContext context;
public UserController(MySqlContext context)
{
this.context = context;
}
[HttpGet]
public async Task<ActionResult<IEnumerable<UserDTO>>> GetUsers()
{
try
{
return await context.User.Select(x => ItemToDTO(x)).ToListAsync();
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpGet("{id}")]
public async Task<ActionResult<UserDTO>> GetUser(int id)
{
try
{
var user = await context.User.FindAsync(id);
if (user == null)
{
return NotFound();
}
return ItemToDTO(user);
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpPut("id")]
public async Task<IActionResult> PutUser(int id, UserDTO userDTO)
{
if (id != userDTO.Id)
{
return BadRequest();
}
var user = await context.User.FindAsync(id);
if (user == null)
{
return NotFound();
}
user.UserName = userDTO.UserName;
user.phone_number = userDTO.phone_number;
user.Age = userDTO.Age;
try
{
await context.SaveChangesAsync();
}
catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
{
return NotFound();
}
return NoContent();
}
[HttpPost]
public async Task<IActionResult> PostUser(UserDTO userDTO)
{
try
{
var user = new User
{
UserName = userDTO.UserName,
phone_number = userDTO.phone_number,
Age = userDTO.Age,
};
context.User.Add(user);
await context.SaveChangesAsync();
return CreatedAtAction(nameof(GetUser), new { id = user.Id }, ItemToDTO(user));
}
catch (Exception ex)
{
// 에러가 발생하면 BadRequest 응답을 반환합니다.
return BadRequest(ex.Message);
}
}
[HttpPatch("{id}")]
public async Task<ActionResult<UserDTO>> PatchUser(int id, UserDTO userDTO)
{
try
{
var user = await context.User.FindAsync(id);
if (user == null)
{
return NotFound();
}
user.UserName = userDTO.UserName;
user.phone_number = userDTO.phone_number;
user.Age = userDTO.Age;
await context.SaveChangesAsync();
return CreatedAtAction(nameof(GetUser), new { id = user.Id }, ItemToDTO(user));
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
[HttpDelete("{id}")]
public async Task<IActionResult> DeleteTodoItem(int id)
{
try
{
var user = await context.User.FindAsync(id);
if (user == null)
{
return NotFound();
}
context.User.Remove(user);
await context.SaveChangesAsync();
return NoContent();
}
catch (Exception ex)
{
return BadRequest(ex.Message);
}
}
private bool TodoItemExists(long id)
{
return context.User.Any(e => e.Id == id);
}
private static UserDTO ItemToDTO(User todoItem) =>
new UserDTO()
{
Id = todoItem.Id,
UserName = todoItem.UserName,
phone_number = todoItem.phone_number,
Age = todoItem.Age
};
}
}
이렇게 하면, Swagger 를 통해 문서화된 API 서버를 만들 수 있습니다.
Unity Client
제가설정한 라우팅 경로로 접근하면 정보를 받을 수 있는지 테스트 하는 Unity Client 코드를 작성하였습니다.
전체코드는 저번에 작성하였던 PHP를 활용한 HTTP 통신 포스팅에 있는 코드와 거의 동일 합니다.
이번에는 Post
코드만 포스팅 하겠습니다.
//Post == Insert
public IEnumerator PostTodoItem(TodoItemDTO _item, Action<bool, TodoItemDTO> _action)
{
string itemJson = JsonUtility.ToJson(_item);
byte[] jsonToSend = new UTF8Encoding().GetBytes(itemJson);
UnityWebRequest request = new UnityWebRequest(url, "POST");
request.uploadHandler = new UploadHandlerRaw(jsonToSend);
request.downloadHandler = new DownloadHandlerBuffer();
request.SetRequestHeader("Content-Type", "application/json");
yield return request.SendWebRequest();
try
{
if (request.result == UnityWebRequest.Result.ConnectionError ||
request.result == UnityWebRequest.Result.ProtocolError)
{
_action(false, null);
}
else
{
Debug.Log("Received: " + request.downloadHandler.text);
JObject jsonResponse = JObject.Parse(request.downloadHandler.text);
long userID = method.ParseLongOrDefault(jsonResponse["id"].ToString());
string userName = method.CheckNull(jsonResponse["name"].ToString());
string isComplete = method.CheckNull(jsonResponse["isComplete"].ToString());
TodoItemDTO todoItemDTO = new TodoItemDTO(userID, userName, isComplete);
_action(true, todoItemDTO);
}
}
catch (Exception ex)
{
//로깅작업
_action(false, null);
}
}
Post
는 내용을 받아 서버에 저장하는 역할을 합니다.
댓글 남기기