Azure移动应用程序自定义json序列化

时间:2016-04-29 15:08:53

标签: c# azure json.net

我似乎无法在Azure移动应用程序中自定义JSON序列化。

为了避免我自己的代码的复杂性,我从头开始设置一个新项目。 Visual Studio社区2015 Update 2,Azure App Service Tools v2.9(如果重要)。新项目,Visual C#,云,Azure移动应用程序。

App_Start\Startup.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)。

4 个答案:

答案 0 :(得分:3)

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()放在那里,因为它会被覆盖。只要进程正在运行,这些设置似乎就会持续存在,所以这有点多余,但它似乎确实完成了工作。我希望有人可以来并提供正确的方法来做到这一点!

答案 1 :(得分:2)

在花了很多时间之后,我认为你能做的最好的事情是创建一个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;
    }
}

答案 2 :(得分:1)

作为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);
    }

....

}

答案 3 :(得分:0)

我建议小心这里提供的答案。在iOS应用程序中使用脱机同步表之前,一切都很好。

在我的情况下,他们没有任何理由崩溃,很可能他们需要一些非默认的序列化设置才能正常运行。我使用了Nuno Cruses的解决方案,当我恢复时,所有人都恢复正常。