让Enum在客户端显示

时间:2013-03-12 12:11:08

标签: asp.net-web-api breeze

我很难理解如何将Enum值转换为它的相应名称。我的模型如下:

public class CatalogRule
{
  public int ID { get; set; }
  [Display(Name = "Catalog"), Required]
  public int CatalogID { get; set; }
  [Display(Name = "Item Rule"), Required]
  public ItemType ItemRule { get; set; }
  public string Items { get; set; }
  [Display(Name = "Price Rule"), Required]
  public PriceType PriceRule { get; set; }
  [Display(Name = "Value"), Column(TypeName = "MONEY")]
  public decimal PriceValue { get; set; }
  [Display(Name = "Exclusive?")]
  public bool Exclude { get; set; }
}

public enum ItemType
{
  Catalog,
  Category,
  Group,
  Item
}

public enum PriceType
{
  Catalog,
  Price_A,
  Price_B,
  Price_C
}

来自.net API的示例结果:

[
  {
    $id: "1",
    $type: "XYZ.CMgr.Models.CatalogRule, XYZ.CMgr",
    ID: 1,
    CatalogID: 501981,
    ItemRule: 0,
    Items: "198",
    PriceRule: 1,
    PriceValue: 0.5,
    Exclude: false
  },
  {
    $id: "2",
    $type: "XYZ.CMgr.Models.CatalogRule, XYZ.CMgr",
    ID: 2,
    CatalogID: 501981,
    ItemRule: 2,
    Items: "9899",
    PriceRule: 2,
    PriceValue: 10.45,
    Exclude: false
  }
]

所以在这个例子中,我需要得到 Catalog for results [0] .ItemRule&结果[0] .PriceRule的价格A 。我怎样才能在BreezeJS中实现这个目标?

2 个答案:

答案 0 :(得分:7)

这在ASP.NET Web API中很容易实现,因为它是默认JSON序列化程序(Json.NET)中的开箱即用功能。

要在JSON中查看字符串而不是枚举数字,只需在app init期间将StringEnumConverter的实例添加到JSON序列化程序设置:

var jsonFormatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
jsonFormatter.SerializerSettings.Converters.Add(new Newtonsoft.Json.Converters.StringEnumConverter());

更新:是的,你没错,这对Breeze.js没有帮助。好吧,无论如何,你可以做一些魔术让枚举像字符串一样工作(而新版本的修复程序没有发布)。

创建自定义ContextProvider,将元数据中的所有整数枚举值更新为字符串。这是:

public class StringEnumEFContextProvider<T> : EFContextProvider<T>
    where T : class, new()
{
    protected override string BuildJsonMetadata()
    {
        XDocument xDoc;
        if (Context is DbContext)
        {
            xDoc = GetCsdlFromDbContext(Context);
        }
        else
        {
            xDoc = GetCsdlFromObjectContext(Context);
        }

        var schemaNs = "http://schemas.microsoft.com/ado/2009/11/edm";

        foreach (var enumType in xDoc.Descendants(XName.Get("EnumType", schemaNs)))
        {
            foreach (var member in enumType.Elements(XName.Get("Member", schemaNs)))
            {
                member.Attribute("Value").Value = member.Attribute("Name").Value;
            }
        }

        return CsdlToJson(xDoc);
    }
}

在Web API控制器中使用它代替EFContextProvider

private EFContextProvider<BreezeSampleContext> _contextProvider =
        new StringEnumEFContextProvider<BreezeSampleContext>();

对于我当前的Breeze.js版本(1.1.3),这很有用,虽然我还没有检查过其他场景,比如验证......

更新要修复验证,请在breeze中更改枚举的数据类型。[min | debug] .js,手动(DataType.fromEdmDataType函数,dt = DataType.String;表示枚举)或在app init期间替换默认功能:

breeze.DataType.fromEdmDataType = function (typeName) {
    var dt = null;
    var parts = typeName.split(".");
    if (parts.length > 1) {
        var simpleName = parts[1];
        if (simpleName === "image") {
            // hack
            dt = DataType.Byte;
        } else if (parts.length == 2) {
            dt = DataType.fromName(simpleName);
            if (!dt) {
                if (simpleName === "DateTimeOffset") {
                    dt = DataType.DateTime;
                } else {
                    dt = DataType.Undefined;
                }
            }
        } else {
            // enum
            dt = DataType.String; // THIS IS A FIX!
        }
    }

    return dt;
};

肮脏,肮脏的黑客,我知道......但那是我找到的解决方案

答案 1 :(得分:4)

在接下来的几天里会有一个新版本,我们会“改变”微风的枚举行为(即打破关于枚举的现有代码)。在新版本中,枚举按其.NET名称而不是整数进行序列化和查询。我将在新版本发布时回复此处。