2013-07-24 28 views
5

Trong trường hợp một dịch vụ WCF trả về một DataContract với một thành viên enum có giá trị không hợp lệ (int không có trong kiểu Enum) là The underlying connection was closed: The connection was closed unexpectedly.
Điều lạ là ngoại lệ này được kích hoạt vì DataContractSerializer không thể tuần tự hóa tại máy chủ của kết nối.Thất bại sớm hoặc rõ ràng ném khi một enum không thể được tuần tự

Tôi thà có một cái gì đó nhiều hơn hữu ích ném vào mặt tôi và trước đó quan trọng hơn, khi chạy trên serverside nhưng có lẽ một cảnh báo trình biên dịch ... Hợp đồng

Dịch vụ WCF

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

    } 

Dịch vụ thực hiện

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

Khách hàng

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

Để có ngoại lệ thực tế ném tôi phải Tắt tính năng 'cho phép chỉ mã của tôi' trong các tùy chọn gỡ lỗi VS2010 và trong Exceptions hộp thoại enable Ném cho 'ngôn ngữ chung Runtime ngoại lệ'

Với rằng các thiết lập ngoại lệ có giá trị là:

SerializationException
giá trị Enum '42' là không hợp lệ cho loại 'WcfService1.Rating' và không thể được đăng. Đảm bảo rằng các giá trị enum cần thiết có mặt và được đánh dấu bằng EnumMemberAttribute thuộc tính nếu loại có DataContractAttribute thuộc tính

này đi kèm với chi phí mà các chương trình gỡ rối được rất ồn ào về tất cả các loại ngoại lệ ném rằng AFAIK thể được bỏ qua.

Tôi có thể thử loại trừ ngoại lệ này mà không bị nhiễu?

Có điều gì tôi có thể tinh chỉnh hoặc thêm vào đường ống WCF không?

Một giải pháp khả thi để thất bại sớm với chi phí làm lại được bổ sung thêm một Khẳng định trong setter của thành viên enum:

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

Một thay thế tôi đã cố gắng đã được bổ sung thêm một hợp đồng với hy vọng một lời cảnh báo có thể được sản xuất. Tôi không thể tìm thấy bất cứ điều gì tốt hơn về cơ bản một bản sao của Debug.Assert.

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

Có một tùy chọn để có trình biên dịch phát ra việc kiểm tra này cho tôi hay là có một sự thay thế tôi không biết?
(Tôi cũng đã cố gắng để biên dịch với check for arithmetic overflow/underflow kích hoạt mà không mong nó sẽ được succeful)

CodeContracts không phát ra một cảnh báo, (bạn phải enble Enum nghĩa vụ ghi Implicit) mặc dù điều đó không thực sự giúp

Giá trị thực tế có thể không nằm trong phạm vi được xác định cho giá trị enum này

Hành vi này nằm trong ngữ cảnh VS2010/.Net 4.0.

+0

Dường như với tôi rằng hợp đồng khẳng định là tốt nhất bạn có thể làm mà không cần cố gắng mở rộng hành vi tuần tự hóa WCF (có thể nhận được như lông như một yak). –

+1

@SixtoSaez Sau khi đào bới thêm một chút nữa, tôi cảm thấy rằng đề xuất của bạn là sự gợi ý nhất hiện nay. Tôi không muốn chú rể một yak ... – rene

Trả lời

3

Bạn có thể làm một vài việc.

Ở phía WCF, sử dụng IncludeExceptionDetailInFaults (hoặc sử dụng thuộc tính ServiceBehavior hoặc trong số app.config). Điều này sẽ làm cho WCF gửi ngoại lệ chi tiết cho khách hàng. Lưu ý đây được coi là cài đặt 'không an toàn' vì nó cho thấy dấu vết ngăn xếp của máy chủ ở phía máy khách, vì vậy bạn chỉ nên sử dụng nó trong quá trình phát triển. Đối với sản xuất, bạn nên sử dụng một trình xử lý lỗi WCF để đăng nhập tất cả các lỗi dịch vụ (hoặc bật truy tìm WCF).

Nếu bạn muốn sử dụng luật hợp đồng để bắt lỗi này trong thời gian biên dịch bạn có thể sử dụng bất biến đối tượng:

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

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

Nếu bạn cho phép phân tích tĩnh, bạn sẽ nhận được một cảnh báo về dòng này:

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

Điều này nghe có vẻ đầy hứa hẹn, tôi sẽ thử ... – rene

+0

Tôi tìm thấy giải pháp ContractInvariantMethod giống như vậy. Cảm ơn vì đã điều tra việc này. – rene

+0

Bạn nên lưu ý rằng điều này là không thể sai lầm. Nếu bạn nhận được enum từ một nơi khác, và không phải là một hằng số mã, bạn vẫn có thể có một giá trị không hợp lệ (ví dụ, đúc một phân tích int.) –

Các vấn đề liên quan