11

For the moment part, i would like to exclude null values from my api response, so in my startup.cs file, i have this.

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

But is it possible to state that on 1 or more controllers, i actually want to include NULL values??

Gillardo
  • 9,518
  • 18
  • 73
  • 141

2 Answers2

5

One option is to create custom Json result type, as described in this question: Using JSON.NET as the default JSON serializer in ASP.NET MVC 3 - is it possible?. Then you can have bool var on base controller and use it do disable null's when using custom Json result or even pass option directly:

return Json(data, ignoreNulls: true); 
Community
  • 1
  • 1
csharpfolk
  • 4,124
  • 25
  • 31
-1

You can get JsonOutputFormatter from the BindingContext.OutputFormatters inside of the code of your controller. It allows you dynamically change the SerializerSettings.

Try to include using Newtonsoft.Json; in the controller code and to do the following inside of your controller action:

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;
}

I included Formatting = Formatting.Indented just for my tests only, because one see the results immediately. You don't need it of cause.

UPDATED: I created the demo project using MVC Web Application with no Authentication. Then I added in HomeController the following metod

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

    return testResult;
}

and changed the Launch URL of the project to Home/TestMethod and started the demo. I could see

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

You don't need to add any additional using statements to use the code which I posted initially (one need just have the standard using Microsoft.AspNet.Mvc; and using System.Linq;), but the code could be more readable if you would have using Microsoft.AspNet.Mvc.Formatters; and using Newtonsoft.Json;. I added the using statements for Microsoft.AspNet.Mvc.Formatters and Newtonsoft.Json and modified the code to the following

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;
}

The output results looks now as following

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

The standard code use "Newtonsoft.Json" in version 6.0.6. We can add "Newtonsoft.Json": "8.0.2" in dependencies to use the latest version of Newtonsoft.Json. See the problem with resolving of indirect dependencies which I reported in the issue and which is still opened.

You can download the test project from here.

Oleg
  • 220,925
  • 34
  • 403
  • 798
  • 2
    I cannot seem to see BindingContext from within my controller method? it this for ASPNET5? – Gillardo Feb 05 '16 at 09:25
  • @user2736022: Yes of cause. Inside of every controller action you have `this` with properties `HttpContext`, `BindingContext` and so on. You can just type `this.` inside of your method. After typing `.` intellysense will show you all properties of `this` including `BindingContext`. C# allows (recommends) you to write `BindingContext` instead of `this.BindingContext`. – Oleg Feb 05 '16 at 10:02
  • Can you check with namespace it is within? It says its my controller does not contain a definition for BindingContext – Gillardo Feb 05 '16 at 10:27
  • @user2736022: `BindingContext` is the property of `Controller`. Every MVC6 Controller should be class which e `using Microsoft.AspNet.Mvc;`. I described all steps in **UPDATED** part of my answer and uploaded [here](http://www.ok-soft-gmbh.com/ForStackOverflow/BindingContextTest.zip) the test Visual Studio 2015 project, which demonstrates the code. – Oleg Feb 05 '16 at 11:12
  • 1
    MVC Core reuses the same instance of JsonOutputFormatter across all controllers. Changing the serializer setting inside of a controller is nearly identical to modifying it at startup. – Pranav Feb 05 '16 at 17:37
  • @Pranav: I think so too. Thus one should set the *variable* settings in *all* controllers. One can define derived class from `Controller` class and use it in all controllers. I want to show the way how one can change the `SerializerSettings` **dynamically**. All other code should be written corresponds to exact requirements. – Oleg Feb 05 '16 at 17:49
  • I am using rc2, this doesnt seem to exist? rc1 has BindingContext but not rc2... – Gillardo Feb 07 '16 at 22:27
  • @user2736022: You can save a lot of time if you provides correct information initially. RC2 is now in renaming process. A lot of packages, methods, internal structures are renamed. I personally don't want to use it now till the changes will be finished. I tried preliminary version of RC2 before, but now I don't have any working MVC Core project which can be even compiled. So I can't help you with BindingContext. – Oleg Feb 08 '16 at 00:05
  • @user2736022: I can't compile any code which use preliminary RC2, but it seems that one can get `OutputFormatters` from `HttpContext.RequestServices.GetRequiredService>().Value.OutputFormatters` instead of `BindingContext` before. Thus `var f = HttpContext.RequestServices.GetRequiredService>().Value.OutputFormatters.OfType().Single();` could work. – Oleg Feb 08 '16 at 01:30
  • This does not work. if you change your example, to have 2 methods, the first includes null/spacing, then second excludes it. Access the first method, its ok, access the second, its ok. Go back to the first and the settings have been overwritten – Gillardo Feb 08 '16 at 09:31
  • @user2736022: Yes of cause. You should read previous comments too. You questions was **how to access to `SerializerSettings` to be able to change there**. I've shown you how the access the settings and to change there dynamically. MVC hold **one instance** of the settings, thus you should set (reset) the properties in every your controller/controller action. – Oleg Feb 08 '16 at 09:55