Menentukan Transfer Data dalam Kontrak Layanan

Windows Communication Foundation (WCF) dapat dianggap sebagai infrastruktur perpesanan. Operasi layanan dapat menerima pesan, memprosesnya, dan mengirimi mereka pesan. Pesan dijelaskan menggunakan kontrak operasi. Sebagai contoh, perhatikan kontrak berikut.

[ServiceContract]  
public interface IAirfareQuoteService  
{  
    [OperationContract]  
    float GetAirfare(string fromCity, string toCity);  
}  
<ServiceContract()>  
Public Interface IAirfareQuoteService  
  
    <OperationContract()>  
    Function GetAirfare(fromCity As String, toCity As String) As Double  
End Interface  

Di sini, GetAirfare operasi menerima pesan dengan informasi tentang fromCity dan toCity, lalu mengembalikan pesan yang berisi angka.

Topik ini menjelaskan berbagai cara kontrak operasi dapat menjelaskan pesan.

Mendeskripsikan Pesan dengan Menggunakan Parameter

Cara paling sederhana untuk menggambarkan pesan adalah dengan menggunakan daftar parameter dan nilai yang dikembalikan. Pada contoh sebelumnya, parameter string fromCity dan toCity digunakan untuk mendeskripsikan pesan permintaan, dan nilai pengembalian float digunakan untuk mendeskripsikan pesan balasan. Jika nilai yang dikembalikan saja tidak cukup untuk mendeskripsikan pesan balasan, parameter keluar dapat digunakan. Misalnya, operasi berikut memiliki fromCity dan toCity dalam pesan permintaannya, dan nomor bersama dengan mata uang dalam pesan balasannya:

[OperationContract]  
float GetAirfare(string fromCity, string toCity, out string currency);  
<OperationContract()>  
    Function GetAirfare(fromCity As String, toCity As String) As Double  

Selain itu, Anda dapat menggunakan parameter referensi untuk membuat bagian parameter dari permintaan dan pesan balasan. Parameter harus dari jenis yang dapat diserialisasikan (dikonversi ke XML). Secara default, WCF menggunakan komponen yang disebut DataContractSerializer kelas untuk melakukan konversi ini. Sebagian besar jenis primitif (seperti int, string, float, dan DateTime.) didukung. Jenis yang ditentukan pengguna biasanya harus memiliki kontrak data. Untuk informasi selengkapnya, lihat Menggunakan Kontrak Data.

public interface IAirfareQuoteService  
{  
    [OperationContract]  
    float GetAirfare(Itinerary itinerary, DateTime date);  
  
    [DataContract]  
    public class Itinerary  
    {  
        [DataMember]  
        public string fromCity;  
        [DataMember]  
        public string toCity;  
   }  
}  
Public Interface IAirfareQuoteService  
    <OperationContract()>  
    GetAirfare(itinerary as Itinerary, date as DateTime) as Double  
  
    <DataContract()>  
    Class Itinerary  
  
        <DataMember()>  
        Public fromCity As String  
        <DataMember()>  
        Public toCity As String  
    End Class  
End Interface  

Terkadang, DataContractSerializer tidak memadai untuk menserialisasikan jenis Anda. WCF mendukung mesin serialisasi alternatif, XmlSerializer, yang juga dapat Anda gunakan untuk menserialisasikan parameter. XmlSerializer memungkinkan Anda untuk menggunakan lebih banyak kontrol atas XML yang dihasilkan menggunakan atribut seperti XmlAttributeAttribute. Untuk beralih menggunakan XmlSerializer untuk operasi tertentu atau untuk seluruh layanan, terapkan atribut XmlSerializerFormatAttribute ke operasi atau layanan. Misalnya:

