Проблема с привязкой списка объектов сложного типа - Dotnet Core 2.1 Razor Pages

Я использую страницы Razor для своего проекта на ядре dotnet 2.1, и приложение, похоже, не связывает мои свойства правильно, простые типы (типы 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)

в моем обработчике страницы вместо свойства columns в DataTableOptions, чтобы я мог вручную привязать свойства к моему классу: я получил полный список моих столбцов с привязанными к нему свойствами, за исключением свойства DataTableColumnSearch DataTableColumn, которое также является сложным типом это оказалось нулевым.

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

тоже не работает.

Вот как выглядит запрос в скрипте:

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% 5D2 = false 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% 5Bsearch 5D% 5Bname% 5D = & columns% 5B4% 5D% 5Bsearchable% 5D = true & column s% 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

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
506
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мне пришлось создать собственный класс привязки модели для обработки этого сценария. По какой-то причине список коллекций сложного объекта, который имеет другой сложный объект как часть его свойств, не может быть автоматически правильно привязан к страницам ядра 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))]

Другие вопросы по теме