Często w pracy z Windows Communication Foundation chcemy udostepnić w kontrakcie danych naszej usługi pewien typ wyliczeniowy. Aby to zrobić wykorzystujemy atrybut [EnumMember], który umieszczamy nad każdą z wartości tego typu. Posłużę się przykładem, który przygotowałem do prezentacji SOA + .NET = WCF, którą prowadziłem na ostatnim spotkaniu TGD.NET.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
using System.Runtime.Serialization;
 
namespace CarRentalServices.DataTransferObjects
{
    [DataContract(Namespace="CarRentalServices.Types")]
    public enum CarMake
    {
        [EnumMember]
        Ford,
 
        [EnumMember]
        Opel,
 
        [EnumMember]
        Peugeot,
 
        [EnumMember]
        Dodge,
 
        [EnumMember]
        Chrysler
    }
}

Podczas prezentacji zastanawialiśmy się co się stanie, jeżeli w typie wyliczeniowym nie użyjemy tego atrybutu? Niestety nie było na to czasu podczas spotkania, jednakże postanowiłem to sprawdzić. Otóż okazuje się, że klient zinterpretuje go jako string, ale próba pobrania obiektu, który zawiera w sobie pole tego typu wygeneruje błąd nieoczekiwanego zakmnięcia połączenia (“The underlying connection was closed: The connection was closed unexpectedly.”). Wystąpi on nawet jeżeli po stronie klienta nie będziemy korzystać z tego typu – nie ustawimy wartości pól o rozpatrywanym typie wyliczeniowym. Dlaczego? Ponieważ typ wyliczeniowy jest inicjowany poprzez pierwszą wartość z listy – w tym przypadku będzie to Ford. Bład powstaje natomiast przez to, że bez atrybutu nad wartościami typu wyliczeniowego zmienia się definicja kontraktu i jednocześnie powstają nieścisłości po stronie klienta podczas desierializacji wysłanej przez serwis odpowiedzi. Jeżeli klient nie potrafi zinterpretować odpowiedzi wówczas zamyka połączenie.

Błąd ten nie powstaje jeżeli atrybutem [EnumMember] oznaczymy tylko te wartości, które mogą być przesłane do klienta, których użyjemy w komunikacji. Wszystkie pozostałe mogą pozostać bez niego.

Wnioski:

1. Typ wyliczeniowy bez wartości oznaczonych atrybutem [EnumMember] powoduje błędy przy korzystaniu z uslugi.
2. Błąd, który nic nie mówi może oznaczać błędną definicję kontraktu danych.