[ServiceContract]  
public interface IAirfareQuoteService  
{  
    [OperationContract]  
    [XmlSerializerFormat]  
    float GetAirfare(Itinerary itinerary, DateTime date);  
}  
public class Itinerary  
{  
    public string fromCity;  
    public string toCity;  
    [XmlAttribute]  
    public bool isFirstClass;  
}  
<ServiceContract()>  
Public Interface IAirfareQuoteService  
    <OperationContract()>  
    <XmlSerializerFormat>  
    GetAirfare(itinerary as Itinerary, date as DateTime) as Double  
  
End Interface  
  
Class Itinerary  
  
    Public fromCity As String  
    Public toCity As String  
    <XmlSerializerFormat()>  
    Public isFirstClass As Boolean  
End Class  

Untuk informasi selengkapnya, lihat Menggunakan Kelas XmlSerializer. Ingatlah bahwa beralih ke secara manual kw XmlSerializer seperti yang ditunjukkan di sini tidak disarankan kecuali Anda memiliki alasan khusus untuk melakukannya seperti yang dijelaskan dalam topik tersebut.

Untuk mengisolasi nama parameter .NET dari nama kontrak, Anda dapat menggunakan atribut MessageParameterAttribute, dan menggunakan properti Name untuk mengatur nama kontrak. Misalnya, kontrak operasi berikut ini setara dengan contoh pertama dalam topik ini.

[OperationContract]  
public float GetAirfare(  
    [MessageParameter(Name="fromCity")] string originCity,  
    [MessageParameter(Name="toCity")] string destinationCity);  
<OperationContract()>  
  Function GetAirfare(<MessageParameter(Name := "fromCity")> fromCity As String, <MessageParameter(Name := "toCity")> toCity As String) As Double  

Mendeskripsikan Pesan Kosong

Pesan permintaan kosong dapat dijelaskan dengan tidak memiliki parameter input atau referensi. Misalnya, di C#:

[OperationContract]

public int GetCurrentTemperature();

Misalnya, dalam Visual Basic:

<OperationContract()>

Function GetCurrentTemperature() as Integer

Pesan balasan kosong dapat dideskripskan dengan memiliki jenis pengembalian void dan tidak ada parameter output atau referensi. Misalnya di:

[OperationContract]  
public void SetTemperature(int temperature);  
<OperationContract()>  
Sub SetTemperature(temperature As Integer)  

Ini berbeda dengan operasi satu arah, seperti:

[OperationContract(IsOneWay=true)]  
public void SetLightbulbStatus(bool isOn);  
<OperationContract(IsOneWay:=True)>  
Sub SetLightbulbStatus(isOne As Boolean)  

Operasi SetTemperatureStatus mengembalikan pesan kosong. Ini dapat mengembalikan kesalahan sebagai gantinya jika ada masalah saat memproses pesan input. Operasi SetLightbulbStatus tidak menghasilkan apa pun. Tidak ada cara untuk mengkomunikasikan kondisi kesalahan dari operasi ini.

Menjelaskan Pesan dengan Menggunakan Kontrak Pesan

Anda mungkin ingin menggunakan satu jenis untuk mewakili seluruh pesan. Meskipun dimungkinkan untuk menggunakan kontrak data untuk tujuan ini, cara yang disarankan untuk melakukannya adalah dengan menggunakan kontrak pesan—ini menghindari tingkat pembungkusan yang tidak perlu dalam XML yang dihasilkan. Selain itu, kontrak pesan memungkinkan Anda untuk melakukan kontrol lebih besar atas pesan yang dihasilkan. Misalnya, Anda dapat memutuskan bagian informasi mana yang harus ada di badan pesan dan mana yang harus ada di header pesan. Contoh berikut menunjukkan penggunaan kontrak pesan.

[ServiceContract]  
public interface IAirfareQuoteService  
{  
    [OperationContract]  
    GetAirfareResponse GetAirfare(GetAirfareRequest request);  
}  
  
[MessageContract]  
public class GetAirfareRequest  
{  
    [MessageHeader] public DateTime date;  
    [MessageBodyMember] public Itinerary itinerary;  
}  
  
[MessageContract]  
public class GetAirfareResponse  
{  
    [MessageBodyMember] public float airfare;  
    [MessageBodyMember] public string currency;  
}  
  
