问题
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).
回答1:
It appears that Azure Mobile Apps aren't currently respecting serializer settings that are set in the OWIN startup class. I don't know if they're getting overwritten or just not used but they aren't getting picked up by the controllers.
As a workaround, it seems you can set the serializer settings from inside the controllers:
public class SomeController : ApiController
{
public object Get()
{
SetSerializerSettings();
Do your logic....
}
private void SetSerializerSettings()
{
this.Configuration.Formatters.JsonFormatter.SerializerSettings =
new JsonSerializerSettings
{
Converters = { new StringEnumConverter { CamelCaseText = true }, },
ContractResolver =
new CamelCasePropertyNamesContractResolver { IgnoreSerializableAttribute = true },
DefaultValueHandling = DefaultValueHandling.Ignore,
NullValueHandling = NullValueHandling.Ignore,
Formatting = Formatting.Indented
};
}
}
The Configuration
property hasn't been set yet in the constructor so you can't put the SetSerializerSettings()
there because it gets overwritten. And these settings seem to persist as long as the process is running, so this is a bit redundant, but it does seem to get the job done. I hope someone can come along and provide the right way to do it!
回答2:
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;
}
}
回答3:
As DevNoob's answer, the serializer settings in the OWIN startup class are not working. When the setting is in the Initialize(HttpControllerContext controllerContext) method in each contoller class, it works. In my case, I have the self referencing problem, so I have solved the problem like this:
public class CustomerController : TableController<Customer>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
controllerContext.Configuration.Formatters.JsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore;
base.Initialize(controllerContext);
MyMobileAppContext context = new MyMobileAppContext();
DomainManager = new EntityDomainManager<Customer>(context, Request);
}
....
}
回答4:
I suggest being careful with the answers provided here. Everything is fine until we use offline sync tables in iOS apps.
In my case they crashed without any good reason, most likely they need some non-default serializer setting to function properly. I used Nuno Cruses's solution and when I reverted all got back to normal.
来源:https://stackoverflow.com/questions/36941834/azure-mobile-app-customizing-json-serialization