为了账号安全,请及时绑定邮箱和手机立即绑定

绑定复杂类型对象列表的问题 - Dotnet Core 2.1 Razor Pages

绑定复杂类型对象列表的问题 - Dotnet Core 2.1 Razor Pages

C#
慕尼黑8549860 2022-06-19 09:49:10
我在 dotnet core 2.1 上为我的项目使用 Razor 页面,应用程序似乎没有正确绑定我的属性,简单类型(int 和 string 类型)正确绑定但不是复杂类型列表,有没有工作为了这个?我的页面处理程序如下所示:public async Task<IActionResult> OnGetDTResponseAsync(DataTableOptions options) {// Some Code}当我使用调试器逐步完成时,“DataTableOptions 选项”的所有简单类型属性都填充得很好,但复杂类型返回 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() { }    }}在尝试解决此问题时,我尝试使用public async Task<IActionResult> OnGetDTResponseAsync(List<Dictionary<string, string>> columns)在我的页面处理程序中代替 DataTableOptions 的 columns 属性,所以我可以手动将属性绑定到我的类:我得到了我的列的完整列表,它的属性绑定到它,除了 DataTableColumn 的 DataTableColumnSearch 属性,它也是一个复杂类型结果为空。public async Task<IActionResult> OnGetDTResponseAsync(List<Dictionary<string, object>> columns) 也不行。这是 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=名称&columns%5B1%5D%5Bname%5D=&columns% 
查看完整描述

1 回答

?
牧羊人nacy

TA贡献1862条经验 获得超7个赞

我必须构建一个自定义模型绑定类来处理这种情况。出于某种原因,具有另一个复杂对象作为其属性的一部分的复杂对象的集合列表无法在核心 2.1 -Razor 页面中自动正确绑定。


请参阅下面的解决方案:


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;

    }

}


}

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


[ModelBinder(BinderType = typeof(CustomDataTableEntityBinder))]


查看完整回答
反对 回复 2022-06-19
  • 1 回答
  • 0 关注
  • 115 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号