[DataContract]  
public class Itinerary  
{  
    [DataMember] public string fromCity;  
    [DataMember] public string toCity;  
}  
<ServiceContract()>  
Public Interface IAirfareQuoteService  
    <OperationContract()>  
    Function GetAirfare(request As GetAirfareRequest) As GetAirfareResponse  
End Interface  
  
<MessageContract()>  
Public Class GetAirfareRequest  
    <MessageHeader()>
    Public Property date as DateTime  
    <MessageBodyMember()>  
    Public Property itinerary As Itinerary  
End Class  
  
<MessageContract()>  
Public Class GetAirfareResponse  
    <MessageBodyMember()>  
    Public Property airfare As Double  
    <MessageBodyMember()> Public Property currency As String  
End Class  
  
<DataContract()>  
Public Class Itinerary  
    <DataMember()> Public Property fromCity As String  
    <DataMember()> Public Property toCity As String  
End Class  

Untuk informasi selengkapnya, lihat Menggunakan Kontrak Pesan.

Pada contoh sebelumnya, kelas DataContractSerializer masih digunakan secara default. Kelas XmlSerializer juga dapat digunakan dengan kontrak pesan. Untuk melakukannya, terapkan atribut XmlSerializerFormatAttribute ke operasi atau kontrak, dan gunakan jenis yang kompatibel dengan kelas XmlSerializer di header pesan dan anggota isi.

Mendeskripsikan Pesan dengan Menggunakan Aliran

Cara lain untuk mendeskripsikan pesan dalam operasi adalah dengan menggunakan kelas Stream atau salah satu kelas turunannya dalam kontrak operasi atau sebagai anggota badan kontrak pesan (harus menjadi satu-satunya anggota dalam kasus ini). Untuk pesan masuk, jenisnya harus Stream—Anda tidak dapat menggunakan kelas turunan.

Alih-alih memanggil serializer, WCF mengambil data dari aliran dan memasukkannya langsung ke pesan keluar, atau mengambil data dari pesan masuk dan memasukkannya langsung ke aliran. Contoh berikut menunjukkan penggunaan aliran.

[OperationContract]  
public Stream DownloadFile(string fileName);  
<OperationContract()>  
Function DownloadFile(fileName As String) As String  

Anda tidak dapat menggabungkan Stream dan data non-aliran dalam satu badan pesan. Gunakan kontrak pesan untuk menempatkan data tambahan di header pesan. Contoh berikut menunjukkan penggunaan aliran yang salah saat menentukan kontrak operasi.

//Incorrect:  
// [OperationContract]  
// public void UploadFile (string fileName, Stream fileData);  
'Incorrect:  
    '<OperationContract()>  
    Public Sub UploadFile(fileName As String, fileData As StreamingContext)  

Contoh berikut menunjukkan penggunaan aliran yang benar saat menentukan kontrak operasi.

[OperationContract]  
public void UploadFile (UploadFileMessage message);  
//code omitted  
[MessageContract]  
public class UploadFileMessage  
{  
    [MessageHeader] public string fileName;  
    [MessageBodyMember] public Stream fileData;  
}  
<OperationContract()>  
Public Sub UploadFile(fileName As String, fileData As StreamingContext)  
'Code Omitted  
<MessageContract()>  
Public Class UploadFileMessage  
   <MessageHeader()>  
    Public Property fileName As String  
    <MessageBodyMember()>  
    Public Property fileData As Stream  
End Class  

Untuk informasi selengkapnya, lihat Data Besar dan Streaming.

Menggunakan Kelas Pesan

Untuk memiliki kontrol terprogram penuh atas pesan yang dikirim atau diterima, Anda dapat menggunakan kelas Message secara langsung, seperti yang ditunjukkan pada kode contoh berikut.

[OperationContract]  
public void LogMessage(Message m);  
<OperationContract()>  
Sub LogMessage(m As Message)  

