2013-07-24 12 views
5

W scenariuszu, w którym usługa WCF zwraca wartość DataContract z elementem wyliczającym, który ma niepoprawną wartość (int nieobecny w typie wyliczenia), zgłaszany wyjątek po stronie klienta jest The underlying connection was closed: The connection was closed unexpectedly.
Co dziwne, ten wyjątek jest wyzwalany, ponieważ DataContractSerializer nie może serializować na serwerze połączenia.Błąd wcześnie lub wyraźnie rzucać, gdy wyliczenie nie może być przekształcone do postaci szeregowej

wolałbym coś bardziej użyteczne rzucony na mnie i ważniejsze wcześniej, w czasie wykonywania na serverside, ale może to ostrzeżenie kompilatora ...

WCF Umowa serwisowa

[ServiceContract] 
    public interface IDtoService 
    { 
     [OperationContract] 
     MyDto GetData(int value); 
    } 

    public enum Rating 
    { 
     None = 0, 
     NotSet = 1, 
     Somevalue = 34 
    } 

    [DataContract] 
    public class MyDto 
    { 
     Rating _rate; 

     [DataMember] 
     public Rating Rating 
     { 
      get { return _rate; } 
      set 
      { 
       _rate = value; 
      } 
     } 

    } 

usługi implementacja

public class DtoService : IDtoService 
    { 
     public MyDto GetData(int value) 
     { 
      var dto = new MyDto { Rating = (Rating) 42 }; // not in ENUM! 
      return dto; 
     } 
    } 

Client

var cl = new DtoServiceClient.DtoServiceClient(); 
var tada = cl.GetData(1); // connection closed exception 

Aby mieć rzeczywisty wyjątek rzucony musiałem Czy wyłączyć „umożliwiają tylko mój kod” w VS2010 opcje debugowania aw Wyjątki dialogowym pozwalają Thrown dla „wspólnego języka wyjątki środowiska wykonawczego”

Z że ustawienia cenny wyjątek:

SerializationException
wartość Enum „42” jest nieprawidłowa dla typu „WcfService1.Rating” i nie może być w odcinkach. Upewnić się, że niezbędne wartości wyliczeniowe są obecne i są oznaczone atrybutu EnumMemberAttribute jeśli typ ma DataContractAttribute atrybut

to kosztem że debugger staje się bardzo głośno o wszystkich innych rodzajach rzucone wyjątkami że AFAIK można być zignorowanym.

Co mogę zrobić, aby ten wyjątek został rzucony bez hałasu?

Czy jest coś, co mogę poprawić lub dodać w potoku WCF?

Możliwym rozwiązaniem nie wcześnie z kosztami przeróbek jest dodanie dodatkowego dochodzić w seter członu ENUM:

Debug.Assert(Enum.IsDefined(typeof(Rating), value),"value is not valid for this enum"); 

Alternatywą Próbowałem została dodanie umowy w nadziei ostrzeżenie mogłoby być wyprodukowanym. Nie mogłem znaleźć nic lepszego niż w zasadzie kopia Debug.Assert.

System.Diagnostics.Contracts.Contract.Assert(Enum.IsDefined(typeof(Rating), value)); 

Czy istnieje możliwość, aby mieć kompilator emitują to dla mnie sprawdzić czy istnieje alternatywa nie jestem świadomy?
(próbowałem także skompilować z check for arithmetic overflow/underflow włączoną bez spodziewałem się, że succeful)

CodeContracts emituje ostrzeżenie, (trzeba enble dorozumianych obowiązków zapisu ENUM) mimo, że naprawdę nie pomaga

rzeczywista wartość ta może być w zakresie określonym w tym eNUM

to zachowanie jest w VS2010/NET związku 4.0.

+0

Wydaje mi się, że umowa jest najlepszą rzeczą, jaką można zrobić, nie próbując rozszerzyć zachowania serializacyjnego WCF (które mogą stać się tak owłosione jak yak). –

+1

@SixtoSaez Po głębszym wykopaniu czuję, że Twoja sugestia jest teraz najbardziej praktyczna. Nie chcę zadbać o jakiem ... – rene

Odpowiedz

3

Możesz zrobić kilka rzeczy.

Po stronie WCF użyj IncludeExceptionDetailInFaults (używając atrybutu ServiceBehavior lub w swoim app.config). Spowoduje to, że WCF wysyła szczegółowe wyjątki do klienta. Zauważ, że jest to ustawienie "niebezpieczne", ponieważ ujawnia ślady stosu serwerów po stronie klienta, więc powinieneś używać tego tylko podczas programowania. W przypadku produkcji należy użyć procedury obsługi błędów WCF, aby zarejestrować wszystkie błędy usługi (lub włączyć śledzenie WCF).

Jeśli chcesz wykorzystywać umów kod, aby nadrobić ten błąd podczas czasie kompilacji można użyć niezmienników obiektu:

public class MyDto 
{ 
    public Rating Rating { get; set; } 

    [ContractInvariantMethod] 
    void Invariant() 
    { 
     Contract.Invariant(Enum.IsDefined(typeof(Rating), Rating)); 
    } 
} 

Włączenie analizy statycznej, otrzymasz ostrzeżenie na tej linii:

new MyDto { Rating = (Rating) 42 }; 
+0

Brzmi obiecująco, spróbuję ... – rene

+0

Uważam, że ContractInvariantMethod to rozwiązanie podobne. Dzięki za zaglądanie w to. – rene

+0

Należy zauważyć, że nie jest to nieomylne. Jeśli otrzymasz wyliczenie gdzieś indziej, a nie stałą kodu, możesz nadal mieć niepoprawną wartość (na przykład rzutowanie sparsowanej int). –

Powiązane problemy