Установите NullValueHandling на уровне контроллера

На данный момент я хотел бы исключить нулевые значения из моего ответа API, поэтому в моем файле startup.cs у меня есть это.

services.AddMvc()
    .AddJsonOptions(options =>
    {
        // Setup json serializer
        options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        options.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
    });

Но можно ли заявить, что на 1 или более контроллерах я действительно хочу включить значения NULL ??


person Gillardo    schedule 04.02.2016    source источник


Ответы (2)


Один из вариантов — создать собственный тип результата Json, как описано в этом вопросе: Использование JSON.NET в качестве сериализатора JSON по умолчанию в ASP.NET MVC 3 — возможно ли это?. Затем вы можете иметь bool var на базовом контроллере и использовать его, чтобы отключить нуль при использовании пользовательского результата Json или даже напрямую передать параметр:

return Json(data, ignoreNulls: true); 
person csharpfolk    schedule 04.02.2016

Вы можете получить JsonOutputFormatter из BindingContext.OutputFormatters внутри кода вашего контроллера. Это позволяет вам динамически изменять файл SerializerSettings.

Попробуйте включить using Newtonsoft.Json; в код контроллера и сделать следующее внутри вашего действия контроллера:

var f = BindingContext.OutputFormatters.FirstOrDefault(
            formatter => formatter.GetType() ==
                         typeof (Microsoft.AspNet.Mvc.Formatters.JsonOutputFormatter))
        as Microsoft.AspNet.Mvc.Formatters.JsonOutputFormatter;
if (f != null) {
    //f.SerializerSettings.Formatting = Formatting.Indented;
    f.SerializerSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore;
}

Я включил Formatting = Formatting.Indented только для своих тестов, потому что результаты сразу видны. Вам это не нужно по причине.

ОБНОВЛЕНО: я создал демонстрационный проект с использованием веб-приложения MVC без аутентификации. Затем я добавил в HomeController следующий метод

public object TestMethod()
{
    var testResult = new {
                         name = "Test",
                         value = 123,
                         nullableProperty = (string) null
                     };

    return testResult;
}

и изменил URL-адрес запуска проекта на Home/TestMethod и запустил демонстрацию. я мог видеть

{"name":"Test","value":123,"nullableProperty":null}

Вам не нужно добавлять какие-либо дополнительные операторы использования, чтобы использовать код, который я разместил изначально (нужны только стандартные using Microsoft.AspNet.Mvc; и using System.Linq;), но код мог бы быть более читабельным, если бы у вас были using Microsoft.AspNet.Mvc.Formatters; и using Newtonsoft.Json;. Я добавил операторы использования для Microsoft.AspNet.Mvc.Formatters и Newtonsoft.Json и изменил код следующим образом.

public object TestMethod()
{
    var testResult = new {
                         name = "Test",
                         value = 123,
                         nullableProperty = (string) null
                     };

    var f = BindingContext.OutputFormatters.FirstOrDefault(
                formatter => formatter.GetType() == typeof (JsonOutputFormatter)) as JsonOutputFormatter;
    if (f != null) {
        f.SerializerSettings.Formatting = Formatting.Indented;
        f.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    }
    return testResult;
}

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

{
  "name": "Test",
  "value": 123
}

Стандартный код использует "Newtonsoft.Json" в версии 6.0.6. Мы можем добавить "Newtonsoft.Json": "8.0.2" в зависимости, чтобы использовать последнюю версию Newtonsoft.Json. См. проблему с разрешением косвенных зависимостей, о которой я сообщил в проблеме и которая все еще открыта .

Вы можете загрузить тестовый проект из здесь.

person Oleg    schedule 04.02.2016
comment
Кажется, я не вижу BindingContext из моего метода контроллера? это для ASPNET5? - person Gillardo; 05.02.2016
comment
@ user2736022: Да, конечно. Внутри каждого действия контроллера у вас есть this со свойствами HttpContext, BindingContext и так далее. Вы можете просто ввести this. внутри своего метода. После ввода . IntellySense покажет вам все свойства this, включая BindingContext. C# позволяет (рекомендует) писать BindingContext вместо this.BindingContext. - person Oleg; 05.02.2016
comment
Можете ли вы проверить пространство имен, в котором оно находится? Он говорит, что мой контроллер не содержит определения для BindingContext - person Gillardo; 05.02.2016
comment
@ user2736022: BindingContext является собственностью Controller. Каждый контроллер MVC6 должен быть классом, который e using Microsoft.AspNet.Mvc;. Я описал все шаги в части ОБНОВЛЕНО своего ответа и загрузил здесь тестовый проект Visual Studio 2015, демонстрирующий код. - person Oleg; 05.02.2016
comment
MVC Core повторно использует один и тот же экземпляр JsonOutputFormatter во всех контроллерах. Изменение параметра сериализатора внутри контроллера почти идентично его изменению при запуске. - person Pranav; 05.02.2016
comment
@Pranav: я тоже так думаю. Таким образом, необходимо установить настройки variable во всех контроллерах. Можно определить производный класс от класса Controller и использовать его во всех контроллерах. Я хочу показать, как можно изменить SerializerSettings динамически. Весь остальной код должен быть написан в точном соответствии с требованиями. - person Oleg; 05.02.2016
comment
Я использую rc2, кажется, этого не существует? rc1 имеет BindingContext, но не rc2... - person Gillardo; 08.02.2016
comment
@ user2736022: Вы можете сэкономить много времени, если изначально предоставите правильную информацию. RC2 сейчас находится в процессе переименования. Многие пакеты, методы, внутренние структуры переименованы. Я лично не хочу использовать его сейчас, пока изменения не будут завершены. Раньше я пробовал предварительную версию RC2, но теперь у меня нет ни одного работающего проекта MVC Core, который можно было бы даже скомпилировать. Поэтому я не могу помочь вам с BindingContext. - person Oleg; 08.02.2016
comment
@ user2736022: Я не могу скомпилировать код, использующий предварительный RC2, но кажется, что раньше можно было получить OutputFormatters из HttpContext.RequestServices.GetRequiredService<IOptions<MvcOptions>>().Value.OutputFormatters вместо BindingContext. Таким образом, var f = HttpContext.RequestServices.GetRequiredService<IOptions<MvcOptions>>().Value.OutputFormatters.OfType<JsonOutputFormatter>().Single(); может работать. - person Oleg; 08.02.2016
comment
Это не работает. если вы измените свой пример, чтобы иметь 2 метода, первый включает нуль/интервал, а второй исключает его. Доступ к первому методу, все в порядке, доступ ко второму, все в порядке. Вернитесь к первому, и настройки были перезаписаны - person Gillardo; 08.02.2016
comment
@ user2736022: Да, конечно. Вы должны прочитать предыдущие комментарии тоже. Ваш вопрос был как получить доступ к SerializerSettings, чтобы иметь возможность там изменить. Я показал вам, как получить доступ к настройкам и изменить их динамически. MVC содержит один экземпляр настроек, поэтому вы должны устанавливать (сбрасывать) свойства в каждом вашем контроллере/действии контроллера. - person Oleg; 08.02.2016