2011-03-31 1 views
9

나는 다음과 같은 예외가 받고 있어요 :MVC3 모델 바인딩 원인 " 'System.Decimal'에 유형 '선택 System.Int32'에서 매개 변수 변환 실패 - 아니 형식 변환기"

예외 { "매개 변수 변환 더 형식 변환기는 이러한 유형의 사이의 변환 수 없기 때문 'System.Decimal'을 입력 할 유형 '선택 System.Int32'에서 에 실패했습니다. "} System.Exception {System.InvalidOperationException}

이 난 후입니다 JQuer 사용 y 컨트롤러에 json을 다시 게시하기위한 Ajax 게시. ModelState에이 오류가 있지만 MVC3이 JSON을 모델에 올바르게 바인딩하고있어 시계의 모든 데이터를 볼 수 있습니다.

보기에는 하나의 십진수 필드와 숫자가 들어있는 텍스트 상자가 있습니다. 텍스트 상자에 정수 값이있는 경우에도이 오류가 발생합니다.

왜 이것이 실패하고있는가요?

답변

13

MVC3에서 정수를 소수로 변환 할 수없는 기본 모델 바인더에서 문제가 발생한 것 같습니다. 그러나 json의 소스 값이 문자열 또는 십진수 값이면 변환 할 수 있습니다.

해결책은 10 진수 값에 대한 사용자 지정 모델 바인더를 만드는 것입니다.

는 global.asax.cs
ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); 

이 추가 그리고 모델 바인더 만들 :

public class DecimalModelBinder : DefaultModelBinder 
    { 
     public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
     { 
      var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 
      return valueProviderResult == null ? base.BindModel(controllerContext, bindingContext) : Convert.ToDecimal(valueProviderResult.AttemptedValue); 
     } 
    } 
+0

누구든지 설명 할 수 :이 시점에서 내가보고 :) 또한

Null 허용뿐만 아니라 십진수 처리하기 위해 기억을 정지? 나는 그것이 왜 그렇게 될지 모르겠다. – Dan

+0

잘 모르겠지만 MVC3 프로젝트에 대한 버그를 제기하는 것에 대해 생각했지만 결국 기회가 없었습니다. – jaffa

10

약간 자파의 훌륭한 대답을 개선하기 위해, 당신은 그래서 Decimal.TryParse을 사용할 수 있습니다를 빈 문자열과 같은 변환 할 수없는 값은 예외를 throw하지 않지만 일관된 방식으로 처리되도록 기본 바인더에 전달됩니다.

public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var valueProviderResult = bindingContext.ValueProvider.GetValue(bindingContext.ModelName); 

     decimal value; 
     return valueProviderResult == null || !Decimal.TryParse(valueProviderResult.AttemptedValue, out value) ? base.BindModel(controllerContext, bindingContext) : value; 

    } 

는 멀리 볼 수있는 바와 같이, 본래 고장이 ValueProviderResult 내부적 적합한 변환기를 제공 실패한 TypeDescriptor를 오는 변환기를 제공하지 않는 점이다. 기본 동작은하지만 일을 does't 이유

ModelBinders.Binders.Add(typeof(decimal), new DecimalModelBinder()); 
ModelBinders.Binders.Add(typeof(decimal?), new DecimalModelBinder());