asp.net-mvc
모델 바인딩
수색…
소개
모델 바인딩은 HTTP 매개 변수를 일반적으로 GET 요청의 쿼리 문자열 또는 POST 본문에서 가져 와서 컨트롤러에 대한 작업없이 개체 지향 방식으로 유효성을 검사하고 소비 할 수있는 개체에 적용하는 프로세스입니다 HTTP 매개 변수를 검색하는 방법을 잘 알고 있습니다.
즉, 모델 바인딩은 MVC에서 값 유형이나 객체인지 여부에 관계없이 매개 변수를 가질 수 있도록 허용합니다.
비고
조치에서 인스턴스를 작성하기 위해 바인드 모델 프로세스는 여러 위치에서 데이터를 검색합니다.
- 양식 데이터
- 경로 데이터
- 검색어 문자열
- 파일 사용자 정의 (예 : 쿠키)
경로 값 바인딩
URL이 https://stackoverflow.com/questions/1558902
경우 {controller=Home}/{action=Index}/{id?}
와 같은 기본 라우팅을 감안할 때
이것은 QuestionsController로 가고 값 1558902는 인덱스 액션의 id 매개 변수에 매핑됩니다.
public ActionResult Index(int? id){
//id would be bound to id of the route
}
쿼리 문자열 바인딩
경로 바인딩을 확장하려면 https://stackoverflow.com/questions/1558902?sort=desc
와 같은 URL이 있다고합니다.
{controller=Home}/{action=Index}/{id?}
와 같은 라우팅
public ActionResult Index(int? id, string sort){
//sort would bind to the value in the query string, i.e. "desc"
}
객체에 바인딩
종종 asp.net-mvc에서 viewmodel 클래스로 작업 할 것이고 이것들의 속성에 바인딩하고 싶을 것입니다. 이는 개별 매개 변수에 매핑하는 것과 유사합니다.
PostViewModel 같은 단순한 뷰 모델 호출이 있다고합시다.
public class PostViewModel{
public int Id {get;set;}
public int SnappyTitle {get;set;}
}
그런 다음 Id 및 SnappyTitle 값을 http 요청의 양식에서 게시 한 다음 모델 자체가 작업 매개 변수 인 경우 해당 모델로 바로 매핑합니다.
public ActionResult UpdatePost(PostViewModel viewModel){
//viewModel.Id would have our posted value
}
바인딩은 매개 변수와 속성 이름에 대소 문자를 구분하지 않는다는 점에 유의할 가치가 있습니다. 또한 가능한 경우 값을 변환합니다. 특정 예제의 경우 더 많은 엣지 케이스를 남기고 있습니다.
Ajax 바인딩
이들은 POST 메소드를 사용하여 HTTP 요청에 포함되는 양식 값입니다. (jQuery POST 요청 포함).
아약스 게시물을 좋아했다고 해봅시다.
$.ajax({
type: 'POST',
url: window.updatePost,
data: { id: 21, title: 'snappy title' },
//kept short for clarity
});
여기서 json, id 및 title의 두 값은 일치하는 작업에 바인딩됩니다 (예 :
public JsonResult UpdatePost(int id, string title) {
...
}
일반 세션 기반 모델 바인딩
때로는 전체 모델을 보존하고 액션 또는 컨트롤러를 통해 전송해야하는 경우가 있습니다. 이 유형의 요구 사항에 대한 세션 좋은 솔루션에 모델 저장. 이것을 MVC의 강력한 모델 바인딩 기능과 결합하면 우리는 그렇게 우아한 방법을 얻게됩니다. 세 가지 간단한 단계를 통해 일반 세션 기반 모델 바인딩을 만들 수 있습니다.
1 단계 : 모델 바인더 만들기
모델 바인더 자체를 만듭니다. 개인적으로 / Infrastructure / ModelBinders 폴더에 SessionDataModelBinder 클래스를 만들었습니다.
using System;
using System.Web.Mvc;
public class SessionDataModelBinder<TModel>
: IModelBinder
where TModel : class
{
private string SessionKey { get; set; }
public SessionDataModelBinder(string sessionKey)
{
if (string.IsNullOrEmpty(sessionKey))
throw new ArgumentNullException(nameof(sessionKey));
SessionKey = sessionKey;
}
public object BindModel(
ControllerContext controllerContext,
ModelBindingContext bindingContext)
{
// Get model from session
TModel model = controllerContext
.HttpContext
.Session[SessionKey] as TModel;
// Create model if it wasn't found from session and store it
if (model == null)
{
model = Activator.CreateInstance<TModel>();
controllerContext.HttpContext.Session[SessionKey] = model;
}
// Return the model
return model;
}
}
2 단계 : 바인더 등록
우리가 아래와 같은 모델을 가지고 있다면 :
public class ReportInfo
{
public int ReportId { get; set; }
public ReportTypes TypeId { get; set; }
}
public enum ReportTypes
{
NotSpecified,
Monthly, Yearly
}
Application_Start 메소드의 Global.asax 에서이 모델에 대한 세션 기반 모델 바인더를 등록 할 수 있습니다.
protected void Application_Start()
{
.........
// Model binders.
// Remember to specy unique SessionKey
ModelBinders.Binders.Add(typeof(ReportInfo),
new SessionDataModelBinder<ReportInfo>("ReportInfo"));
}
3 단계 : 사용하십시오!
이제 우리는 액션에 매개 변수를 추가하는 것만으로이 모델 바인더로부터 이점을 얻을 수 있습니다.
public class HomeController : Controller
{
public ActionResult Index(ReportInfo reportInfo)
{
// Simply set properties
reportInfo.TypeId = ReportTypes.Monthly;
return View();
}
public ActionResult About(ReportInfo reportInfo)
{
// reportInfo.TypeId is Monthly now because we set
// it previously in Index action.
ReportTypes currentReportType = reportInfo.TypeId;
return View();
}
}
PostModel에서 바인딩 방지
(포스트) 모델 고려 :
public class User
{
public string FirstName { get; set; }
public bool IsAdmin { get; set; }
}
다음과 같은보기 :
@using (Html.BeginForm()) {
@Html.EditorFor(model => model.FirstName)
<input type="submit" value="Save" />
}
악의적 인 사용자가 IsAdmin을 할당하는 것을 방지하기 위해 작업에서 Bind
특성을 사용할 수 있습니다.
[HttpPost]
public ViewResult Edit([Bind(Exclude = "IsAdmin")] User user)
{
// ...
}
파일 업로드
모델:
public class SampleViewModel
{
public HttpPostedFileBase file {get;set;}
}
전망:
@model HelloWorldMvcApp.SampleViewModel
@using (Html.BeginForm("Index","Home",FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div class="form-group">
@Html.TextBoxFor(model => model.file, new {@class="form-control", type="file"})
@Html.ValidationMessageFor(model => model.file)
</div>
<button type="submit" class="btn btn-success submit">Upload</button>
}
동작:
[HttpPost]
public ActionResult Index(SampleViewModel model)
{
if (model.file.ContentLength > 0)
{
string fileName = Path.GetFileName(model.file.FileName);
string fileLocation = "~/App_Data/uploads/"+ fileName;
model.file.SaveAs(Server.MapPath(fileLocation));
}
return View(model);
}
모델 바인더를 사용하여 동적 형식으로 수동으로 날짜 필드 유효성 검사
다른 사용자가 다른 날짜 / 시간 형식을 필요로하는 경우 형식에 따라 수신 날짜 문자열을 실제 날짜로 구문 분석해야 할 수 있습니다. 이 경우이 스 니펫이 도움이 될 수 있습니다.
public class DateTimeBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
DateTime date;
var displayFormat = Session["DateTimeFormat"];
if (value.AttemptedValue != "")
{
if (DateTime.TryParseExact(value.AttemptedValue, displayFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out date))
{
return date;
}
else
{
bindingContext.ModelState.AddModelError(bindingContext.ModelName, "Invalid date format");
}
}
}
return base.BindModel(controllerContext, bindingContext);
}