接口上的自定义模型绑定返回空ModelName

时间:2014-03-04 16:35:11

标签: c# asp.net-mvc model-binding

我有接口IInterface和实现它的类Concrete

我有一个观点

@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" />
}

采取行动:

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的{​​{1}}包含密钥[0].Interface.ModelType

使用立即窗口我可以确认呼叫.GetValue("[0].Interface.ModelType")会返回相应的typeValue

如何让bindingContext.ModelName不为空,或者如何获取我需要的字符串"[0].Interface.ModelType"

1 个答案:

答案 0 :(得分:0)

好的,我找到了一个令人满意的hacky解决方案:

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);
}