Ini adalah skenario tingkat lanjut, yang dijelaskan secara rinci di Menggunakan Kelas Pesan.

Menjelaskan Pesan Kesalahan

Selain pesan yang dijelaskan oleh nilai yang dikembalikan dan parameter output atau referensi, operasi apa pun yang tidak satu arah dapat mengembalikan setidaknya dua kemungkinan pesan: pesan respons normal dan pesan kesalahan. Perhatikan kontrak operasi berikut.

[OperationContract]  
float GetAirfare(string fromCity, string toCity, DateTime date);  
<OperationContract()>  
Function GetAirfare(fromCity As String, toCity As String, date as DateTime)  

Operasi ini dapat mengembalikan pesan normal yang berisi nomor float, atau pesan kesalahan yang berisi kode kesalahan dan deskripsi. Anda dapat melakukannya dengan menampilkan FaultException dalam implementasi layanan Anda.

Anda dapat menentukan kemungkinan pesan kesalahan tambahan dengan menggunakan atribut FaultContractAttribute. Kesalahan tambahan harus diserialisasikan menggunakan DataContractSerializer, seperti yang ditunjukkan pada contoh kode berikut.

[OperationContract]  
[FaultContract(typeof(ItineraryNotAvailableFault))]  
float GetAirfare(string fromCity, string toCity, DateTime date);  
  
//code omitted  
  
[DataContract]  
public class ItineraryNotAvailableFault  
{  
    [DataMember]  
    public bool IsAlternativeDateAvailable;  
  
    [DataMember]  
    public DateTime alternativeSuggestedDate;  
}  
<OperationContract()>  
<FaultContract(GetType(ItineraryNotAvailableFault))>  
Function GetAirfare(fromCity As String, toCity As String, date as DateTime) As Double  
  
'Code Omitted  
<DataContract()>  
Public Class  
  <DataMember()>  
  Public Property IsAlternativeDateAvailable As Boolean  
  <DataMember()>  
  Public Property alternativeSuggestedDate As DateTime  
End Class  

Kesalahan tambahan ini dapat dihasilkan dengan menampilkan FaultException<TDetail> dari jenis kontrak data yang sesuai. Untuk informasi selengkapnya, lihat Menangani Pengecualian dan Kesalahan.

Anda tidak dapat menggunakan kelas XmlSerializer untuk menjelaskan kesalahan. XmlSerializerFormatAttribute tidak berpengaruh pada kontrak kesalahan.

Menggunakan Jenis Turunan

Anda mungkin ingin menggunakan jenis dasar dalam operasi atau kontrak pesan, dan kemudian menggunakan jenis turunan ketika benar-benar menjalankan operasi. Dalam hal ini, Anda harus menggunakan atribut ServiceKnownTypeAttribute atau beberapa mekanisme alternatif untuk mengizinkan penggunaan jenis turunan. Pertimbangkan operasi berikut.

[OperationContract]  
public bool IsLibraryItemAvailable(LibraryItem item);  
<OperationContract()>  
    Function IsLibraryItemAvailable(item As LibraryItem) As Boolean  

Asumsikan bahwa dua jenis, Book dan Magazine, berasal dari LibraryItem. Untuk menggunakan jenis ini dalam operasi IsLibraryItemAvailable, Anda dapat mengubah operasi sebagai berikut:

[OperationContract]

[ServiceKnownType(typeof(Book))]

[ServiceKnownType(typeof(Magazine))]

public bool IsLibraryItemAvailable(LibraryItem item);

Atau, Anda dapat menggunakan atribut KnownTypeAttribute saat default DataContractSerializer sedang digunakan, seperti yang ditunjukkan dalam kode contoh berikut.

[OperationContract]  
public bool IsLibraryItemAvailable(LibraryItem item);  
  
// code omitted
  
[DataContract]  
[KnownType(typeof(Book))]  
[KnownType(typeof(Magazine))]  
public class LibraryItem  
{  
    //code omitted  
}  
<OperationContract()>  
Function IsLibraryItemAvailable(item As LibraryItem) As Boolean  
  
