2013-04-03 42 views
1

我正在一個多用戶帳戶系統的用戶帳戶系統在我正在建立的大學電子郵件系統的用戶配置文件編輯器。強大類型的視圖解決錯誤的類型時,發佈回採取行動與繼承模型

我有3個視圖模型AdministratorFacultyStudent從一個Person類繼承。當他們在視圖中使用EditorForModel()顯示時,它們顯示正確的編輯器就好了,但是當我將更改提交給控制器時,它們將作爲基類(我已使用Visual Studio調試器驗證過)而不是正確提交的視圖模型類來解決。所以,當它達到行動方法時,我正在失去重要的編輯器數據。如何在將這些信息發回控制器而不爲每個模型類型創建完全獨立的視圖時如何解決它的正確類型?

+2

你將毫無疑問必須寫用於此目的的自定義模型粘合劑。 – 2013-04-03 23:29:30

+0

如果你不能在不編寫自定義模型綁定器的情況下使用inherted類型,那麼使用editorfor有什麼意義呢 – 2013-04-03 23:36:45

+1

這不是'EditorFor'調用,它決定了傳遞給Action方法的內容..當Model Binder查看它說的方法:「哦,看,一個'人'對象,我會創建其中一個......」。請記住,所有服務器正在接收的是表單發佈值。沒有(默認)方式通知客戶端編輯器模板類型。 – 2013-04-03 23:39:48

回答

1

我想出了以下解決方案:

public class InheritanceBinder : DefaultModelBinder 
    { 

     public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
     { 
      var modelType = bindingContext.ModelType; 
      object model = modelType.Assembly.CreateInstance(modelType.FullName); 

      var inheritedtypes = Assembly.GetExecutingAssembly().GetTypes().Where(t => model.GetType().IsAssignableFrom(t)).ToList(); 
      HttpRequestBase req = controllerContext.HttpContext.Request; 
      var keys = req.Form.Keys.Cast<string>().Where(q => q != "__RequestVerificationToken").ToList(); 



      List<KeyValuePair<Type, int>> matches = new List<KeyValuePair<Type,int>>(); 

      inheritedtypes.ForEach(t => { 
       int p_matches = 0; 

       Array.ForEach(t.GetProperties(), item => 
       { 
        if (keys.Any(key => item.Name == key)) 
         p_matches++; 
       }); 

       matches.Add(new KeyValuePair<Type, int>(t, p_matches)); 
      }); 




      var bestmatches = matches.Where(q => q.Value == matches.Max(s => s.Value)); 
      if (!bestmatches.Any()) 
       throw new TargetInvocationException("Could not determine model to bind based on the form values provided", null); 

      var usematch = bestmatches.First().Key; 

      object bindObj = Activator.CreateInstance(usematch); 



      bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => bindObj, usematch); 

      return base.BindModel(controllerContext, bindingContext); 
     } 


    } 
0

您確定您在操作方法中期望的模型不是Person類型嗎? 這可能會導致您的問題。

+0

它應該是一種被接收的人,但它是錯誤的類型的人,即我發佈一個學生和接收失去與學生相關數據的人 – 2013-04-03 23:25:52

+1

這是正常的,因爲默認模型聯編程序正在使用您的操作方法的參數類型創建一個對象。 – 2013-04-03 23:28:40