发布List <Interface> .net core 1.0

jes*_*sew 4 asp.net-mvc custom-model-binder asp.net-core asp.net-core-1.0

我正在.net核心中构建动态表单创建者。“表单”将包含许多不同的表单元素。因此,表单模型将如下所示:

public class FormModel {
  public string FormName {get;set;}
  public List<IElements> Elements{get;set;}
}
Run Code Online (Sandbox Code Playgroud)

我有类TextBoxElementTextAreaElementCheckBoxElement所有实现IElemets接口。我有EditorTemplates每个要素。呈现表单的代码效果很好。尽管由于ListInterfaces的原因,发布表单不起作用。

我一直在研究如何实现自定义模型联编程序,并在网络上看到了一些示例,但没有人工作。

如果有人可以向我展示如何为该示例实现自定义模型绑定程序,我将不胜感激。

计划B:将表单作为json发布到网络api,然后让JSON.Net对其进行隐蔽。我已经尝试过了,而且效果很好。在startup.cs中,我添加了:

services.AddMvc().AddJsonOptions(opts => opts.SerializerSettings.TypeNameHandling = TypeNameHandling.Auto);
Run Code Online (Sandbox Code Playgroud)

必要时返回类型。元素列表中的对象,而不是FormModel上的对象。但我真的很想知道如何使用自定义模型活页夹来解决它。

Lee*_*unn 5

好的,这对我有用。我仍然需要掌握新的模型绑定,因此我可能会做一些愚蠢的事情,但这只是一个开始!

测试表格

<form method="post">
    <input type="hidden" name="Elements[0].Value" value="Hello" />
    <input type="hidden" name="Elements[0].Type" value="InterfacePost.Model.Textbox" />

    <input type="hidden" name="Elements[1].Value" value="World" />
    <input type="hidden" name="Elements[1].Type" value="InterfacePost.Model.Textbox" />

    <input type="hidden" name="Elements[2].Value" value="True" />
    <input type="hidden" name="Elements[2].Type" value="InterfacePost.Model.Checkbox" />

    <input type="submit" value="Submit" />
</form>
Run Code Online (Sandbox Code Playgroud)

接口

public interface IElement
{
    string Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

文本框实现

public class Textbox : IElement
{
    public string Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

复选框的实现

public class Checkbox : IElement
{
    public string Value { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

模型绑定提供者

public class ModelBinderProvider : IModelBinderProvider
{
    public IModelBinder GetBinder(ModelBinderProviderContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException(nameof(context));
        }

        if (context.Metadata.ModelType == typeof(IElement))
        {
            return new ElementBinder();
        }

        // else...
        return null;
    }
}
Run Code Online (Sandbox Code Playgroud)

模型绑定器

public class ElementBinder : IModelBinder
{
    public async Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext.ModelType == typeof(IElement))
        {
            var type = bindingContext.ValueProvider.GetValue($"{bindingContext.ModelName}.Type").FirstValue;

            if (!String.IsNullOrWhiteSpace(type))
            {

                var element = Activator.CreateInstance(Type.GetType(type)) as IElement;

                element.Value = bindingContext.ValueProvider.GetValue($"{bindingContext.ModelName}.Value").FirstValue;

                bindingContext.Result = ModelBindingResult.Success(element);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

挂钩模型绑定程序提供商

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc(options =>
        {
            options.ModelBinderProviders.Insert(0, new ModelBinderProvider());
        });
    }
}
Run Code Online (Sandbox Code Playgroud)

表格模型

public class FormModel
{
    public string FormName { get; set; } // Not using this

    public List<IElement> Elements { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

行动

注意三种类型,文本框,文本框和复选框。

在此处输入图片说明