代码之家  ›  专栏  ›  技术社区  ›  andrecarlucci

asp中嵌套属性的模型绑定。净核心2.2

  •  0
  • andrecarlucci  · 技术社区  · 6 年前

    我试图为我的模型(动作参数)创建一个通用的复杂对象,并在许多地方重用它。

    以下是一些示例代码:

    [HttpGet("/api/values")]
    public ActionResult<string> Get([FromQuery] MyModel model) {
        var sb = new StringBuilder();
        sb.AppendLine(model.Id);
        sb.AppendLine($"{model.Id}-{model.Generated?.DateStart}-{model.Generated?.DateEnd}");
        sb.AppendLine($"{model.Id}-{model.Reference?.DateStart}-{model.Reference?.DateEnd}");
        return sb.ToString();
    }
    
    
    public class MyModel {
        public string Id { get; set; }
        public DateInfo Generated { get; set; } = new DateInfo();
        public DateInfo Reference { get; set; } = new DateInfo();
    }
    
    public class DateInfo {
        public DateTime? DateStart { get; set; }
        public DateTime? DateEnd { get; set; }
        public RelativeTime? RelativeTime { get; set; }
    }
    

    假设DateInfo类具有验证和公共属性,可用于许多模型。

    添加 [FromQuery(Name = "Something")] 对嵌套属性的修改有助于招摇过市,但这使得不可能有两个相同类型的嵌套属性。

    乌德帕特:

    我理解添加完全限定的属性名称( .../价值观Id=1&生成。DateInfo=2&参考DateInfo=3 )这会让它工作起来,但这将是一个非常丑陋的方式来调用任何API。连字符是方式,而不是点。

    我希望以映射常规属性的相同方式映射绑定。

    如何做到这一点?

    1 回复  |  直到 4 年前
        1
  •  2
  •   Daniel Rothig    6 年前

    我有两个选择。

    备选方案1: 只需创建一个新的扁平类 {Id, Foo, Bar} 用作动作方法的参数。然后可以将其映射到MyModel。这是我推荐的最易于维护的方法。

    选项2: 自定义模型绑定,如下所示:

    [ModelBinder(BinderType = typeof(MyModelBinder))]
    public class MyModel 
    {
        public string Id { get; set; }
        [FromQuery]
        public Info ComplexNestedProperty { get; set; }
    }
    
    public class AuthorEntityBinder : IModelBinder
    {
        public Task BindModelAsync(ModelBindingContext bindingContext)
        {
            var model = new MyModel 
            {
                Id = bindingContext.ValueProvider.GetValue("id"),
                ComplexNestedProperty = new Info 
                {
                    Foo = bindingContext.ValueProvider.GetValue("foo"),
                    Bar = bindingContext.ValueProvider.GetValue("bar")
                }
            };            
    
            bindingContext.Result = ModelBindingResult.Success(model);
            return Task.CompletedTask;
        }
    } 
    

    作为对 选择2 您可以合理地编写一些反射,以获取嵌套模型的所有叶属性名称。