2010-11-26 2 views
4

런타임에서 검색 한 하위 클래스에 UpdateModel 메서드를 사용하려고합니다. 누군가가 전체 해시를 만들고 있는지 여부를 밝힐 수 있다면 좋을 것입니다./또는 내가하려는 일이 가능한지 여부.MVC UpdateModel 및 하위 클래스 대 기본 클래스

나는 일반적인 동작을 사용하여 여러 부분 뷰의 유효성을 제어합니다. 나는 부분적인 관찰마다 특정한 행동을하는 것을 피하려고 노력하고있다.

각 부분보기는 기본 모델에서 파생 된 고유 한 모델이있다 : I는 제출 된 폼 요소와 값을 얻기 위해 작업에 FormCollection를 사용하고

public class ModelA : ModelBase{ 
    [Required] 
    public string SomeStringProperty{get;set;} 
... 
} 
public class ModelB : ModelBase{ 
    [Required] 
    public DateTime? SomeDateProperty{get;set;} 
... 
} 
public class ModelBase{ 
    public Guid InstanceId{get;set;} 
} 

을,이 모델의 유형을 포함 뷰가 그 요구를 검증하기 위해서 사용하고있을 필요가 있습니다. 이 예를 들어이의 보안 문제를 무시 , 나는 그들을 알고 있어요,이 개념

[HttpPost] 
    public ActionResult ChangeCaseState(int id, FormCollection formCollection) 
    { 
     Guid instanceId = new Guid(formCollection["instanceId"]); 
     string modelType = formCollection["modelType"]; 
     //Return a specific Model class based on the event/modelType 
     var args = GetStateModelClass(modelType, instanceId); 

     try 
     { 
      UpdateModel(args); 
      if(Model.IsValid){ 
      ... 
     } 
     catch (Exception) 
     { 
      return View("~/Views/Shared/StateForms/" + modelType + ".ascx", args); 
     }... 

을의 내부에만 증거입니다 그리고 여기가 기준으로 하위 클래스를 반환하기 위해 사용하고 코드입니다 컨트롤러에 건네받는 modelType

private static ModelBase StateModelClassFactory(string stateModelTypeName, Guid instanceId) 
     { 
      switch (stateModelTypeName) 
      { 
       case "modelTypeA": 
        return new ModelA(workflowInstanceId); 
       case "modelTypeB": 
        return new ModelB(workflowInstanceId); 
    ... 
    } 

StateModelClassFactory 메서드의 반환 형식이 실제로 하위 클래스를 반환하고있어, 비록 기본 클래스의 때문에

은 UpdateModel 방법에 의해 사용되는 모델 바인더는 기본 클래스 내의 값에 바인딩합니다.

이 문제를 해결할 수있는 방법에 대한 아이디어가 있습니까?

업데이트 : 내가 만든

고객 모델 바인더 :

public class CustomModelBinder : DefaultModelBinder 
    { 
     public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
      { 

그리고 후드 조금 더 무슨 일이 있었는지 확인하기 위해 올바른 기본 클래스에 새로운 모델 바인더를 할당 :

ModelBinders.Binders.Add(typeof(ModelBase), new CaseController.CustomModelBinder()); 

모델 바인더를 디버그하고 bindingContext를 검사 할 때 Model 속성이 올바른 Sub Class이지만 ModelType 속성은 기본 클래스의 속성입니다. BindModel 메서드 내에서 ModelType을 변경해야할까요? 이렇게하는 방법에 대한 포인터가 있으면 ModelType의 setter가 중복 된 것처럼 보입니다. 서브 클래스의 SomeDateProperty가 PropertyMetadata 속성에서 actaully 인 것으로 나타났습니다 .... 내가 원했던 것처럼 행동하는 것처럼 보입니다.

답변

2

그래서 내 문제를 해결했다고 생각합니다. 기본적으로 UpdateModel을 호출하기 전에 Model 클래스를 검색하는 방식 때문에 ModelBinder는 Model이 SubClass의 모델이더라도 바인딩합니다.이 코드는 특정 문제를 해결할 때 사용한 코드입니다.

그리고 Global.asax에의

public class SubClassModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var model = bindingContext.Model; 
     var metaDataType = ModelMetadataProviders.Current.GetMetadataForType(null, model.GetType()); 
     bindingContext.ModelMetadata = metaDataType; 
     bindingContext.ModelMetadata.Model = model; 

     return base.BindModel(controllerContext, bindingContext); 
    } 
} 
는 그의 inital 포인터 대린에

ModelBinders.Binders.Add(typeof(ModelBase), new SubClassModelBinder()); 

감사합니다.

+0

+1. 솔루션을 공유해 주셔서 감사합니다. –

0

이 문제를 해결하려면 string 속성 값을 기반으로 올바른 하위 인스턴스를 반환하는 기본 유형에 대한 사용자 정의 모델 바인더를 작성할 수 있습니다.

+0

감사 대린, 내가 솔루션의 시작이다 생각에서 빠른 플레이를했고, 질문을 업데이 트했습니다. – Tr1stan

5

난 그냥이 특정 문제에 달려 UpdateModel로를 통과하면서 더 나은 일반적인 접근 방식은 단지 dynamic에 모델을 캐스팅하는 것입니다 발견 :

이 내 유형의 가능한 모든 속성을 설정 나타납니다
[HttpPost] 
public ActionResult ChangeCaseState(int id, FormCollection formCollection) 
{ 
    ...try 
    { 
     UpdateModel((dynamic)args);//!!notice cast to dynamic here 
     if(Model.IsValid){ 
     ... 
    } 
    catch... 

변수가 기본 유형과 비교되는지 여부에 관계없이

이 문제에 대한 코드 플렉스에 제출 작업 항목이있다 : http://aspnet.codeplex.com/workitem/8277?ProjectName=aspnet

+0

고맙습니다. 나는 .net 3.5 (태그가 질문에 추가됨)를 사용하고있었습니다. 나는 닷넷 4.0 웹 사이트에서 아직 작업하지 않았기 때문에 역동적 인 키워드에 익숙하지 않다. 여전히 문제가된다면 이것을 시도 할 것이다. – Tr1stan

+0

좋은 찾으십시오, 나는 UpdateModel보다는 오히려 TryUpdateModel를 사용하고 동적 인 던지기가 트릭을 할 때이 동일한 문제점을 만났습니다. – blins

+0

결혼 해주세요! 고맙다, 나는이 지위를 가로 질러 오기 전에 지옥에 있었다. x – ctrlplusb