绑定复杂类型对象列表的问题-Dotnet Core 2.1 Razor Pages [英] Issue with Binding a List of complex type object - Dotnet Core 2.1 Razor Pages

查看:113
本文介绍了绑定复杂类型对象列表的问题-Dotnet Core 2.1 Razor Pages的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在dotnet core 2.1上的项目中使用的是Razor页面,并且应用程序似乎无法正确绑定我的属性,简单类型(int和字符串类型)可以正确绑定,但复杂类型列表却不能正确绑定有没有解决的办法?

I'm using Razor pages for my project on dotnet core 2.1, and the application doesn't seem to bind my properties correctly, the simple types (int and string types) binds correctly but not the list of complex types, is there a work around for this?

我的页面处理程序如下:

my page handler looks like this:

public async Task<IActionResult> OnGetDTResponseAsync(DataTableOptions options) {// Some Code}

当我逐步使用调试器进行调试时,"DataTableOptions选项"的所有简单类型属性都会得到很好的填充,但是复杂类型将返回null.

When I step through with my debugger all simple type properties for "DataTableOptions options" are well populated but the complex type returns null.

我的模型如下:

public class DataTableOptions
{
    public string Draw { get; set; }
    public int Start { get; set; }
    public int Length { get; set; }
    public List<DataTableColumnOrder> Order { get; set; }
    public List<DataTableColumn> Columns { get; set; }
    public DataTableColumnSearch Search { get; set; }
    public List<string> Params { get; set; }

    public DataTableOptions() { }

    public class DataTableColumn
    {
        public string Data { get; set; }
        public string Name { get; set; }
        public bool Searchable { get; set; }
        public bool Orderable { get; set; }
        public DataTableColumnSearch Search { get; set; }

        public DataTableColumn() { }
    }

    public class DataTableColumnSearch
    {
        public string Value { get; set; }
        public bool Regex { get; set; }

        public DataTableColumnSearch() { }
    }

    public class DataTableColumnOrder
    {
        public int Column { get; set; }
        public string Dir { get; set; }

        public DataTableColumnOrder() { }
    }
}

在尝试解决此问题时,我尝试使用

While trying to solve this, I tried using

public async Task<IActionResult> OnGetDTResponseAsync(List<Dictionary<string, string>> columns)

在页面处理程序中

代替DataTableOptions的columns属性,因此我可以手动将属性绑定到我的类:我得到了列的完整列表,该列绑定了它的属性,除了DataTableColumn的DataTableColumnSearch属性也是如此一种复杂的类型,显示为null.

in my page handler in place of the columns property of DataTableOptions so i could manually bind the properties to my class: I got a full list of my columns with it's properties binded to it, except for the DataTableColumn's DataTableColumnSearch property which is also a complex type that came out as null.

public async Task<IActionResult> OnGetDTResponseAsync(List<Dictionary<string, object>> columns) 

也不起作用.

这是提琴手中的请求:

GET/CMS/Index?handler = DTResponse& draw = 1&列%5B0%5D%5Bdata%5D = id&列%5B0%5D%5Bname%5D =&列%5B0%5D%5Bsearchable%5D = false& columns%5B0%5D%5Borderable%5D = false& columns%5B0%5D%5Bsearch%5D%5Bvalue%5D =& columns%5B0%5D%5Bsearch%5D%5Bregex%5D = false& columns%5B1 %5D%5Bdata%5D =名称和列%5B1%5D%5Bname%5D =&列%5B1%5D%5Bsearchable%5D = true&列%5B1%5D%5Borderable%5D = true&列%5B1%5D %5Bsearch%5D%5Bvalue%5D =&列%5B1%5D%5Bsearch%5D%5Bregex%5D = false&列%5B2%5D%5Bdata%5D = webPage.name&列%5B2%5D%5Bname%5D =&列%5B2%5D%5Bsearchable%5D = true&列%5B2%5D%5Borderable%5D = true&列%5B2%5D%5Bsearch%5D%5Bvalue%5D =&列%5B2%5D%5Bsearch% %5D%5Bregex%5D = false&列%5B3%5D%5Bdata%5D = value&列%5B3%5D%5Bname%5D =&列%5B3%5D%5Bsearchable%5D = true&列%5B3%5D %5Borderable%5D = true&列%5B3%5D%5Bsearch%5D%5Bvalue%5D =&列%5B3%5D%5Bsearch%5D%5Bregex%5D = false& col umns%5B4%5D%5Bdata%5D = contentType.name&列%5B4%5D%5Bname%5D =&列%5B4%5D%5Bsearchable%5D = true&列%5B4%5D%5Borderable%5D = true&列%5B4%5D%5Bsearch%5D%5Bvalue%5D =&列%5B4%5D%5Bsearch%5D%5Bregex%5D = false&列%5B5%5D%5Bdata%5D =&列%5B5%5D% 5Bname%5D =&列%5B5%5D%5Bsearchable%5D = false&列%5B5%5D%5Borderable%5D = false&列%5B5%5D%5Bsearch%5D%5Bvalue%5D =&列%5B5% 5D%5Bsearch%5D%5Bregex%5D = false& order%5B0%5D%5Bcolumn%5D = 2& order%5B0%5D%5Bdir%5D = asc& start = 0& length = 10& search%5Bvalue%5D = & search%5Bregex%5D = false& __ = 1545122652329 HTTP/1.1

GET /CMS/Index?handler=DTResponse&draw=1&columns%5B0%5D%5Bdata%5D=id&columns%5B0%5D%5Bname%5D=&columns%5B0%5D%5Bsearchable%5D=false&columns%5B0%5D%5Borderable%5D=false&columns%5B0%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B0%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B1%5D%5Bdata%5D=name&columns%5B1%5D%5Bname%5D=&columns%5B1%5D%5Bsearchable%5D=true&columns%5B1%5D%5Borderable%5D=true&columns%5B1%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B1%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B2%5D%5Bdata%5D=webPage.name&columns%5B2%5D%5Bname%5D=&columns%5B2%5D%5Bsearchable%5D=true&columns%5B2%5D%5Borderable%5D=true&columns%5B2%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B2%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B3%5D%5Bdata%5D=value&columns%5B3%5D%5Bname%5D=&columns%5B3%5D%5Bsearchable%5D=true&columns%5B3%5D%5Borderable%5D=true&columns%5B3%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B3%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B4%5D%5Bdata%5D=contentType.name&columns%5B4%5D%5Bname%5D=&columns%5B4%5D%5Bsearchable%5D=true&columns%5B4%5D%5Borderable%5D=true&columns%5B4%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B4%5D%5Bsearch%5D%5Bregex%5D=false&columns%5B5%5D%5Bdata%5D=&columns%5B5%5D%5Bname%5D=&columns%5B5%5D%5Bsearchable%5D=false&columns%5B5%5D%5Borderable%5D=false&columns%5B5%5D%5Bsearch%5D%5Bvalue%5D=&columns%5B5%5D%5Bsearch%5D%5Bregex%5D=false&order%5B0%5D%5Bcolumn%5D=2&order%5B0%5D%5Bdir%5D=asc&start=0&length=10&search%5Bvalue%5D=&search%5Bregex%5D=false&_=1545122652329 HTTP/1.1

推荐答案

我必须构建一个自定义模型绑定类来处理这种情况. 由于某种原因,在核心2.1 -Razor页面中,不能自动正确地绑定包含另一个复杂对象作为其属性的一部分的复杂对象的收集列表.

I had to build a custom model binding class to handle this scenario. For some reason a Collection List of a complex object that has another complex object as part of it's properties can't be automatically binded correctly in core 2.1 -Razor pages.

请在下面查看我的解决方案:

See my solution below:

using Microsoft.AspNetCore.Mvc.ModelBinding;
using RestaurantDataModel.Data.Requests;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ExampleDataModel.Data
{
public class CustomDataTableEntityBinder : IModelBinder
{
    public Task BindModelAsync(ModelBindingContext bindingContext)
    {
        if (bindingContext == null)
        {
            throw new ArgumentNullException(nameof(bindingContext));
        }

        var allValues = bindingContext.HttpContext.Request.Query;
        DataTableOptions DTOs = new DataTableOptions {
            Draw = allValues.FirstOrDefault(a => a.Key == "draw").Value,
            Start = Convert.ToInt32(allValues.FirstOrDefault(a => a.Key == "start").Value),
            Length = Convert.ToInt32(allValues.FirstOrDefault(a => a.Key == "length").Value)
        };

        if (allValues.Any(a => a.Key.Length > 9 && a.Key.Substring(0, 9).Contains("columns")))
        {
            var myListIndex = 0;
            var myListIndexComparer = 0;
            var allColumns = allValues.Where(a => a.Key.Length > 9 && a.Key.Substring(0, 9).Contains("columns")).ToList();
            DataTableColumn DTC = new DataTableColumn();
            DataTableColumnSearch DTCS = new DataTableColumnSearch();
            DTOs.columns = new List<DataTableColumn>();
            foreach (var column in allColumns)
            {
                var perColumnArray = column.Key.Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
                var rawIndex = perColumnArray[1];

                if (!int.TryParse(rawIndex, out myListIndex))
                {
                    return Task.CompletedTask;
                }

                if (myListIndexComparer != myListIndex)
                {
                    DTC.search = DTCS;
                    DTOs.columns.Add(DTC);
                    DTC = new DataTableColumn();
                    DTCS = new DataTableColumnSearch();
                }
                myListIndexComparer = myListIndex;
                switch (perColumnArray[2])
                {
                    case "data":
                        DTC.data = column.Value;
                        break;
                    case "name":
                        DTC.name = column.Value;
                        break;
                    case "searchable":
                        DTC.searchable = String.IsNullOrWhiteSpace(column.Value) ? false : Convert.ToBoolean(column.Value);
                        break;
                    case "orderable":
                        DTC.orderable = String.IsNullOrWhiteSpace(column.Value) ? false : Convert.ToBoolean(column.Value);
                        break;
                    case "search":
                        if (perColumnArray[3] == "regex")
                        {
                            DTCS.regex = String.IsNullOrWhiteSpace(column.Value) ? false : Convert.ToBoolean(column.Value);
                        }
                        if (perColumnArray[3] == "value")
                        {
                            DTCS.value = column.Value;
                        }
                        break;
                }

                if(allColumns.IndexOf(column) == allColumns.IndexOf(allColumns.Last()))
                {
                    DTC.search = DTCS;
                    DTOs.columns.Add(DTC);
                }
            }
        }
        if (allValues.Any(a => a.Key.Length > 7 && a.Key.Substring(0, 7).Contains("order")))
        {
            var myListIndex = 0;
            var myListIndexComparer = 0;
            var allOrders = allValues.Where(a => a.Key.Length > 7 && a.Key.Substring(0, 7).Contains("order")).ToList();
            DataTableColumnOrder DTCO = new DataTableColumnOrder();
            DTOs.order = new List<DataTableColumnOrder>();
            foreach (var order in allOrders)
            {
                var perColumnArray = order.Key.Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);
                var rawIndex = perColumnArray[1];

                if (!int.TryParse(rawIndex, out myListIndex))
                {
                    return Task.CompletedTask;
                }

                if (myListIndexComparer != myListIndex)
                {
                    DTOs.order.Add(DTCO);
                    DTCO = new DataTableColumnOrder();
                }
                myListIndexComparer = myListIndex;
                switch (perColumnArray[2])
                {
                    case "column":
                        DTCO.Column = Convert.ToInt32(order.Value);
                        break;
                    case "dir":
                        DTCO.Dir = order.Value;
                        break;
                }
                if(allOrders.IndexOf(order) == allOrders.IndexOf(allOrders.Last()))
                {
                    DTOs.order.Add(DTCO);
                }
            }
        }
        if (allValues.Any(a => a.Key.Length > 7 && a.Key.Substring(0, 8).Contains("search")))
        {
            var allSearches = allValues.Where(a => a.Key.Length > 8 && a.Key.Substring(0, 8).Contains("search")).ToList();
            DataTableColumnSearch DTCS = new DataTableColumnSearch();
            DTOs.search = new DataTableColumnSearch();
            foreach (var search in allSearches)
            {
                var perColumnArray = search.Key.Split(new char[] { '[', ']' }, StringSplitOptions.RemoveEmptyEntries);

                switch (perColumnArray[1])
                {
                    case "value":
                        DTCS.value = search.Value;
                        break;
                    case "regex":
                        DTCS.regex = String.IsNullOrWhiteSpace(search.Value) ? false : Convert.ToBoolean(search.Value);
                        break;
                }
                if(allSearches.IndexOf(search) == allSearches.IndexOf(allSearches.Last()))
                {
                    DTOs.search = DTCS;
                }
            }
        }

        bindingContext.Result = ModelBindingResult.Success(DTOs);
        return Task.CompletedTask;
    }
}

}

然后将其添加到模型类的顶部:

And then I added this to the top of my model class:

[ModelBinder(BinderType = typeof(CustomDataTableEntityBinder))]

这篇关于绑定复杂类型对象列表的问题-Dotnet Core 2.1 Razor Pages的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