dev/asp.net, c#

[.NET 6.0] WebAPI - Request.Body 데이터 수신 (IFormFile 파일,[FromBody] string)

코딩for 2022. 11. 21. 18:18
반응형



.net 6 으로 API 프로젝트 작업을 진행하면서 Back End 작업중 POST 메서드에 대한 처리가 필요했다.

요구사항
1. POST 메서드로 기본적으로 csv, json 파일이 올수 있다.
2. 또는 파일의 내용을 body 에 직접 담아서 보낼수도 있다.
3. 응답 코드는 201로 응답한다.

2가지 방법으로 요청이 오기 때문에 Route를 2개로 따로 받아 처리하기로 하였다. (라우터 하나에 두가지 모두 받는 방법이 있는지는 잘 모르겠다.)

File 로 받기

Post 메소드의 파라미터를 IFormFile 로 한다.

[HttpPost]
public IActionResult Post(IFormFile file)
{
    // 파일을 읽어서(csv, json 에따라서 파싱) 
    var fileContent = this.ReadFile(file);

    //add  service 작업
    // 파일내용을 등록

    // 응답코드 201 리턴
    return CreatedAtAction(nameof(GetList), result);
}


스웨거로 확인한 결과 파일 csv 나 json 파일 입력에 대한 처리 후 정상적으로 201 호출을 응답한다.

 

Body 로 받기

json 으로만 받게 되면 입력 모델 class 를 만들어 처리하면 편하지만,  mvc 나 core 버전이 바뀔때마다 body데이터를 받는게 조금씩 달라지는 경우가 있다. 
Request.Body 데이터를 두가지 형식(cvs, json 문자열)으로 body 로 전달되어 string으로 데이터를 받아서 처리를 하게 되었다.  NET 6 에서 [FromBody] string body 로 받으니 null 로 되어서 Formatter 추가 작업이 필요한것을 알게 되었음.

// Program.cs 

builder.Services.AddControllers(mvcOptions =>
{
    mvcOptions.InputFormatters.Add(new TextSingleValueFormatter());
});

 

// TextSingleValueFormatter.cs 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Formatters;

namespace Employee.Test
{
    public class TextSingleValueFormatter : InputFormatter
    {
        private const string TextPlain = "text/plain";
        public TextSingleValueFormatter()
        {
            SupportedMediaTypes.Add(TextPlain);
        }
        public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
        {
            try
            {
                using (var reader = new StreamReader(context.HttpContext.Request.Body))
                {
                    string textSingleValue = await reader.ReadToEndAsync();
                    //Convert from string to target model type (this is the parameter type in the action method)
                    object model = Convert.ChangeType(textSingleValue, context.ModelType);
                    return InputFormatterResult.Success(model);
                }
            }
            catch (Exception ex)
            {
                context.ModelState.TryAddModelError("BodyTextValue", $"{ex.Message} ModelType={context.ModelType}");
                return InputFormatterResult.Failure();
            }
        }

        protected override bool CanReadType(Type type)
        {
            //Put whatever types you want to handle. 
            return type == typeof(string) ||
                type == typeof(int) ||
                type == typeof(DateTime);
        }
        public override bool CanRead(InputFormatterContext context)
        {
            return context.HttpContext.Request.ContentType == TextPlain;
        }
    }
}

* TextSingleValueFormatter.cs 검색하다 발견한 소스인데 출처를 잊어버림

formatter 처리 후 정상적으로 body 데이터 수신

[HttpPost]
[Route("cvs")]
[Consumes("text/plain")]
public IActionResult Post([FromBody] string cvs)
{
    // 데이터 파싱

    // service 등록 처리

    return Ok();
}



반응형