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

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

问题描述

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

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.

我的模型看起来像这样:

my model looks like this :

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 属性,它也是一个复杂的类型,结果为空.

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) 

也不起作用.

这是请求在 fiddler 中的样子:

This is what the request looks like in fiddler:

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

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天全站免登陆