수색…


소개

모델 바인딩은 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);
    }


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow