Do you use enum types in your WCF web services?

前端 未结 9 1870
臣服心动
臣服心动 2020-11-27 06:06

I\'ve heard some people saying that enums are evil and shouldn\'t be used in web services because of the mismatches that could occur between the server and the client if som

相关标签:
9条回答
  • 2020-11-27 06:10

    Here's an approach. Maybe it's cumbersome. I just really dislike not being able to use enums.

    It gracefully handles deserialization of an unrecognized value, returning the default value instead. The default value would need to be safe - either an acceptable fallback or something that the application could recognize as exceptional. (Like "Unspecified.")

    The extensions prevent having to null-check before comparing.

    [DataContract]
    public class EnumValue<T> where T : struct
    {
        [DataMember]
        private string _raw = string.Empty;
    
        [IgnoreDataMember]
        private bool _parsed;
    
        [IgnoreDataMember]
        private T _parsedValue;
    
        public EnumValue()
        {
            Set(default(T));
        }
    
        public EnumValue(T value)
        {
            Set(value);
        }
    
        internal T Value
        {
            get
            {
                if (_parsed) return _parsedValue;
                if (!Enum.TryParse<T>(_raw, out _parsedValue))
                {
                    _parsedValue = default(T);
                }
                _parsed = true;
                return _parsedValue;
            }
        }
    
        public void Set(T value)
        {
            _raw = value.ToString();
            _parsedValue = value;
            _parsed = true;
        }
    }
    
    public static class EnumValueExtensions
    {
        public static T GetValue<T>(this EnumValue<T> enumValue) where T : struct
        {
            return enumValue == null ? default(T) : enumValue.Value;
        }
    
        public static bool EqualsValue<T>(this EnumValue<T> enumValue, T compareTo) where T : struct
        {
            return (enumValue.GetValue().Equals(compareTo));
        }
    }
    
    0 讨论(0)
  • 2020-11-27 06:12

    I've used enums in my WCF based services without any problems. The possible issues you mention are definitely things to consider, although if you make sure you apply enums in fairly static situations you probably won't have much trouble.

    0 讨论(0)
  • 2020-11-27 06:15

    The reason people recommend to avoid enums in webservices is because they create subtle backwards compatible problems.

    The same applies to regular enums but in web services the problem is even more clear specially in .NET-generated proxies (see below).

    • If the enumerate is input only you have no issues.
    • If the enumerate can be an out parameter then if you add a new element and you return it, old clients could have problems:
      • If the client is using a .NET-generated proxy it will break before the caller can handle it (in the deserialization)
      • Even if the generated code for the proxy supported the change (for example if it maps the enumerate to a string) the user code in the client may not process properly the new unexpected value (it could easily be a never executed path)

    By defining the parameter as a string you signal the user of your API that the value may change in the future. Even if you think that the value will never change is a good practice to be ready.

    There is a good post by Dare Obasanjo on this topic.

    0 讨论(0)
  • 2020-11-27 06:16

    I have used enums in WCF, also in interoperability scenarios. If you control both sides of the service, it is easier to work with. If you only control one side of the service, you need to look out for the issues that you mentioned.

    Enums are so much better that string variables, or what else you might choose to use. Using strings instead of enums is an anti pattern called "loosey Goosey" in SOA.

    0 讨论(0)
  • 2020-11-27 06:17

    Enums in WSDLs must be considered as a concern for maintenance.

    Adding or removing an enumeration value is(should be!) a trigger for a major update of the interface. If the enum is an output value, then you necessarily need to define a new version of the WSDL through a new URI, so to keep current clients from breaking the established contract("what if they receive on of these new, unexpected values in return?") If the enum is an input value, you could consider this as a minor update("since current clients won't need to know about this new value"), but then, the only way for those clients to benefit from the addition of this new option/functionnality (you added this new enum value for a reason, right?) would be to ask them to switch, later or sooner, to the new version of the interface.

    And this doesn't have to do with the functionnal meaning of the enum, I think.

    Stay on the best practices side, and you'll be safe.

    0 讨论(0)
  • 2020-11-27 06:17

    Using anything else but enums does not solve your compatibility issue, it only hides it. Assume you use an int to replace an enum. Did you really solve the compatibility issue or just disguised it until the client runtime hits the unknown value?

    However, one thing is worth mentioning: WCF proxies do not recreate explicitly set enum numeric values. If the enum is declared with "holes", like

    enum ErrorCodes
    {
      OK = 0,
      GenericError = 100,
      SomeOtherError = 101,
    }
    

    the client side representation will be like this

    enum ErrorCodes
    {
      OK,
      GenericError,
      SomeOtherError,
    }
    

    ... which on the client results in (int)ErrorCodes.GenericError being 1.

    You'll have syntactic equivalence, but not numeric equivalence.

    0 讨论(0)
提交回复
热议问题