2014-03-04 46 views
1

我有接口IInterface並實現它自定義模型綁定在接口上返回空MODELNAME

我有一個觀點

@model IEnumerable<IInterface> 
@for (int i = 0; i < Model.Count(); i++) 
{ 
    @Html.EditorFor(x => x[i]) 
} 
<span id="result"></span> 

編輯模板Concrete.cshtml

@model Concrete 
@Ajax.BeginForm("Action", new AjaxOptions { UpdateTargetId = "result" }) 
{ 
    @Html.Hidden("ModelType", Model.GetType()) 
    <input type="submit" /> 
} 

與類Concrete動作:

public string Action(IInterface interface) { return "success"; } 

和模型綁定:

public class MyModelBinder : DefaultModelBinder 
{ 
    protected override CreateModel(
     ControllerContext controllerContext, 
     ModelBindingContext bindingContext, 
     Type modelType) 
    { 
     var typeValue = bindingContext.ValueProvider.GetValue(
          bindingContext.ModelName + ".ModelType" 
         ); 

     ... 

我曾與一個ViewModel內IInterface使用此之前,它工作得很好,但是,現在當我提出我的Ajax表單bindingContext.ModelName是空的。

在調試器中檢查ValueProvider我可以看到它包含一個FormValueProvider誰是_values包含密鑰​​。

使用立即窗口我可以確認調用.GetValue("[0].Interface.ModelType")返回適當的typeValue

我怎麼能得到bindingContext.ModelName不是空的或我怎麼能得到我需要的字符串"[0].Interface.ModelType"

+0

豈不是更好的做法,以實現該接口爲你的模型類型? – PlTaylor

+0

你是什麼意思? –

+0

'@model IInterface'而不是'@model Concrete' – PlTaylor

回答

0

好吧,我發現了一個哈克解決方案,它絕不是令人滿意的:

var typeValue = bindingContext.ValueProvider.GetValue(bindingContext.ModelName + ".ModelType"); 

if (typeValue == null) 
{ 
    var enumerable = (IEnumerable)bindingContext.ValueProvider; 

    var formValueProvider = enumerable.OfType<FormValueProvider>().Single(); 

    var field = typeof(NameValueCollectionValueProvider).GetField(
        "_values", 
        BindingFlags.NonPublic | BindingFlags.Instance 
       ); 

    var dictionary = (IDictionary)field.GetValue(formValueProvider); 

    var keys = (IEnumerable<string>)dictionary.Keys; 

    var key = keys.FirstOrDefault(x => x.EndsWith(".ModelType")); 

    typeValue = bindingContext.ValueProvider.GetValue(key); 
}