2014-03-04 128 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); 
}