HTML 폼 데이터 전송하기 - 파트 1
- 본 번역문서의 원문은 Sending HTML Form Data: Form-urlencoded Data www.asp.net 입니다.
- 본 번역문서는 ASP.NET Web API : HTML 폼 데이터 전송하기 www.taeyo.net 에서도 함께 제공됩니다.
파트 1: 폼-URL인코딩된(Form-urlencoded) 데이터
본문에서는 폼-URL인코딩된 데이터를 Web API 컨트롤러로 전송하는 방법을 살펴봅니다.
기초적인 HTML 폼 정보
HTML 폼은 데이터를 GET이나 POST를 사용해서 서버로 전송합니다. 마크업에서 form 요소의 method 어트리뷰트를 설정하면 전송에 사용될 HTTP 메서드를 지정할 수 있습니다:
<form action="api/values" method="post">
폼 전송의 기본 메서드는 GET입니다. 폼 전송 시 GET 메서드를 사용하면, 폼의 데이터는 쿼리스트링으로 URI에 인코딩됩니다. 반면, 폼 전송 시 POST 메서드를 사용하면, 폼 데이터는 요청 본문에 담겨집니다. 더불어, POST로 전송되는 데이터는 enctype 어트리뷰트를 설정해서 요청 본문의 포멧을 지정할 수 있습니다:
enctype | 설명 |
---|---|
application/x-www-form-urlencoded | 폼 데이터가 URI 쿼리스트링과 비슷한 형태, 즉 이름/값 쌍으로 인코딩됩니다. 이 포멧이 POST 메서드의 기본 포멧입니다. |
multipart/form-data | 폼 데이타가 Multipart MIME 메시지 형태로 인코딩됩니다. 파일을 서버로 업로드 할 때, 이 포멧이 사용됩니다. |
이번 파트 1에서는 x-www-form-urlencoded 포멧만 살펴볼 것입니다. 그리고, 다음 파트 2에서는 Multipart MIME 포멧에 대해서 살펴보겠습니다.
복합 형식 전송하기
일반적인 경우, 폼 컨트롤 몇 개로부터 가져온 값들로 구성된 복합 형식을 서버로 전송하는 경우가 대부분일 것입니다. 가령, 상태 갱신을 뜻하는 다음과 같은 모델이 존재한다고 가정해보겠습니다:
namespace FormEncode.Models { using System; using System.ComponentModel.DataAnnotations; public class Update { [Required] [MaxLength(140)] public string Status { get; set; } public DateTime Date { get; set; } } }
그리고, 다음은 POST를 통해서 Update
개체를 전달 받는 Web API 컨트롤러의 예제 코드입니다.
namespace FormEncode.Controllers { using FormEncode.Models; using System; using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Web; using System.Web.Http; public class UpdatesController : ApiController { static readonly Dictionary<Guid, Update> updates = new Dictionary<Guid, Update>(); [HttpPost] [ActionName("Complex")] public HttpResponseMessage PostComplex(Update update) { if (ModelState.IsValid && update != null) { // 상태 텍스트에 포함되어 있는 모든 HTML 마크업을 변환합니다. update.Status = HttpUtility.HtmlEncode(update.Status); // 새로운 ID를 할당합니다. var id = Guid.NewGuid(); updates[id] = update; // 201 응답을 생성합니다. var response = new HttpResponseMessage(HttpStatusCode.Created) { Content = new StringContent(update.Status) }; response.Headers.Location = new Uri(Url.Link("DefaultApi", new { action = "status", id = id })); return response; } else { return Request.CreateResponse(HttpStatusCode.BadRequest); } } [HttpGet] public Update Status(Guid id) { Update update; if (updates.TryGetValue(id, out update)) { return update; } else { throw new HttpResponseException(HttpStatusCode.NotFound); } } } }
계속해서 이번에는 사용자가 상태 갱신 정보를 제출할 수 있는 HTML 폼을 작성해보겠습니다.
<h1>Complex Type</h1> <form id="form1" method="post" action="api/updates/complex" enctype="application/x-www-form-urlencoded"> <div> <label for="status">Status</label> </div> <div> <input name="status" type="text" /> </div> <div> <label for="date">Date</label> </div> <div> <input name="date" type="text" /> </div> <div> <input type="submit" value="Submit" /> </div> </form>
이 폼의 action 어트리뷰트에 컨트롤러 액션의 URI가 지정되어 있다는 점에 주목하시기 바랍니다. 다음은 폼에 임의의 값들이 입력된 모습을 보여주고 있습니다:
사용자가 이 폼의 Submit 버튼을 클릭하면, 브라우저는 다음과 비슷한 HTTP 요청을 서버로 전송하게 됩니다:
POST http://localhost:38899/api/updates/complex HTTP/1.1 Accept: text/html, application/xhtml+xml, */* User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0) Content-Type: application/x-www-form-urlencoded Content-Length: 47 status=Shopping+at+the+mall.&date=6%2F15%2F2012
이 때, 이름/값 쌍 형태의 폼 데이터가 요청 본문에 들어 있다는 점에 주목하시기 바랍니다.
Web API는 자동으로 이름/값 쌍들로 구성된 데이터를 Update
클래스의 인스턴스로 변환해줍니다.
AJAX로 폼 데이터 전송하기
브라우저는 사용자가 폼을 제출하면, 현재 페이지를 떠나서 응답 메시지의 본문을 렌더링합니다. 이런 동작 방식은 응답 메시지가 HTML 페이지인 경우에는 아무런 문제도 없습니다. 그러나, Web API를 사용하는 경우에는 응답 본문이 비어 있거나 JSON 등으로 구조화된 데이터가 담겨있는 경우가 대부분입니다. 그러므로, 현재 페이지에서 응답을 계속 처리할 수 있도록 AJAX 요청을 통해서 폼 데이터를 전송하는 편이 더 합리적입니다.
다음 코드는 jQuery를 사용해서 폼 데이터를 POST 전송하는 방법을 보여줍니다.
<script type="text/javascript"> $("#form1").submit(function () { var jqxhr = $.post('api/updates/complex', $('#form1').serialize()) .success(function () { var loc = jqxhr.getResponseHeader('Location'); var a = $('<a/>', { href: loc, text: loc }); $('#message').html(a); }) .error(function () { $('#message').html("Error posting the update."); }); return false; }); </script>
이 코드에 사용된 jQuery submit 함수는 폼의 동작을 새로운 함수로 대체시켜줍니다.
그 결과, Submit 버튼의 기본적인 동작이 재정의됩니다.
또한, serialize 함수는 폼의 데이터들을 이름/값 쌍들로 직렬화시켜줍니다.
그리고, 폼 데이터를 서버로 전송하기 위해서는 $.post()
를 호출하고 있습니다.
마지막으로, 요청이 완료되면 .success()
헨들러나 .error()
헨들러가 사용자에게 적절한 메시지를 보여주게 됩니다.
단순 형식 전송하기
이전 절에서는 복합 형식 전송에 관해서 살펴봤으며, 이 방식으로 전송된 데이터는 Web API에 의해 모델 클래스의 인스턴스로 역직렬화 되었습니다. 당연한 얘기겠지만, 문자열 같은 단순 형식도 전송이 가능합니다.
단순 형식을 전송하는 방식도 기본적으로는 크게 다른 점이 없지만, 두 가지 미세한 차이점이 존재합니다. 첫 번째로 컨트롤러의 액션 매개변수 이름에 반드시 FromBody 어트리뷰트를 지정해야만 합니다.
[HttpPost] [ActionName("Simple")] public HttpResponseMessage PostSimple([FromBody] string value) { if (value != null) { Update update = new Update() { Status = HttpUtility.HtmlEncode(value), Date = DateTime.UtcNow }; var id = Guid.NewGuid(); updates[id] = update; var response = new HttpResponseMessage(HttpStatusCode.Created) { Content = new StringContent(update.Status) }; response.Headers.Location = new Uri(Url.Link("DefaultApi", new { action = "status", id = id })); return response; } else { return Request.CreateResponse(HttpStatusCode.BadRequest); } }
그 이유는 Web API가 기본적으로 요청 URI에서 기본 형식들을 읽어오려고 시도하기 때문입니다. 따라서, FromBody 어트리뷰트를 지정해서 Web API에게 해당 값을 요청 본문에서 읽어오도록 지시해야 합니다.
두 번째로 클라이언트는 값을 다음과 같은 형식으로 전송해야만 합니다:
=value
단순 형식에서는 이름/값 쌍의 이름 부분이 반드시 비어 있어야만 합니다. 일부 브라우저는 HTML 폼에서 이를 지원하지 않지만 다음과 같은 스크립트를 사용해서 이런 형식을 만들 수 있습니다:
$.post('api/updates/simple', { "": $('#status1').val() });
다음은 예제 폼입니다:
<h1>Simple Type</h1> <form id="form2"> <div> <label for="status">Status</label> </div> <div> <input id="status1" type="text" /> </div> <div> <input type="submit" value="Submit" /> </div> </form>
그리고, 다음은 폼 값을 서버로 제출하는 스크립트 예제입니다. 이전 스크립트와 유일하게 다른점은 post 함수에 전달되는 인자 한 가지 뿐입니다.
$('#form2').submit(function () { var jqxhr = $.post('api/updates/simple', { "": $('#status1').val() }) .success(function () { var loc = jqxhr.getResponseHeader('Location'); var a = $('<a/>', { href: loc, text: loc }); $('#message').html(a); }) .error(function () { $('#message').html("Error posting the update."); }); return false; });
또한, 단순 형식의 배열을 전송할 때도 같은 접근 방식을 사용할 수 있습니다:
$.post('api/updates/postlist', { "": ["update one", "update two", "update three"] });
다음 과정
- 여러분의 첫 번째 ASP.NET Web API (C#) 2013-05-27 20:30
- CRUD 작업을 지원하는 Web API 작성하기 2013-06-14 20:30
- ASP.NET 웹폼에서 Web API 사용하기 2013-06-25 20:30
- ASP.NET Web API와 라우팅 2013-07-10 20:30
- ASP.NET Web API 도움말 페이지 작성하기 2013-08-14 15:43
- .NET 클라이언트에서 Web API 호출하기 (C#) 2013-08-21 16:26
- WPF 응용 프로그램에서 Web API 호출하기 (C#) 2013-08-28 22:41
- HttpClient 메시지 처리기 2013-09-04 17:16
- ASP.NET Web API 예외 처리 2013-09-11 21:23
- HTML 폼 데이터 전송하기 - 파트 1 2013-09-18 21:23
- HTML 폼 데이터 전송하기 - 파트 2 2013-09-25 01:11
- ASP.NET Web API와 HTTP 쿠키 2013-10-02 09:00
- 자체-호스트(Self-Host) Web API (C#) 2013-10-09 15:59
- OWIN을 이용한 ASP.NET Web API 자체 호스트(Self-Host) 2014-01-17 08:00
- 보안: ASP.NET Web API의 인증(Authentication)과 권한(Authorization) 2014-01-20 08:00
- 보안: 기본 인증 2014-01-22 08:00
- 보안: ASP.NET Web API와 개별 사용자 계정 2014-01-24 08:00
- 보안: 폼 인증 2014-01-27 08:00
- 보안: 통합 Windows 인증 2014-01-29 08:00
- 보안: 크로스 사이트 요청 위조(Cross-Site Request Forgery) 공격 방지하기 2014-02-03 08:00
- 보안: Web API에서 SSL 사용하기 2014-02-05 08:00
- 보안: 외부 인증 서비스 (C#) 2014-02-07 08:00
- 보안: ASP.NET Web API 교차-원본 요청(Cross-Origin Request) 활성화하기 2014-02-10 08:00