2013-05-25 3 views
16

DefaultModelBinder에서 상속되는 MVC 4 용 사용자 지정 모델 바인더를 만들려고합니다. 에서 인터페이스를 가로 채고 바인딩 수준을 가로 채고 AssemblyQualifiedName이라는 숨겨진 필드에서 원하는 유형을로드하려고합니다. 여기 DefaultModelBinder에서 상속받은 사용자 지정 모델 바인더

는 지금까지 (간체)이 작업은 다음과 같습니다

public class MyWebApplication : System.Web.HttpApplication 
{ 
    protected void Application_Start() 
    { 
     ModelBinders.Binders.DefaultBinder = new InterfaceModelBinder(); 
    } 
} 

public class InterfaceModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, 
     ModelBindingContext bindingContext) 
    { 
     if (bindingContext.ModelType.IsInterface 
      && controllerContext.RequestContext.HttpContext.Request.Form.AllKeys.Contains("AssemblyQualifiedName")) 
     { 
      ModelBindingContext context = new ModelBindingContext(bindingContext); 

      var item = Activator.CreateInstance(
       Type.GetType(controllerContext.RequestContext.HttpContext.Request.Form["AssemblyQualifiedName"])); 

      Func<object> modelAccessor =() => item; 
      context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(), 
       bindingContext.ModelMetadata.ContainerType, modelAccessor, item.GetType(), bindingContext.ModelName); 

      return base.BindModel(controllerContext, context); 
     } 

     return base.BindModel(controllerContext, bindingContext); 
    } 
} 

예 Create.cshtml 파일 (간체) :

@model Models.ScheduledJob 

@* Begin Form *@ 
@Html.Hidden("AssemblyQualifiedName", Model.Job.GetType().AssemblyQualifiedName) 

@Html.Partial("_JobParameters") 
@* End Form *@ 

위 부분 _JobParameters.cshtmlModel.Job의 속성을보고 빌드 편집 컨트롤은 @Html.EditorFor()과 유사하지만 추가 마크 업이 있습니다. ScheduledJob.Job 속성은 IJob (인터페이스) 유형입니다.

예 ScheduledJobsController.cs (간체) : 나는 양식을 저장하면

[HttpPost] 
public ActionResult Create(ScheduledJob scheduledJob) 
{ 
    //scheduledJob.Job here is not null, but has only default values 
} 

, 올바르게 객체 유형을 해석하고 새로운 인스턴스를 가져옵니다 만, 개체의 속성은 적절한으로 설정되지 않습니다 값.

기본 바인더에 지정된 유형의 속성 바인딩을 인계 할 필요가있는 다른 방법에는 무엇이 있습니까?

답변

21

This article은 모델 바인더가 지나치게 복잡하다는 것을 나에게 보여주었습니다. 다음 코드는 작동합니다

는 그 사용자 정의 모델 바인더에 필요한 수있는 모든 경우, 메시지를 무시하기 쉽습니다 MVC 4를
public class InterfaceModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     if (bindingContext.ModelType.IsInterface) 
     { 
      Type desiredType = Type.GetType(
       EncryptionService.Decrypt(
        (string)bindingContext.ValueProvider.GetValue("AssemblyQualifiedName").ConvertTo(typeof(string)))); 
      bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, desiredType); 
     } 

     return base.BindModel(controllerContext, bindingContext); 
    } 
} 
+0

위의 바인더는 어디에서 추가 했습니까? 바인더 ModelBinders.Binders.Add (typeof (Organization), 새 OrganizationModelBinder (DependencyResolver.Current.GetService ())); App_start() 메소드의 global.asax.cs 페이지에 있습니다. 나는 우리가 루트와 번들을 어떻게 사용하는지와 같은 모델 바인더를 등록하는 더 좋은 방법을 찾고있다. – mmssaann

+0

@mmssaann global.asax.cs'Application_Start()'에서'ModelBinders.Binders.DefaultBinder = new MyCustomModelBinder();'를 사용했습니다. 그런 다음, ModelBinder를 추상 클래스 나 인터페이스를 처리 할만큼 충분히 일반화 시켰습니다. 그렇지 않으면 바인딩 논리를 DefaultModelBinder로 전달합니다. –

1

:

protected void Application_Start(object sender, EventArgs e) 
    { 
     //set mvc default messages, or language specifc 
     ClientDataTypeModelValidatorProvider.ResourceClassKey = "ValidationMessages"; 
     DefaultModelBinder.ResourceClassKey = "ValidationMessages"; 
    } 

다음 만들기를 리소스 파일로 ValidationMessages 이름 다음과 같은 항목 :

NAME: FieldMustBeDate 
VALUE: The field {0} must be a date. 
NAME: FieldMustBeNumeric 
VALUE: The field {0} must be a number 

규정 준수에 실패했습니다. 우리의 보안 검사는 javascript 주사가 돌아와 유효성 검사 메시지에 나타나서 실행되는 것을 좋아하지 않았습니다. 이 구현을 사용하여 사용자가 제공 한 값을 반환하는 기본 메시지를 재정의합니다.

관련 문제