我似乎无法在Azure移动应用程序中自定义JSON序列化。
为了避免自己代码的复杂性,我从头开始设置了一个新项目。Visual Studio社区2015更新2,Azure应用程序服务工具v2.9(如果重要的话)。新项目,Visual C#,云,Azure移动应用程序。
在App_StartStartup.MobileApp.cs
中,这是模板中的内容:
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);
}
这就是我尝试过的:
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);
...
}
运行这个并访问http://localhost:53370/tables/TodoItem
,json没有缩进,并且有一堆false
字段,这表明设置被忽略了。
那么,我如何更改序列化程序设置,以便在该配置中尊重它们呢?从每个控制器返回一个带有我自己自定义设置的JsonResult
是可行的,但只允许我发送200 OK
状态(我必须跳过重重关卡才能返回一个尊重我设置的201 Created
)。
Azure Mobile Apps当前似乎不尊重在OWIN启动类中设置的序列化程序设置。我不知道它们是被覆盖还是没有被使用,但它们没有被控制器拾取。
作为一种变通方法,您似乎可以从控制器内部设置串行器设置:
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
};
}
}
Configuration
属性尚未在构造函数中设置,因此不能将SetSerializerSettings()
放在那里,因为它会被覆盖。只要进程在运行,这些设置似乎就会持续存在,所以这有点多余,但它似乎确实完成了任务。我希望有人能来提供正确的方法!
在这上面花了很多时间之后,我认为您能做的最好的事情就是创建一个MobileAppControllerConfigProvider
并将其传递给WithMobileAppControllerConfigProvider
。
这就是我正在做的,让所有控制器尊重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);
和:
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;
}
}
DevNoob的答案是,OWIN启动类中的序列化程序设置不起作用。当设置在每个控制器类的Initialize(HttpControllerContext controllerContext)方法中时,它就可以工作。在我的情况下,我有自参考问题,所以我解决了这样的问题:
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);
}
....
}
我建议小心这里提供的答案。在我们在iOS应用程序中使用离线同步表之前,一切都很好。
在我的案例中,它们在没有任何正当理由的情况下崩溃,很可能它们需要一些非默认的序列化程序设置才能正常工作。我用了努诺·克鲁塞斯的溶液,当我恢复时,一切都恢复了正常。