View에서 Controller로 data를 전달하는 방법을 알아보자
ASP.NET Core는 다음의 attributes를 사용해서 다양한 소스를 바인딩 하도록 한다.
- [FormForm] : From HTML Form
- [FromRoute] : From Route Values
- [FromQuery] : From Query String
- [FromBody] : From Request Body
- [FromHeader] : From Request Header
모델 바인딩이란?
HTTP Request에서 Controller의 Action method의 parameter로 전달된 data를 mapping하는 프로세스이다.
HTTP Request는 다양한 형식의 data를 포함한다. ASP.NET Core model binding mechanism은 다양한 형식의 값들이 action method의 parameter로 쉽게 바인딩 되도록 한다.
Submit 버튼 클릭 -> Post Requst 전송 (Form Data, Query String, Route Parameter 등등) -> Routing Engine이 요청 URL과 매핑되는 action method 찾아서 실행 -> Model binder가 action method 실행 직전에 HTTP Request data를 parameter로 변경
Model binder가 Request data를 바딩인에 실패한 경우 ModelState.isValid 값으로 성공여부를 확인할 수 있다.
Model binding 없이 직접 data가 접근할 수 있는 방법을 알아보자.
- HTML Forms에 직접 접근 : Request object에 접근
[HttpPost]
public IActionResult NoModelBinding()
{
ProductEditModel model = new ProductEditModel();
string message = "";
model.Name = Request.Form["Name"].ToString();
model.Rate = Convert.ToDecimal( Request.Form["Rate"]);
model.Rating =Convert.ToInt32( Request.Form["Rateing"]);
message = "product " + model.Name + " created successfully";
return Content(message);
}
- Query String에 직접 접근 : Request.Query collection에 접근
Request.Query[“id”].ToString()
- Request Header에 직접 접근 : Request.Headers collection에 접근
- Route Data에 직접 접근
OnActionExecuting 함수를 override 해야한다.
using Microsoft.AspNetCore.Mvc.Filters;
public override void OnActionExecuting(ActionExecutingContext context)
{
string id = context.RouteData.Values["id"].ToString();
base.OnActionExecuting(context);
}
Model Binding Sources
- HTML Form & Query String에서 데이터 추출
<form action="/home/FormAndQuery/?name=Test" method="post">
<label for="Name">Name</label>
<input type="text" name="Name" />
<label for="Rate">Rate</label>
<input type="text" name="Rate" />
<label for="Rating">Rating</label>
<input type="text" name="Rating" />
<input type="submit" name="submit" />
</form>
[HttpGet]
public IActionResult FormAndQuery()
{
return View();
}
[HttpPost]
public IActionResult FormAndQuery([FromQuery] string name,ProductEditModel model)
{
string message = "";
if (ModelState.IsValid)
{
message = "Query string "+ name + " product " + model.Name + " Rate " + model.Rate + " Rating " + model.Rating ;
}
else
{
message = "Failed to create the product. Please try again";
}
return Content(message);
}
name은 Form에도 포함되어 있고, query string에도 포함되어 있다.
form이 submit될 때, name parameter는 언제나 form field로 매핑된다.
Model binder는 아래 우선 순서로 match한다.
- Form Values
- Route Values
- Query strings
[FromQuery] attribute를 사용해서 name parameter를 query string에서 값을 가져오도록 지정할 수 있다.
Controlling the Binding Source
- [FormForm] : From HTML Form
[HttpPost]
public IActionResult Create([FromForm] ProductEditModel model)
{
}
- [FromRoute] : From Route Values
- [FromQuery] : From Query String
- [FromBody] : From Request Body
- [FromHeader] : From Request Header
public IActionResult FromHeader( [FromHeader] string Host)
{
return Content(Host);
}
public void OnGet([FromHeader(Name = "Accept-Language")] string language)
{
return Content(language);
}
- [FromServices] : 의존성 주입을 이용해서 서비스로부터 가져온 값으로 매개변수를 바인딩
Simple types
model binder는 source string을 아래의 형식으로 변환할 수 있다.
Boolean
Byte, SByte
Char
DateTime
DateTimeOffset
Decimal
Double
Enum
Guid
Int16, Int32, Int64
Single
TimeSpan
UInt16, UInt32, UInt64
Uri
Version
Complex types
아래와 같이 public property와 public default constructor를 갖는다.
public class Instructor
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
}
Attributes for complex type
아래 attributes는 data source가 form data일 때만 유효하다.
- [Bind]
- [BindRequired]
- [BindNever]
[Bind]
모델의 어떤 properties가 model binding에 꼭 포함되어야 하는지 명시한다.
[Bind("LastName,FirstMidName")]
public class Instructor
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
}
또는 post method에서 지정할 수도 있다.
[HttpPost]
public IActionResult OnPost(
[Bind("LastName,FirstMidName")] Instructor instructor)
[ModelBinder]
모델 바인딩될 때 속성 또는 매개 변수의 이름을 변경하는 데 사용할 수도 있습니다.
public class Instructor
{
[ModelBinder(Name = "instructor_id")]
public string Id { get; set; }
// ...
}
[BindRequired]
model property에만
Disabling Binding with [BindNever]
model binder에서 property를 bind하지 않도록 알려주기 위해서 아래와 같이 attribute를 지정할 수 있다.
[BindNever]
public int Rating { get; set; }
반대로 [BindRequired] attribute도 있다.
Collections
- selectedCourses=1050&selectedCourses=2000
- selectedCourses[0]=1050&selectedCourses[1]=2000
- [0]=1050&[1]=2000
- selectedCourses[a]=1050&selectedCourses[b]=2000&selectedCourses.index=a&selectedCourses.index=b
- [a]=1050&[b]=2000&index=a&index=b
public IActionResult OnPost(int? id, int[] selectedCourses)
Dictionaries
- selectedCourses[1050]=Chemistry&selectedCourses[2000]=Economics
- [1050]=Chemistry&selectedCourses[2000]=Economics
- selectedCourses[0].Key=1050&selectedCourses[0].Value=Chemistry&
selectedCourses[1].Key=2000&selectedCourses[1].Value=Economics - [0].Key=1050&[0].Value=Chemistry&[1].Key=2000&[1].Value=Economics
public IActionResult OnPost(int? id, Dictionary<int, string> selectedCourses)
'ASP.NET Core' 카테고리의 다른 글
.NET 6 API with Redis] 2. docker를 사용해서 redis 컨테이너 구성 (0) | 2022.05.18 |
---|---|
.NET 6 API with Redis] 1. Redis란? (0) | 2022.05.18 |
ASP.NET Core] Form Tag Helper, Environment Tag Helper (0) | 2022.01.25 |
ASP.NET Core] Input Tag Helper (0) | 2022.01.25 |
ASP.NET Core] Tag Helper (0) | 2022.01.25 |
댓글