【问题标题】:Serialize type safe enums for web api response?为 Web api 响应序列化类型安全枚举?
【发布时间】:2016-06-27 09:15:49
【问题描述】:

我无法从我的 web api 以正确的方式将我的模型发回。

我收到这条异常消息:The 'ObjectContent1' type failed to serialize the response body for content type 'application/xml; charset=utf-8'.

这是我的模型的样子:

public class ValidationCreditReport
    {
        public int companyId { get; set; }
        public string companyName { get; set; }
        public CreditRecommendation recommendationSecure { get; set; }
        public CreditRecommendation recommendationUnsecure { get; set; }
        public CreditOutlook creditOutlook { get; set; }
        public IndicativeRating indicativeCorporateRating { get; set; }
        public IndicativeRating indicativeSeniorUnsecured { get; set; }
        public IndicativeRating indicativeSeniorSecured { get; set; }
        public Currency currency { get; set; }

        public override string ToString()
        {
            return companyId + " " + companyName + " " + recommendationSecure.Name + " " + recommendationUnsecure.Name + " " +
                creditOutlook.Name + " " + indicativeCorporateRating.Name + " " + indicativeSeniorSecured.Name + " " + indicativeSeniorSecured.Name + " " + currency.Name;
        }
    }

这是我的枚举类型:

public class CreditRecommendation
    { 
        public string Name{ get; set; }
        private CreditRecommendation (string name)
        {
            Name = name;
        }

        public static CreditRecommendation Buy = new CreditRecommendation("Buy");
        public static CreditRecommendation Sell = new CreditRecommendation("Sell");
        public static CreditRecommendation Hold = new CreditRecommendation("Hold");
        public static CreditRecommendation NoRating = new CreditRecommendation("NoRating");

        public static CreditRecommendation FromName(string name)
        {
            switch (name)
            {
                case "Buy":
                    return Buy;
                case "Sell":
                    return Sell;
                case "Hold":
                    return Hold;
                case "NoRating":
                    return NoRating;
                default:
                    throw new ArgumentException("Provided name invalid: " + name);
            }
        }
    };

其余枚举模型看起来相同,但只是名称不同,并且在它们各自的 switch case 下或多或少有一些选项。

我现在一直在尝试做的是编写我自己的 toString() 函数,该函数调用枚举 .name 并将它们附加到普通字符串中。我正在考虑将这个字符串硬编码成一个 json 字符串。但我认为这不是解决这个问题和处理这个问题的正确方法。

最后这里是我实际尝试发回数据的地方:

public HttpResponseMessage GetLastPublishedData(String companyName)
        {
            using (SqlConnection connection = CreateSqlConnection())
            {
                using (var transaction = connection.BeginTransaction())
                {
                    try
                    {
                        var service = CreateCreditService(connection, transaction);
                        var msg = service.ValidateAndPrepareCreditReport(companyName);
                        var result = CreateValidationCreditReport(msg);
                        transaction.Commit();
                        return this.Request.CreateResponse<ValidationCreditReport>(HttpStatusCode.OK, result);
                    }
                    catch{
                        transaction.Rollback();
                        throw;
                    }

                }
            }
        }

我已经浏览了整个项目,问题似乎源于我的枚举并且它们无法序列化。

非常感谢任何和所有帮助。

【问题讨论】:

  • 您在谈论枚举,但您正在向我们展示课程。我不明白你的方法,你为什么使用一个类来表示一个简单的枚举?
  • @FedericoDipuma 我从一位已辞职的前同事那里继承了其中的一些代码。我不是 100% 确定所有的设计选择,但我正在尽力理解它们。
  • @Gurkang - 你标记了这个问题json 但异常错误消息提到了 XML。你用的是哪个?您正在尝试进行单例序列化,它在每个序列化程序中的工作方式都不同(或者对于XmlSerializer 根本没有,请参阅XmlSerialization with a singleton

标签: c# json serialization asp.net-web-api enums


【解决方案1】:

据我所知,您的代码需要重构。对枚举类型使用类确实是一个糟糕的设计选择,没有任何优势。

重构您的类型并改用简单的枚举:

public enum CreditRecommendation {
    Buy,
    Sell,
    Hold,
    NoRating
}

然后,如果您希望它们在 JSON 响应中被序列化为字符串,只需将正确的转换器添加到 Web API JSON 序列化程序实例:

 config.Formatters.JsonFormatter.SerializerSettings.Converters.Add
            (new Newtonsoft.Json.Converters.StringEnumConverter());

假设 config 是您的 HttpConfiguration 实例。

【讨论】:

  • 感谢您的意见。我通过为每个枚举类添加一个空的构造函数来使序列化工作。如果我们应该重构或者我们应该如何进行,我会和我的老板谈谈!
【解决方案2】:

我通过为每个枚举类添加一个空的构造函数来使其工作。

因此对于 CreditRecommendation 类,它现在看起来像这样:

public CreditRecommendation() { }

【讨论】:

  • 虽然这行得通,但它违背了模式的目的,即由于私有构造函数而无法使用无效值启动类。我认为费德里科的结论是正确的;出于序列化目的,这种模式不是您想要的;要么将其切换出来,要么将其映射到更适合的模型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-10
相关资源
最近更新 更多