Model binding of nested properties in asp.net core 2.2

女生的网名这么多〃 提交于 2020-05-30 05:16:10

问题


I'm trying to create a common complex object for my models (action parameters) and reuse it in many places.

Here is some sample code:

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

Imagine the DateInfo class would have validation and common properties to be used in many models.

Adding [FromQuery(Name = "Something")] to the nested properties does the trick for swagger, but it makes it impossible to have two nested properties with the same type.

UDPATE:

I understand that adding the fully qualified property name (.../values?Id=1&Generated.DateInfo=2&Reference.DateInfo=3) would make it work, but that would be a really ugly way to call any API. Hyphens are the way, not dots.

I would like to map the binding in the same way as mapping a regular property.

How to achieve that?


回答1:


I see two options.

Option 1: Just create a new, flattened class {Id, Foo, Bar} to use as the parameter of your action method. You can then map that to MyModel. That's the approach I would recommend as most maintainable.

Option 2: Custom model binding, as follows:

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

As an expansion on Option 2 you could reasonably write some reflection that gets all the leaf property names of your nested model.



来源:https://stackoverflow.com/questions/53181095/model-binding-of-nested-properties-in-asp-net-core-2-2

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!