'Code Omitted  
<DataContract()>  
<KnownType(GetType(Book))>  
<KnownType(GetType(Magazine))>  
Public Class LibraryItem  
  'Code Omitted  
End Class  

Anda dapat menggunakan atribut XmlIncludeAttribute saat menggunakan XmlSerializer.

Anda dapat menerapkan atribut ServiceKnownTypeAttribute ke operasi atau ke seluruh layanan. Ini menerima jenis atau nama metode yang dipanggil untuk mendapatkan daftar jenis yang diketahui, seperti atribut KnownTypeAttribute. Untuk informasi selengkapnya, lihat Jenis yang Diketahui Kontrak Data.

Menentukan Penggunaan dan Gaya

Saat menjelaskan layanan menggunakan Web Services Description Language (WSDL), dua gaya yang umum digunakan adalah Dokumen dan panggilan prosedur jarak jauh (RPC). Dalam gaya Dokumen, seluruh isi pesan dijelaskan menggunakan skema, dan WSDL menjelaskan berbagai bagian isi pesan dengan merujuk ke elemen dalam skema itu. Dalam gaya RPC, WSDL mengacu pada jenis skema untuk setiap bagian pesan daripada elemen. Dalam beberapa kasus, Anda harus memilih salah satu gaya ini secara manual. Anda dapat melakukannya dengan menerapkan atribut DataContractFormatAttribute dan mengatur properti Style (saat DataContractSerializer sedang digunakan), atau dengan mengatur Style pada atribut XmlSerializerFormatAttribute (saat menggunakan XmlSerializer).

Selain itu, XmlSerializer mendukung dua bentuk XML yang diserialisasikan: Literal dan Encoded. Literal adalah formulir yang paling umum diterima, dan merupakan satu-satunya formulir yang DataContractSerializer didukung. Encoded adalah formulir lama yang dijelaskan di bagian 5 spesifikasi SOAP, dan tidak disarankan untuk layanan baru. Untuk beralih ke mode Encoded, atur properti Use pada atribut XmlSerializerFormatAttribute ke Encoded.

Biasanya, Anda tidak boleh mengubah pengaturan default untuk properti Style dan Use.

Mengontrol Proses Serialisasi

Anda dapat melakukan beberapa hal untuk menyesuaikan cara data diserialisasi.

Mengubah Pengaturan Serialisasi Server

Saat default DataContractSerializer digunakan, Anda dapat mengontrol beberapa aspek proses serialisasi pada layanan dengan menerapkan atribut ServiceBehaviorAttribute ke layanan. Secara khusus, Anda dapat menggunakan properti MaxItemsInObjectGraph untuk mengatur kuota yang membatasi jumlah maksimum objek yang dideserialisasi DataContractSerializer. Anda dapat menggunakan properti IgnoreExtensionDataObject untuk mematikan fitur versi bolak-balik. Untuk informasi selengkapnya tentang kuota, lihat Pertimbangan Keamanan untuk Data. Untuk informasi lebih lanjut tentang bolak-balik, lihat Kontrak Data yang Kompatibel dengan Penerusan.

[ServiceBehavior(MaxItemsInObjectGraph=100000)]  
public class MyDataService:IDataService  
{  
    public DataPoint[] GetData()  
    {  
       // Implementation omitted  
    }  
}  
<ServiceBehavior(MaxItemsInObjectGraph:=100000)>  
Public Class MyDataService Implements IDataService  
  
    Function GetData() As DataPoint()  
         ‘ Implementation omitted  
    End Function  
End Interface  

Perilaku Serialisasi

Dua perilaku tersedia di WCF, DataContractSerializerOperationBehavior dan XmlSerializerOperationBehavior yang dipasang secara otomatis bergantung pada serializer yang digunakan untuk operasi tertentu. Karena perilaku ini diterapkan secara otomatis, Anda biasanya tidak perlu menyadarinya.

