2013-03-12 2 views
9

Ho difficoltà a capire come convertire un valore Enum nel nome corrispondente. Il mio modello è la seguente:Ottenere un Enum da visualizzare sul lato client

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 
} 

risultato di un campione da API .net:

[ 
    { 
    $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 
    } 
] 

Quindi, in questo esempio, ho bisogno di ottenere catalogo per i risultati [0] .ItemRule & Prezzo A per i risultati [0] .PriceRule. Come posso realizzare questo in BreezeJS ??

risposta

4

Ci sarà una nuova release nei prossimi giorni dove noi "cambiamo" il comportamento enum di brezza (cioè spezza il codice esistente rispetto alle enumerazioni). Nella nuova versione le enumerazioni vengono serializzate e interrogate dai loro nomi .NET invece che come numeri interi. Pubblicherò di nuovo qui quando uscirà la nuova versione.

+0

Durante l'analisi di questo problema, ho scoperto che sebbene i metadati Enum fossero presenti nella chiamata dell'API/Metadata, questa è stata eliminata dal lato client da Breeze. Grazie per l'aggiornamento Jay. –

+1

Breeze v 1.2.1 è stato appena rilasciato e le enumerazioni sono ora interrogabili come stringhe e vengono materializzate in questo modo. –

+0

Per inciso, l'ho aggiornato qualche minuto fa ...;) Questa versione risolve il problema, Grazie ... –

7

Questo è facile da fare in API Web ASP.NET, perché è una funzionalità predefinita nel serializzatore JSON predefinito (Json.NET).

Per vedere le stringhe invece di numeri enum in JSON, basta aggiungere un'istanza di StringEnumConverter alle impostazioni serializzatore JSON durante applicazione init:

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

UPDATE: Sì, avete ragione, questo non è aiutare con Breeze .js. Ok, puoi comunque fare un po 'di magia per far funzionare le enigmi come stringhe (mentre la nuova versione con la correzione non viene rilasciata).

Creare un numero personalizzato ContextProvider che aggiorna tutti i valori di enum intero nei metadati delle stringhe. Eccolo:

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

e usarlo al posto del EFContextProvider nel controller di API Web:

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

Questo funziona bene per me con la versione corrente Breeze.js (1.1.3), anche se io porto 't controllato altri scenari, come la convalida ...

UPDATE:. per fissare la convalida, il tipo di dati cambiamento per le enumerazioni in brezza [min | debug] .js, manualmente (DataType.fromEdmDataType funzione, dt = DataType.String; per l'e num) o sostituire la funzione predefinita durante l'applicazione 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; 
}; 

sporchi, hack sporco, lo so ... Ma questa è la soluzione che ho trovato

+0

Ho paura che non ha avuto alcun effetto sulla chiamata di ritorno API. Ciò potrebbe essere dovuto al fatto che il controller Breeze gestisce le chiamate API e ... –

+0

@Van Dame, ho aggiornato la risposta con la soluzione per la versione corrente di Breeze.js – whyleee

+0

Grazie per le correzioni, ma sembra che questa correzione non sia necessaria in un paio di giorni e preferirei evitare qualsiasi hack ... :) –