Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using enums in WCF Data Services

I'm trying to manually build a WCF Data Service using a POCO data model and I cannot figure out how to properly expose enum values. Assuming a simple model like:

public class Order
{
   public int ID {get; set;}
   public string Description {get; set;}
   public OrderStatus Status {get; set;}
}

public enum OrderStatus
{
   New,
   InProcess,
   Complete
}

How do you expose the valuable information in the OrderStatus property via the OData WCF Data Service?

If you do nothing, the Data Service generates a runtime error (enum is invalid property). The only answer I've seen that at least resolves the error is to mark the enum property as Ignored, such as:

[System.Data.Services.IgnoreProperties("Status")]
public class Order ...

This works, but it forces you to "omit" valuable information from the service layer. Are there other options for working with enum values in WCF Data Services?

EDIT: Please notice this is WCF Data Services (aka Astoria). This is not raw WCF Services, in which case the answers are more clear.

like image 515
Todd Avatar asked Aug 25 '10 21:08

Todd


4 Answers

Enums are currently not supported in WCF Data Services (the OData protocol doesn't support them either). The typical workaround is to use string and constant values, or integer and constant values.

like image 70
Vitek Karas MSFT Avatar answered Oct 24 '22 10:10

Vitek Karas MSFT


Maybe we can "cheat" it with the below workaround:

[System.Data.Services.IgnoreProperties("Status")]
public class Order
{
   public int ID {get; set;}
   public string Description {get; set;}
   public OrderStatus Status {get; set;}
   public int StatusValue
   {
      get
      {
           return (int)this.Status;
      }
      set
      {
          // Add validation here
          this.Status = (OrderStatus)value;
      } 
   }
}

public enum OrderStatus
{
   New,
   InProcess,
   Complete
}
like image 28
Boris Modylevsky Avatar answered Oct 24 '22 10:10

Boris Modylevsky


As follow-up, the "wrapper" approach is ultimately what worked. Essentially, a small class is written to wrap the enum and return primitive int values in the Data Service:

[IgnoreProperties("EnumValue")]
public class OrderStatusWrapper
{
    private OrderStatus _t;

    public int Value
    {
        get{ return (int)_t; }
        set { _t = (OrderStatus)value; }
    }

    public OrderStatus EnumValue
    {
        get { return _t; }
        set { _t = value; }
    }

    public static implicit operator OrderStatusWrapper(OrderStatus r)
    {
        return new OrderStatusWrapper { EnumValue = r };
    }

    public static implicit operator OrderStatus(OrderStatusWrapper rw)
    {
        if (rw == null)
            return OrderStatus.Unresolved;
        else
            return rw.EnumValue;
    }
}  

This was largely based on the advice given for working around EF4's enum limits:

http://blogs.msdn.com/b/alexj/archive/2009/06/05/tip-23-how-to-fake-enums-in-ef-4.aspx

Hope this technique helps others that follow.

like image 41
Todd Avatar answered Oct 24 '22 09:10

Todd


Assuming DataContract Serialization, like so:

[DataContract]
public class Order
{
   [DataMember]
   public int ID {get; set;}
   [DataMember]
   public string Description {get; set;}
   [DataMember]
   public OrderStatus Status {get; set;}
}

[DataContract]
public enum OrderStatus
{
    [EnumMember]
    New,
    [EnumMember]
    InProcess,
    [EnumMember]   
    Complete
}
like image 43
StuartLC Avatar answered Oct 24 '22 11:10

StuartLC