Namun, DataContractSerializerOperationBehavior memiliki properti MaxItemsInObjectGraph, IgnoreExtensionDataObject, dan DataContractSurrogate yang dapat Anda gunakan untuk menyesuaikan proses serialisasi. Dua properti pertama memiliki arti yang sama seperti yang dibahas di bagian yang sebelumnya. Anda dapat menggunakan properti DataContractSurrogate untuk mengaktifkan pengganti kontrak data, yang merupakan mekanisme ampuh untuk menyesuaikan dan memperluas proses serialisasi. Untuk mengetahui informasi selengkapnya, lihat Pengganti Kontrak Data.

Anda dapat menggunakan DataContractSerializerOperationBehavior untuk menyesuaikan serialisasi klien dan server. Contoh berikut menunjukkan cara meningkatkan kuota MaxItemsInObjectGraph pada klien.

ChannelFactory<IDataService> factory = new ChannelFactory<IDataService>(binding, address);  
foreach (OperationDescription op in factory.Endpoint.Contract.Operations)  
{  
    DataContractSerializerOperationBehavior dataContractBehavior =  
                op.Behaviors.Find<DataContractSerializerOperationBehavior>()  
                as DataContractSerializerOperationBehavior;  
    if (dataContractBehavior != null)  
    {  
        dataContractBehavior.MaxItemsInObjectGraph = 100000;  
    }  
}  
IDataService client = factory.CreateChannel();  
Dim factory As ChannelFactory(Of IDataService) = New ChannelFactory(Of IDataService)(binding, address)  
For Each op As OperationDescription In factory.Endpoint.Contract.Operations  
        Dim dataContractBehavior As DataContractSerializerOperationBehavior = op.Behaviors.Find(Of DataContractSerializerOperationBehavior)()  
        If dataContractBehavior IsNot Nothing Then  
            dataContractBehavior.MaxItemsInObjectGraph = 100000  
        End If  
     Next  
    Dim client As IDataService = factory.CreateChannel  

Berikut ini adalah kode yang setara pada layanan, dalam kasus yang dihosting sendiri:

ServiceHost serviceHost = new ServiceHost(typeof(IDataService))  
foreach (ServiceEndpoint ep in serviceHost.Description.Endpoints)  
{  
foreach (OperationDescription op in ep.Contract.Operations)  
{  
        DataContractSerializerOperationBehavior dataContractBehavior =  
           op.Behaviors.Find<DataContractSerializerOperationBehavior>()  
                as DataContractSerializerOperationBehavior;  
        if (dataContractBehavior != null)  
        {  
            dataContractBehavior.MaxItemsInObjectGraph = 100000;  
        }  
}  
}  
serviceHost.Open();  
Dim serviceHost As ServiceHost = New ServiceHost(GetType(IDataService))  
        For Each ep As ServiceEndpoint In serviceHost.Description.Endpoints  
            For Each op As OperationDescription In ep.Contract.Operations  
                Dim dataContractBehavior As DataContractSerializerOperationBehavior = op.Behaviors.Find(Of DataContractSerializerOperationBehavior)()  
  
                If dataContractBehavior IsNot Nothing Then  
                    dataContractBehavior.MaxItemsInObjectGraph = 100000  
                End If  
            Next  
        Next  
        serviceHost.Open()  

Dalam kasus yang dihosting Web, Anda harus membuat kelas turunan baru ServiceHost dan menggunakan pabrik host layanan untuk menyambungkannya.

Mengontrol Pengaturan Serialisasi di Konfigurasi

MaxItemsInObjectGraph dan IgnoreExtensionDataObject dapat dikontrol melalui konfigurasi dengan menggunakan dataContractSerializer titik akhir atau perilaku layanan, seperti yang ditunjukkan pada contoh berikut.

