2010-07-16 1 views
1

예를 들어 고객을 참조하는 필드가있는 Order라는 클래스가 있고 드롭 다운 목록이있는 Order 양식 (< % = Html.DropDownListFor (e => e.Customer.ID, 새 SelectList (. ..)) %>)는 ID 세트 만있는 빈 고객을 작성합니다. 이것은 NHibernate에서 잘 작동하지만, Customer 클래스의 몇몇 필드에 유효성 검사가 추가되면, 모델 바인더는이 필드가 필요하다고 말할 것이다. 모델 바인더가 이러한 참조를 검증하지 못하게하려면 어떻게해야합니까?모델 바인더의 관계 검증을 방지하는 방법은 무엇입니까?

감사합니다.

답변

0

오래된 질문이지만, 나는 후대를 위해 어쨌든 대답하겠다고 생각했습니다. 이 상황에서 바인드를 시도하기 전에 해당 특성을 가로 채기 위해서는 사용자 정의 모델 바인더가 필요합니다. 기본 모델 바인더는 사용자 정의 바인더를 사용하여 등록 정보를 반복적으로 시도하거나 설정되지 않은 경우 기본값을 바인드합니다.

DefaultModelBinder에서 찾고있는 재정의는 GetPropertyValue입니다. 이것은 모델의 모든 속성에 대해 호출되며 기본적으로 DefaultModelBinder.BindModel (전체 프로세스의 진입 점)을 호출합니다.

단순화 된 모델 :

public class Organization 
{ 
    public int Id { get; set; } 

    [Required] 
    public OrganizationType Type { get; set; } 
} 

public class OrganizationType 
{ 
    public int Id { get; set; } 

    [Required, MaxLength(30)] 
    public string Name { get; set; } 
} 

보기 :

<div class="editor-label"> 
    @Html.ErrorLabelFor(m => m.Organization.Type) 
</div> 
<div class="editor-field"> 
    @Html.DropDownListFor(m => m.Organization.Type.Id, Model.OrganizationTypes, "-- Type") 
</div> 

모델 바인더 :

public class OrganizationModelBinder : DefaultModelBinder 
{ 
    protected override object GetPropertyValue(
     ControllerContext controllerContext, 
     ModelBindingContext bindingContext, 
     System.ComponentModel.PropertyDescriptor propertyDescriptor, 
     IModelBinder propertyBinder) 
    { 
     if (propertyDescriptor.PropertyType == typeof(OrganizationType)) 
     { 
      var idResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".Id"); 
      if (idResult == null || string.IsNullOrEmpty(idResult.AttemptedValue)) 
      { 
       return null; 
      } 

      var id = (int)idResult.ConvertTo(typeof(int)); 
      // Can validate the id against your database at this point if needed... 
      // Here we just create a stub object, skipping the model binding and 
      // validation on OrganizationType 
      return new OrganizationType { Id = id }; 
     } 

     return base.GetPropertyValue(controllerContext, bindingContext, propertyDescriptor, propertyBinder); 
    } 
} 

주 그에서 Model.foo.bar에 대해 DropDownList를 작성합니다. Id. 모델 바인더에서 모델 이름에도 추가해야합니다. DropDownListFor는 두 가지 모두에서 제외 할 수 있지만, DropDownListFor는 전송 한 SelectList에서 미리 선택하지 않고 선택한 값을 찾는 데 몇 가지 문제가 있습니다.

마지막으로 컨트롤러에서이 속성을 데이터베이스 컨텍스트에 연결하십시오 (Entity Framework를 사용하는 경우 다르게 처리 할 수 ​​있음). 그렇지 않으면 추적되지 않으며 컨텍스트가 저장시 추가하려고 시도합니다.

컨트롤러 :

public ActionResult Create(Organization organization) 
{ 
    if (ModelState.IsValid) 
    { 
     _context.OrganizationTypes.Attach(organization.Type); 
     _context.Organizations.Add(organization); 
     _context.SaveChanges(); 

     return RedirectToAction("Index"); 
    } 

    // Build up view model... 
    return View(viewModel); 
}