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

Я использую страницы Razor для своего проекта на dotnet core 2.1, и приложение, похоже, неправильно связывает мои свойства, простые типы (int и string) связываются правильно, но не список сложных типов, этоЕсть ли обходной путь для этого?

мой обработчик страницы выглядит следующим образом:

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

Когда я перехожу через мой отладчик, все свойства простого типа для «Опции DataTableOptions» хорошо заполнены, нокомплексный тип возвращает ноль.

моя модель выглядит следующим образом:

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, чтобы я мог вручную связать свойства с моим классом: я получил полный список моих столбцов с привязанными к нему свойствами, за исключением свойства DataTableColumnSearch объекта DataTableColumn, который также является сложным типом, который вышел как нуль.

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

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

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

GET / CMS / Index? Обработчик = DTResponse & draw = 1 & столбцы% 5B0% 5D% 5Bdata% 5D = id & столбцы% 5B0% 5D% 5Bname% 5D = & columns% 5B0% 5D% 5Bsearchable% 5D = false & columns% 5B0% 5D% 5Borderable% 5D = ложные и столбцы% 5B0% 5D% 5Bsearch% 5D% 5Bvalue% 5D = & столбцы% 5B0% 5D% 5Bsearch% 5D% 5Bregex% 5D = ложь и столбцы% 5B1% 5D% 5Bdata% 5D = имя и столбцы% 5B1% 5D% 5Bname% 5D= & столбцы% 5B1% 5D% 5Bsearchable% 5D = истинные и столбцы% 5B1% 5D% 5Borderable% 5D = истинные и столбцы% 5B1% 5D% 5Bsearch% 5D% 5Bvalue% 5D = & столбцы% 5B1% 5D% 5Bsearch% 5D% 5Bregex% 5D = ложь и столбцы% 5В2% 5D% 5Bdata% 5D = webPage.name & колонны% 5В2% 5D% 5Bname% 5D = & столбцы% 5В2% 5D% 5Bsearchable% 5D = верно и столбцы% 5В2% 5D% 5Borderable% 5D = верно и столбцы% 5В2% 5D% 5Bsearch% 5D% 5Bvalue% 5D = & столбцы% 5В2% 5D% 5Bsearch% 5D% 5Bregex% 5D = ложь и столбцы% 5B3% 5D% 5Bdata% 5D = значение & колонны% 5B3% 5D% 5Bname% 5D = & столбцы% 5B3% 5D% 5Bsearchable% 5D = верно и столбцы% 5B3% 5D% 5Borderable% 5D = верно и столбцы% 5B3% 5D% 5Bsearch% 5D% 5Bvalue% 5D = & столбцы% 5B3% 5D% 5Bsearch% 5D% 5Bregex% 5D = ложь и столбцы% 5B4% 5D% 5Bdata% 5D = contentType.name & столбцы% 5B4% 5D% 5Bname% 5D = & столбцы% 5B4% 5D% 5Bsearchable% 5D = истина &колонны% 5B4% 5D% 5Borderable% 5D = истинные и столбцы% 5B4% 5D% 5Bsearch% 5D% 5Bvalue% 5D = & столбцы% 5B4% 5D% 5Bsearch% 5D% 5Bregex% 5D = ложные и столбцы% 5B5% 5D% 5Bdata% 5D = & столбцы%5B5% 5D% 5Bname% 5D = & колонны% 5B5% 5D% 5Bsearchable% 5D = ложь и столбцы% 5B5% 5D% 5Borderable% 5D = ложные и столбцы% 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 Ответ

0 голосов
/ 22 декабря 2018

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