<configuration>  
    <system.serviceModel>  
        <behaviors>  
            <endpointBehaviors>  
                <behavior name="LargeQuotaBehavior">  
                    <dataContractSerializer  
                      maxItemsInObjectGraph="100000" />  
                </behavior>  
            </endpointBehaviors>  
        </behaviors>  
        <client>  
            <endpoint address="http://example.com/myservice"  
                  behaviorConfiguration="LargeQuotaBehavior"  
                binding="basicHttpBinding" bindingConfiguration=""
                            contract="IDataService"  
                name="" />  
        </client>  
    </system.serviceModel>  
</configuration>  

Serialisasi Jenis Bersama, Pelestarian Grafik Objek, dan Serializer Kustom

DataContractSerializer menserialisasi dengan menggunakan nama kontrak data dan bukan nama jenis .NET. Ini konsisten dengan prinsip arsitektur berorientasi layanan dan memungkinkan tingkat fleksibilitas yang tinggi—jenis .NET dapat berubah tanpa memengaruhi kontrak kabel. Dalam kasus yang jarang terjadi, Anda mungkin ingin membuat serial nama jenis .NET yang sebenarnya, sehingga memperkenalkan koupling ketat antara klien dan server, mirip dengan teknologi jarak jauh .NET Framework. Ini bukan praktik yang disarankan, kecuali dalam kasus yang jarang terjadi yang biasanya terjadi saat bermigrasi ke WCF dari .NET Framework jarak jauh. Dalam hal ini, Anda harus menggunakan kelas NetDataContractSerializer bukan kelas DataContractSerializer.

DataContractSerializer biasanya menserialisasikan grafik objek sebagai pohon objek. Artinya, jika objek yang sama dirujuk lebih dari satu kali, objek tersebut diserialisasikan lebih dari satu kali. Misalnya, pertimbangkan instans PurchaseOrder yang memiliki dua bidang jenis Alamat yang disebut billTo dan shipTo. Jika kedua bidang diatur ke instans Alamat yang sama, ada dua instans Alamat yang identik setelah serialisasi dan deserialisasi. Hal ini dilakukan karena tidak ada cara standar yang dapat dioperasikan untuk mewakili grafik objek dalam XML (kecuali untuk standar yang dikodekan SOAP lama yang tersedia di XmlSerializer, seperti yang dijelaskan di bagian sebelumnya tentang Style dan Use). Menserialisasikan grafik objek sebagai pohon memiliki kelemahan tertentu, misalnya grafik dengan referensi melingkar tidak dapat diserialisasikan. Terkadang, perlu untuk beralih ke serialisasi grafik objek yang sebenarnya, meskipun tidak dapat dioperasikan. Ini dapat dilakukan dengan menggunakan DataContractSerializer yang dibuat dengan parameter preserveObjectReferences yang diatur ke true.

Terkadang, serializer bawaan tidak cukup untuk skenario Anda. Dalam kebanyakan kasus, Anda masih dapat menggunakan XmlObjectSerializer dari mana abstraksi DataContractSerializer dan NetDataContractSerializer berasal.

Tiga kasus sebelumnya (pelestarian jenis .NET, pelestarian grafik objek, dan serialisasi berbasis XmlObjectSerializer yang sepenuhnya kustom) semuanya memerlukan serializer kustom untuk dicolokkan. Untuk melakukannya, lakukan langkah-langkah berikut:

  1. Tulis perilaku Anda sendiri yang diturunkan dari DataContractSerializerOperationBehavior.

  2. Ganti dua metode CreateSerializer untuk mengembalikan serializer Anda sendiri (baik NetDataContractSerializer, DataContractSerializer dengan preserveObjectReferences diatur ke true, atau kustom Anda sendiri XmlObjectSerializer).

  3. Sebelum membuka host layanan atau membuat saluran klien, hapus perilaku DataContractSerializerOperationBehavior yang ada dan pasang kelas turunan kustom yang Anda buat di langkah sebelumnya.

Untuk informasi selengkapnya tentang konsep serialisasi lanjutan, lihat Serialisasi dan Deserialisasi.

Lihat juga