2016-06-15 4 views
2

당신은 바인딩 모델 중에이이 NullReferenceException와 충돌합니다 모델 클래스에 다음과 같은 두 가지 속성을 정의하는 경우 :정지 ASP.NET MVC 모델 클래스의 모든 게터를 호출

 public Customer Customer { get; private set; } //set in the action method 
     public bool Name => Customer.Name; 

이것은 Customer이 여전히 있기 때문에 모델 바인딩 중에는 null이고 ASP.NET MVC에서는 Name에 대한 getter를 호출합니다.

스택은 다음과 같습니다이 모델 검증과 같은 스택에서

System.ComponentModel.ReflectPropertyDescriptor.GetValue(Object component) +525 
    System.Web.Mvc.ModelMetadata.get_Model() +34 
    System.Web.Mvc.DataAnnotationsModelValidator.Validate(Object container) +151 
    System.Web.Mvc.<Validate>d__1.MoveNext() +387 
    System.Web.Mvc.DefaultModelBinder.OnModelUpdated(ControllerContext controllerContext, ModelBindingContext bindingContext) +163 
    System.Web.Mvc.DefaultModelBinder.BindComplexElementalModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Object model) +83 
    System.Web.Mvc.DefaultModelBinder.BindComplexModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +1754 
    System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +460 
    System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +137 
    System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +982 
    System.Web.Mvc.<>c__DisplayClass22.<BeginExecuteCore>b__1e() +39 
    System.Web.Mvc.Async.AsyncResultWrapper.<.cctor>b__0(IAsyncResult asyncResult, Action action) +21 
    System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +53 
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +36 
    System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +38 
    System.Web.Mvc.MvcHandler.<BeginProcessRequest>b__5(IAsyncResult asyncResult, ProcessRequestState innerState) +44 
    System.Web.Mvc.Async.WrappedAsyncVoid`1.CallEndDelegate(IAsyncResult asyncResult) +65 
    System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +38 
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +399 
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +137 

모든 게터를 조회한다. 모델 유효성 검사를 사용하지 않습니다.

이 상황을 어떻게 처리 할 수 ​​있습니까? ASP.NET MVC가 (명백한) 이유없이 모든 getter를 호출하지 않도록 할 수 있습니까?

+0

"왜 이러는가?"외에이 모델의 사용법을 보여줄 수 있습니까? 이 예외가 정확히 발생합니까? – CodeCaster

+0

'ActionResult M (MyModel 모델) {m.Customer = ...; 반환보기 (모델); }'. 폼 페이지에서이 패턴이 편리한 패턴임을 알 수 있습니다. – boot4life

+0

모델 바인딩 중 예외가 발생합니다. 내 코드가 실행되기 전에. 스택을 참조하십시오. – boot4life

답변

1

모델 바인더 new가 모델의 인스턴스를 모델링 한 경우 모델의 속성을 반영하여 이름이 일치하는 항목을 FormCollection의 값으로 검색하는 것이 좋습니다. 무슨 일이 일어나고있는 건 위험한 Name 소품이 불려지면 Customer 소품이 널려서 NullRef가 null이라는 것입니다.

.NET에서 이러한 속성을 확인하는 순서는 실제로 무작위 일 수는 없지만 코드를 그대로 처리하여 코드가 크게 향상됩니다. null로 검사하지 않는 한 기본적으로 nullable 인 클래스에서 메서드/소품을 직접 호출하는 것은 끔찍한 생각입니다. 여기에는 두 가지 옵션이 있습니다. (1) 생성자가 "Customer"속성을 초기화하도록 Model 클래스를 다시 디자인하거나, (2) "Name"메서드에서 null 체크를 추가하십시오.

여기에 가장 쉬운 방법입니다 그냥 널 (null) 검사 당신이 그것을 잡을 때 그것을 :

public bool Name => Customer?.Name ?? false; 

이 당신이 서로 연결 널 (NULL) 소품이있는 모델을 가지고있는 근본적인 문제를 해결하지 않습니다. 모델의 생성자가 모델 바인딩을 망칠 까봐 걱정하지 마십시오. Model Binder는 (1) 모델 클래스를 초기화 한 다음 (2) 수화를 시도합니다. 따라서 Model 클래스의 생성자에서 Customer 클래스/prop를 초기화해도 고객 필드에 대한 UI 필드 매핑에 영향을주지 않습니다.

+0

'Customer' 값을 가진 것은 모델 바인딩이 아니라는 것입니다. 그것은 DB에서 온다. 또한 합법적으로 null 일 수 있습니다. 이 경우 Name에 액세스 할 수 없으며 뷰는 그렇게하지 않습니다. ASP.NET을 사용하여 모델 클래스에 데이터를 기록하는 합법적 인 방법이 아닌가? 그것은 데이터를보기로 전달하기위한 것입니다. – boot4life

+0

루트 문제를 데이터로 스누핑하는 것으로 MVC 스누핑이라고 생각할 수 있습니다. MVC가 getter를 호출하지 않게 할 수 있습니까? – boot4life

+0

"It [Customer]는 (는) 합법적으로 null 일 수 있습니다."문제가 있습니다. 모델에서 Customer가 null 인 경우 해당 getter는 호출 될 때 오류를 발생시킵니다. Getter는 메소드가 아니며, 읽는 것만으로는 예외를 트리거해서는 안되는 객체의 속성입니다. 아마도 조건부로 호출하려는 경우에만 메서드를 만들 수 있습니다. ASP.NET MVC는 여기서 문제가되지 않습니다. NullRef를 허용하지 않으려면 Model 클래스를 조정해야합니다. 실제로 NullRef가 디버깅 세션에서 코드를 실행하는 것이 VS 인 경우 Nulled-Customer 모델의 Name 속성을 검사하면 얻을 수 있습니다. – Graham