2009-03-16 27 views
8

Chúng tôi có một giao diện dịch vụ web SOAP hiện có mà chúng tôi muốn triển khai bằng cách sử dụng WCF cho một ứng dụng mới. Điều này dường như làm việc tốt ngoại trừ một chi tiết nhỏ. Không gian tên XML của kiểu trả về của hàm phải khác với không gian tên XML của chính dịch vụ web. Và đối với cuộc sống của tôi, tôi không thể làm cho nó hoạt động được.Cách tùy chỉnh tuần tự hóa WCF XML

Tôi đã tạo lại cùng một vấn đề với một dự án mẫu nhỏ. Giao diện WCF:

[XmlSerializerFormat] 
[ServiceContract(Namespace = "urn:outer-namespace")] 
public interface IService1 
{ 
    [OperationContract] 
    MyClass DoStuff(int value); 
} 

[Serializable] 
public class MyClass 
{ 
    [XmlElement(ElementName = "DataString")] 
    public string MyString { get; set; } 
} 

Việc thực hiện dịch vụ web:

public class Service1 : IService1 
{ 
    public MyClass DoStuff(int value) 
    { 
     return new MyClass { MyString = "Wooh!" }; 
    } 
} 

Một phản hồi từ webservice này sau đó được đăng như: (Bỏ thứ SOAP)

<DoStuffResponse xmlns="urn:outer-namespace"> 
    <DoStuffResult> 
     <DataString>Wooh!</DataString> 
    </DoStuffResult> 
    </DoStuffResponse> 

Nhưng chúng tôi muốn <DoStuffResult> là của xmlns = "urn: inner-namespace".

Tôi đã thử thêm [return: XmlElement (...)] vào chức năng giao diện hoặc chức năng dịch vụ web nhưng không thực hiện. Ngoài ra một [XmlType] hoặc [XmlRoot] trên định nghĩa lớp MyClass không hoạt động.

Có ai có ý tưởng làm cách nào để thay đổi không gian tên XML được tuần tự hóa (hoặc tên phần tử) của đối tượng là giá trị trả về của một chức năng dịch vụ web WCF không?

Trả lời

3

Xác định các không gian tên với các thuộc tính định nghĩa hợp đồng dữ liệu XML (hoặc, tốt hơn).

ví dụ: với XML Serialization:

[Serializable, XmlRoot(namespace="http://example.com/eg1")] 
public class MyClass { 
    [XmlElement(ElementName = "DataString")] 
    public string MyString { get; set; } 
} 

ví dụ: với hợp đồng dữ liệu tuần tự:

[DataContract(Namespace="http://example.com/eg2")] 
public class MyClass { 
    [DataMember] 
    public string MyString { get; set; } 
} 

EDIT

Dựa trên những nhận xét đầu tiên, ở trên sẽ không làm việc, vì mong muốn là để thiết lập không gian tên trên wrapper SOAP xung quanh thông điệp, không trên bản thân thông điệp.

OperationContractAttribute không cung cấp quyền kiểm soát không gian tên và tôi không thể thấy bất kỳ thuộc tính WCF nào khác ở cấp phương thức.

Hai khả năng: (1) Bạn có thể có đủ quyền kiểm soát bằng cách giảm mức trừu tượng và sử dụng Hợp đồng thư. (2) Lấy WSDL hiện tại cho dịch vụ (sử dụng svcutil.exe), điều chỉnh thủ công để lấy các không gian tên bạn muốn, sau đó sử dụng lại svcutil.exe để tạo mã và xem mã kết quả.

+0

Giống như tôi đã nêu trong câu hỏi, tôi đã cố gắng thêm một thuộc tính XmlRoot và nó đã không làm việc. Nó chỉ thêm không gian tên cho các trường trong MyClass, nhưng không thêm vào MyClass. DataContract cũng không hoạt động, và tôi thích XmlSerializer vì đổi tên và trật tự không quan trọng. –

+0

Tôi đã sử dụng svcutil, nhưng không chỉ định bộ nối tiếp và nó tạo ra một sự kết hợp giữa MessageContract và ServiceContract với XmlSerializer. Vì vậy, nó có một hoặc hai trình bao bọc và tôi vẫn có thể sử dụng các thuộc tính XML để làm cho nó hoạt động. –

1

Sau nhiều ngày tìm kiếm và thử hàng tá giải pháp được đề xuất; Tôi cuối cùng đã có thể nhận được WCF để ngăn chặn buộc một tên container wrapper thêm Result vào tên của phương thức dịch vụ web. Bí quyết là để thêm thuộc tính trang trí sau vào giao diện dịch vụ web:

[return:MessageParameter(Name = "whatIWantItNamed")] 

Thuộc tính này nên được đặt/nằm trực tiếp sau khi các thuộc tính [OperationContract] (và ngay trước khi phương pháp sơ khai thực tế) trong giao diện.

(tôi cũng cần thêm một thuộc tính XmlSerializerFormat cho tất cả các ServiceContractOperationContract thuộc tính.)

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