Nuno Cruces Nuno Cruces - 3 months ago 26
C# Question

Azure Mobile App customizing json serialization

I can't seem to be able to customize JSON serialization in an Azure Mobile App.

To avoid the complexity of my own code, I setup a new project from scratch. Visual Studio Community 2015 Update 2, Azure App Service Tools v2.9 (if that matters). New Project, Visual C#, Cloud, Azure Mobile App.

In

App_Start\Startup.MobileApp.cs
this is what's in the template:

public static void ConfigureMobileApp(IAppBuilder app)
{
HttpConfiguration config = new HttpConfiguration();

new MobileAppConfiguration()
.UseDefaultConfiguration()
.ApplyTo(config);

// Use Entity Framework Code First to create database tables based on your DbContext
Database.SetInitializer(new MobileServiceInitializer());

MobileAppSettingsDictionary settings = config.GetMobileAppSettingsProvider().GetMobileAppSettings();

if (string.IsNullOrEmpty(settings.HostName))
{
app.UseAppServiceAuthentication(new AppServiceAuthenticationOptions
{
// This middleware is intended to be used locally for debugging. By default, HostName will
// only have a value when running in an App Service application.
SigningKey = ConfigurationManager.AppSettings["SigningKey"],
ValidAudiences = new[] { ConfigurationManager.AppSettings["ValidAudience"] },
ValidIssuers = new[] { ConfigurationManager.AppSettings["ValidIssuer"] },
TokenHandler = config.GetAppServiceTokenHandler()
});
}

app.UseWebApi(config);
}


This is what I have tried:

public static void ConfigureMobileApp(IAppBuilder app)
{
JsonConvert.DefaultSettings = () => new JsonSerializerSettings()
{
Converters = { new StringEnumConverter { CamelCaseText = true }, },
ContractResolver = new CamelCasePropertyNamesContractResolver { IgnoreSerializableAttribute = true },
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.Indented
};

HttpConfiguration config = new HttpConfiguration();
config.Formatters.JsonFormatter.SerializerSettings = JsonConvert.DefaultSettings();

new MobileAppConfiguration()
.UseDefaultConfiguration()
.ApplyTo(config);

...
}


Running this and accessing
http://localhost:53370/tables/TodoItem
, json is not indented, and has a bunch of
false
fields, which shows settings are being ignored.

So how can I change serializer settings so that they will be respected in this configuration? Returning a
JsonResult
with my own custom settings from every controller works, but only allows me to send
200 OK
status (I have to jump through hoops to return a
201 Created
that respects my settings).

Answer

After spending a lot of time on this, I think the best you can do is create a MobileAppControllerConfigProvider and pass it to WithMobileAppControllerConfigProvider.

This is what I'm doing, to get all controllers to respect JsonConvert.DefaultSettings:

JsonConvert.DefaultSettings = () => new JsonSerializerSettings { /* something */ };

var provider = new MobileConfigProvider();

var config = new HttpConfiguration();
config.MapHttpAttributeRoutes();
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.JsonFormatter.UseDataContractJsonSerializer = false;
config.Formatters.JsonFormatter.SerializerSettings = provider.Settings;

new MobileAppConfiguration().
    MapApiControllers().
    AddMobileAppHomeController().
    AddPushNotifications().
    WithMobileAppControllerConfigProvider(provider).
    ApplyTo(config);

And:

sealed class MobileConfigProvider : MobileAppControllerConfigProvider
{
    readonly Lazy<JsonSerializerSettings> settings = new Lazy<JsonSerializerSettings>(JsonConvert.DefaultSettings);

    public JsonSerializerSettings Settings => settings.Value;

    public override void Configure(HttpControllerSettings controllerSettings, HttpControllerDescriptor controllerDescriptor)
    {
        base.Configure(controllerSettings, controllerDescriptor);
        controllerSettings.Formatters.JsonFormatter.SerializerSettings = Settings;
    }
}
Comments