Сбой привязки ядра ASP.NET из-за значения нулевого поля, помеченного [JsonIgnore] - PullRequest
0 голосов
/ 06 ноября 2019

Контроллер ASP.NET принимает объект, который выглядит примерно так:

public class Data
{
    public string Text {get;set;}
    [JsonIgnore] public int Length => Text.Length;
}

Значение свойства текста необязательно. Однако, когда он равен NULL, MVC завершается неудачно во время привязки модели. По какой-то причине код привязки MVC пытается получить доступ к полю длины и получает исключение из-за пустого текста.

Я наивно предполагал, что атрибут JsonIgnore будет учитываться MVC илипо крайней мере, он не будет пытаться десериализовать свойство только для чтения. Как я могу скрыть это свойство от привязки MVC? Есть ли атрибут, который работает как JsonIgnore, который MVC понимает?

Платформа .net core 2.1

РЕДАКТИРОВАТЬ: Отмеченный ответ указал мне в правильном направлении. Я отключил проверку на основе информации с этой страницы Проверка модели в ASP.NET Core MVC и Razor Pages

В объекте запуска ConfigureServices я добавил эту строку:

services.AddSingleton<IObjectModelValidator>(new NullObjectModelValidator());

и создал NullObjectModelValidator

public class NullObjectModelValidator : IObjectModelValidator
{
    public void Validate(ActionContext actionContext, 
        ValidationStateDictionary validationState, string prefix, object model)
    {
    }
}

Это не правильное решение в каждом случае, но если данные не нуждаются в проверке, тогда этот подход работает.

Ответы [ 2 ]

0 голосов
/ 06 ноября 2019

Во-первых - если вы передаете данные из формы в контроллер обычным способом, они передаются не как Json, а как FormData, в Url Encoded Form (пример: Text=&Length=4). Так что JsonIgnore здесь не имеет значения.

Следующее, что ModelBinder не пытается привязать значение к длине (так как оно доступно только для чтения). Он устанавливает только Text в значение null. Затем он пытается применить некоторую проверку по умолчанию, которая включает в себя обход объекта, получение его значений и применение атрибутов проверки. И вот ваша ошибка, как описано в комментарии и @nurdyguy ответ: свойство Length обращается к свойству Length объекта null. Итак, решение здесь:

public int Length => Text?.Length ?? 0;

Другое решение, которое я не рекомендую, состоит в том, чтобы пропустить проверку по полю:

[ValidateNever]public int Length => Text?.Length ?? 0;

Но это только скрывает ошибку в вашем коде, который все еще там.

Кстати: если вам действительно нужно какое-то время исключить какое-либо свойство из привязки модели, используйте атрибут [BindNever] в свойстве (но здесь это не решает вашу проблему, как описано ранее).

0 голосов
/ 06 ноября 2019

Тег [JsonIgnore] указывает, что механизм связывания модели игнорирует это значение при де / сериализации JSON в poco. То, что является , работает правильно и здесь не проблема. Ваша проблема в том, что [JsonIgnore] public int Length => Text.Length; завершится ошибкой, если Text равно нулю, потому что Text.Length выдает исключение нулевой ссылки. Это полностью не зависит от [JsonIgnore]. Вы определили свойство Length как устанавливаемое на основе расчета. Независимо от того, есть тег [JsonIgnore] или нет, это значение необходимо рассчитать, поскольку оно является частью модели.

Один из способов решения этой проблемы - использовать нулевое слияние:

[JsonIgnore] public int Length => Text?.Length ?? 0;

ЭтоКстати, когда Text равен нулю, Text?.Length возвращает ноль, а затем ?? проверяет наличие нуля и возвращает 0. Другой вариант - разрешить Length быть обнуляемым целым:

[JsonIgnore] public int? Length => Text?.Length;

Так что теперь Length будет нулевым, если Text равно нулю, но будет иметь значение, когда Text не равно нулю. Недостатком является то, что вам придется работать в другом месте, имея дело со значением, равным обнуляемому int против обычного int.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...