.NET Uzaktan İletişimden WCF'ye Taşınma

Bu makalede, .NET Uzaktan İletişimi kullanan bir uygulamanın Windows Communication Foundation (WCF) kullanmak üzere nasıl geçirildiğini açıklar. Bu ürünler arasındaki benzer kavramları karşılaştırır ve ardından WCF'de çeşitli yaygın Uzaktan İletişim senaryolarının nasıl gerçekleştirilmelidir açıklanmaktadır.

.NET Uzaktan İletişimi, yalnızca geriye dönük uyumluluk için desteklenen eski bir üründür. İstemci ve sunucu arasındaki ayrı güven düzeylerini koruyamadığından karma güven ortamlarında güvenli değildir. Örneğin, .NET Uzaktan İletişim uç noktasını hiçbir zaman İnternet'te veya güvenilmeyen istemcilerde kullanıma sunmamalısınız. Mevcut Uzaktan İletişim uygulamalarının daha yeni ve daha güvenli teknolojilere geçirilmesini öneririz. Uygulamanın tasarımı yalnızca HTTP kullanıyorsa ve RESTful ise Web API'sini ASP.NET öneririz. Daha fazla bilgi için bkz. web API'ASP.NET. Uygulama SOAP tabanlıysa veya TCP gibi Http dışı protokoller gerektiriyorsa WCF'yi öneririz.

.NET Uzaktan İletişimini WCF ile Karşılaştırma

Bu bölümde. .NET Uzaktan İletişimi'nin temel yapı taşları WCF eşdeğerleriyle karşılaştırılıyor. Bu yapı taşları daha sonra WCF'de bazı yaygın istemci-sunucu senaryoları oluşturmak için kullanacağız. Aşağıdaki grafik, .NET Uzaktan İletişimi ile WCF arasındaki temel benzerlikleri ve farkları özetlemektedir.

.NET uzaktan iletişim WCF
Sunucu türü Alt MarshalByRefObject Özniteliğiyle işaretle [ServiceContract]
Hizmet işlemleri Sunucu türündeki genel yöntemler Özniteliğiyle işaretle [OperationContract]
Serileştirme ISerializable veya [Serializable] DataContractSerializer veya XmlSerializer
Geçirilen nesneler Değere veya başvuruya göre Yalnızca değere göre
Hatalar/özel durumlar Serileştirilebilir özel durumlar FaultContract<TDetail>
İstemci proxy nesneleri Kesin olarak yazılan saydam proxy'ler MarshalByRefObjects'ten otomatik olarak oluşturulur Kesin türü belirlenmiş proxy'ler ChannelFactory<TChannel kullanılarak isteğe bağlı olarak oluşturulur>
Platform gerekli hem istemci hem de sunucu Microsoft OS ve .NET kullanmalıdır Platformlar arası
İleti biçimi Özel Endüstri standartları (örneğin, SOAP ve WS-*)

Sunucu Uygulama Karşılaştırması

.NET Uzaktan İletişiminde Sunucu Oluşturma

.NET Uzaktan İletişim sunucu türleri MarshalByRefObject'ten türetilmelidir ve istemcinin çağırabileceği yöntemleri tanımlamalıdır, örneğin:

public class RemotingServer : MarshalByRefObject  
{  
    public Customer GetCustomer(int customerId) { … }  
}  

Bu sunucu türünün genel yöntemleri, istemciler tarafından kullanılabilen genel sözleşme haline gelir. Sunucunun ortak arabirimi ile uygulaması arasında ayrım yoktur; bir tür her ikisini de işler.

Sunucu türü tanımlandıktan sonra, aşağıdaki örnekte olduğu gibi istemciler tarafından kullanılabilir hale getirilebilir:

TcpChannel channel = new TcpChannel(8080);  
ChannelServices.RegisterChannel(channel, ensureSecurity : true);  
RemotingConfiguration.RegisterWellKnownServiceType(  
    typeof(RemotingServer),
    "RemotingServer",
    WellKnownObjectMode.Singleton);  
Console.WriteLine("RemotingServer is running.  Press ENTER to terminate...");  
Console.ReadLine();  

Uzaktan iletişim türünü sunucu olarak kullanılabilir hale getirmenin yapılandırma dosyalarını kullanmak da dahil olmak üzere birçok yolu vardır. Bu yalnızca bir örnektir.

WCF'de Sunucu Oluşturma

WCF'deki eşdeğer adım iki tür oluşturmayı içerir: genel "hizmet sözleşmesi" ve somut uygulama. birincisi [ServiceContract] ile işaretlenmiş bir arabirim olarak bildirilir. İstemciler için kullanılabilen yöntemler [OperationContract] ile işaretlenir:

[ServiceContract]  
public interface IWCFServer  
{  
    [OperationContract]  
    Customer GetCustomer(int customerId);  
}  

Sunucunun uygulaması, aşağıdaki örnekte olduğu gibi ayrı bir somut sınıfta tanımlanır:

public class WCFServer : IWCFServer  
{  
    public Customer GetCustomer(int customerId) { … }  
}  

Bu türler tanımlandıktan sonra, WCF sunucusu aşağıdaki örnekte olduğu gibi istemciler tarafından kullanılabilir hale getirilebilir:

NetTcpBinding binding = new NetTcpBinding();  
Uri baseAddress = new Uri("net.tcp://localhost:8000/wcfserver");  
  
using (ServiceHost serviceHost = new ServiceHost(typeof(WCFServer), baseAddress))  
{  
    serviceHost.AddServiceEndpoint(typeof(IWCFServer), binding, baseAddress);  
    serviceHost.Open();  
  
    Console.WriteLine($"The WCF server is ready at {baseAddress}.");
    Console.WriteLine("Press <ENTER> to terminate service...");  
    Console.WriteLine();  
    Console.ReadLine();  
}  

Not

TCP, her iki örnekte de bunları mümkün olduğunca benzer tutmak için kullanılır. HTTP kullanan örnekler için bu konunun devamında yer alan senaryo kılavuzlarına bakın.

WCF hizmetlerini yapılandırmanın ve barındırmanın birçok yolu vardır. Bu, "şirket içinde barındırılan" olarak bilinen yalnızca bir örnektir. Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:

İstemci Uygulama Karşılaştırması

.NET Uzaktan İletişiminde İstemci Oluşturma

Bir .NET Uzaktan İletişim sunucusu nesnesi kullanıma sunulduktan sonra, aşağıdaki örnekte olduğu gibi istemciler tarafından kullanılabilir:

TcpChannel channel = new TcpChannel();  
ChannelServices.RegisterChannel(channel, ensureSecurity : true);  
RemotingServer server = (RemotingServer)Activator.GetObject(  
                            typeof(RemotingServer),
                            "tcp://localhost:8080/RemotingServer");  
  
RemotingCustomer customer = server.GetCustomer(42);  
Console.WriteLine($"Customer {customer.FirstName} {customer.LastName} received.");

Activator.GetObject() tarafından döndürülen RemotingServer örneği "saydam proxy" olarak bilinir. İstemcide RemotingServer türü için genel API'yi uygular, ancak tüm yöntemler farklı bir işlemde veya makinede çalışan sunucu nesnesini çağırır.

WCF'de İstemci Oluşturma

WCF'deki eşdeğer adım, proxy'yi açıkça oluşturmak için bir kanal fabrikası kullanmayı içerir. Uzaktan İletişim gibi, proxy nesnesi de aşağıdaki örnekte olduğu gibi sunucudaki işlemleri çağırmak için kullanılabilir:

NetTcpBinding binding = new NetTcpBinding();  
String url = "net.tcp://localhost:8000/wcfserver";  
EndpointAddress address = new EndpointAddress(url);  
ChannelFactory<IWCFServer> channelFactory =
    new ChannelFactory<IWCFServer>(binding, address);  
IWCFServer server = channelFactory.CreateChannel();  
  
Customer customer = server.GetCustomer(42);  
Console.WriteLine($"  Customer {customer.FirstName} {customer.LastName} received.");

Bu örnekte, uzaktan iletişim örneğine en çok benzediği için kanal düzeyinde programlama gösterilmektedir. Ayrıca Visual Studio'da istemci programlamayı basitleştirmek için kod oluşturan Hizmet Başvurusu Ekle yaklaşımı da kullanılabilir. Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:

Serileştirme Kullanımı

Hem .NET Uzaktan İletişimi hem de WCF, istemci ve sunucu arasında nesne göndermek için serileştirme kullanır, ancak bunlar şu önemli yollarla farklılık gösterir:

  1. Seri hale getirmek için farklı serileştiriciler ve kurallar kullanırlar.

  2. .NET Uzaktan İletişimi, bir katmandaki yöntem veya özellik erişiminin diğer katmanda kod yürütmesine izin veren ve güvenlik sınırları dışında olan "başvuruya göre" serileştirmeyi destekler. Bu özellik güvenlik açıklarını ortaya çıkarır ve uzaktan iletişim uç noktalarının hiçbir zaman güvenilmeyen istemcilere açıklanmaması gerektiğinin ana nedenlerinden biridir.

  3. Uzaktan İletişim tarafından kullanılan serileştirme geri çevirmedir (açıkça serileştirilmemesi gerekenleri dışlar) ve WCF serileştirmesi kabul edilir (hangi üyelerin seri hale getirileceğine açıkça işaret eder).

.NET uzaktan iletişiminde serileştirme

.NET Uzaktan İletişimi, istemci ve sunucu arasındaki nesneleri seri hale getirmek ve seri durumdan çıkarmak için iki yolu destekler:

  • Değere göre – nesnenin değerleri katman sınırları boyunca serileştirilir ve bu nesnenin yeni bir örneği diğer katmanda oluşturulur. Bu yeni örneğin yöntemlerine veya özelliklerine yapılan tüm çağrılar yalnızca yerel olarak yürütülür ve özgün nesneyi veya katmanı etkilemez.

  • Başvuruya göre – katman sınırları arasında özel bir "nesne başvurusu" serileştirilir. Bir katman bu nesnenin yöntemleri veya özellikleriyle etkileşime geçtiğinde, özgün katmandaki özgün nesneye geri iletişim kurar. Başvuruya göre nesneler iki yönde de akabilir: sunucudan istemciye veya istemciden sunucuya.

Uzaktan iletişimdeki değere göre türler aşağıdaki örnekte olduğu gibi [Serializable] özniteliğiyle işaretlenir veya ISerializable uygular:

[Serializable]  
public class RemotingCustomer  
{  
    public string FirstName { get; set; }  
    public string LastName { get; set; }  
    public int CustomerId { get; set; }  
}  

Başvuru türleri, aşağıdaki örnekte olduğu gibi MarshalByRefObject sınıfından türetilir:

public class RemotingCustomerReference : MarshalByRefObject  
{  
    public string FirstName { get; set; }  
    public string LastName { get; set; }  
    public int CustomerId { get; set; }  
}  

Uzaktan iletişimin yan başvuru nesnelerinin etkilerini anlamak son derece önemlidir. Katmanlardan biri (istemci veya sunucu) diğer katmana bir başvuru nesnesi gönderirse, tüm yöntem çağrıları nesnenin sahibi olan katmanda yeniden yürütülür. Örneğin, sunucu tarafından döndürülen bir başvuru nesnesi üzerinde çağıran bir istemci, sunucuda kod yürütür. Benzer şekilde, istemci tarafından sağlanan bir başvuru nesnesi üzerinde çağıran bir sunucu, istemcide kodu yeniden yürütür. Bu nedenle, .NET Uzaktan İletişimi'nin yalnızca tam güvenilir ortamlarda kullanılması önerilir. Genel bir .NET Uzaktan İletişim uç noktasının güvenilmeyen istemcilere açıklanması Uzaktan İletişim sunucusunu saldırılara karşı savunmasız hale getirir.

WCF'de serileştirme

WCF yalnızca değere göre serileştirmeyi destekler. İstemci ve sunucu arasında değiş tokuş yapmak için bir tür tanımlamanın en yaygın yolu aşağıdaki örnekteki gibidir:

[DataContract]  
public class WCFCustomer  
{  
    [DataMember]  
    public string FirstName { get; set; }  
  
    [DataMember]  
    public string LastName { get; set; }  
  
    [DataMember]  
    public int CustomerId { get; set; }  
}  

[DataContract] özniteliği bu türü, istemci ve sunucu arasında seri hale getirilebilen ve seri durumdan çıkarılabilen bir tür olarak tanımlar. [DataMember] özniteliği, serileştirileceği tek tek özellikleri veya alanları tanımlar.

WCF bir nesneyi katmanlar arasında gönderdiğinde, yalnızca değerleri serileştirir ve nesnenin diğer katmanda yeni bir örneğini oluşturur. Nesnenin değerleriyle tüm etkileşimler yalnızca yerel olarak gerçekleşir; diğer katmanla .NET Uzaktan İletişimi başvuru nesnelerinin yaptığı gibi iletişim kurmaz. Daha fazla bilgi için bkz . Serileştirme ve Seri Durumdan Çıkarma.

Özel Durum İşleme Özellikleri

.NET uzaktan iletişimindeki özel durumlar

Uzaktan iletişim sunucusu tarafından oluşan özel durumlar serileştirilir, istemciye gönderilir ve diğer özel durumlar gibi istemcide yerel olarak oluşturulur. Özel durumlar, Özel durum türü alt sınıflanarak ve [Serializable] ile işaretlenerek oluşturulabilir. Çoğu çerçeve özel durumu zaten bu şekilde işaretlenir ve çoğu sunucu tarafından oluşturulur, serileştirilir ve istemcide yeniden oluşturulur. Bu tasarım geliştirme sırasında kullanışlı olsa da, sunucu tarafı bilgileri istemeden istemciye açıklanabilir. Bu, uzaktan iletişimin yalnızca tam güvenilir ortamlarda kullanılmasının birçok nedenden biridir.

WCF'de Özel Durumlar ve Hatalar

WCF, yanlışlıkla bilgilerin açığa çıkmasına neden olabileceğinden sunucudan istemciye rastgele özel durum türlerinin döndürülmesine izin vermez. Bir hizmet işlemi beklenmeyen bir özel durum oluşturursa, istemcide genel amaçlı bir FaultException oluşturmasına neden olur. Bu özel durum, sorunun neden veya nerede oluştuğuyla ilgili hiçbir bilgi taşımaz ve bazı uygulamalar için bu yeterlidir. İstemciye daha zengin hata bilgileri iletmesi gereken uygulamalar bunu bir hata sözleşmesi tanımlayarak yapar.

Bunu yapmak için önce hata bilgilerini taşımak için bir [DataContract] türü oluşturun.

[DataContract]  
public class CustomerServiceFault  
{  
    [DataMember]  
    public string ErrorMessage { get; set; }  
  
    [DataMember]  
    public int CustomerId {get;set;}  
}  

Her hizmet işlemi için kullanılacak hata sözleşmesini belirtin.

[ServiceContract]  
public interface IWCFServer  
{  
    [OperationContract]  
    [FaultContract(typeof(CustomerServiceFault))]  
    Customer GetCustomer(int customerId);  
}  

Sunucu bir FaultException oluşturarak hata koşullarını bildirir.

throw new FaultException<CustomerServiceFault>(  
    new CustomerServiceFault() {
        CustomerId = customerId,
        ErrorMessage = "Illegal customer Id"
    });  

İstemci sunucuya her istekte bulunursa, hataları normal özel durumlar olarak yakalayabilir.

try  
{  
    Customer customer = server.GetCustomer(-1);  
}  
catch (FaultException<CustomerServiceFault> fault)  
{  
    Console.WriteLine($"Fault received: {fault.Detail.ErrorMessage}");
}  

Hata sözleşmeleri hakkında daha fazla bilgi için bkz FaultException. .

Güvenlikle İlgili Dikkat Edilmesi Gerekenler

.NET uzaktan iletişiminde güvenlik

Bazı .NET Uzaktan İletişim kanalları, kanal katmanında (IPC ve TCP) kimlik doğrulaması ve şifreleme gibi güvenlik özelliklerini destekler. HTTP kanalı, hem kimlik doğrulaması hem de şifreleme için Internet Information Services'e (IIS) dayanır. Bu desteğe rağmen, .NET Uzaktan İletişimi'ni güvenli olmayan bir iletişim protokolü olarak değerlendirmeniz ve bunu yalnızca tam güvenilir ortamlarda kullanmanız gerekir. Genel uzaktan iletişim uç noktasını hiçbir zaman İnternet'te veya güvenilmeyen istemcilerde kullanıma sunma.

WCF'de Güvenlik

WCF, kısmen .NET Uzaktan İletişimi'nde bulunan güvenlik açığı türlerini ele almak için güvenlik göz önünde bulundurularak tasarlanmıştır. WCF hem aktarım hem de ileti düzeyinde güvenlik sunar ve kimlik doğrulaması, yetkilendirme, şifreleme vb. için birçok seçenek sunar. Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:

WCF'ye geçiş

Uzaktan İletişimden WCF'ye Neden Geçiş Yapılır?

  • .NET Uzaktan İletişimi eski bir üründür. .NET uzaktan iletişiminde açıklandığı gibi, eski bir ürün olarak kabul edilir ve yeni geliştirme için önerilmez. Yeni ve mevcut uygulamalar için WCF veya ASP.NET Web API'si önerilir.

  • WCF, platformlar arası standartlar kullanır. WCF, platformlar arası birlikte çalışabilirlik düşünülerek tasarlanmıştır ve birçok endüstri standartlarını (SOAP, WS-Security, WS-Trust vb.) destekler. WCF hizmeti, Windows dışındaki işletim sistemlerinde çalışan istemcilerle birlikte çalışabilir. Uzaktan iletişim öncelikle hem sunucu hem de istemci uygulamalarının bir Windows işletim sisteminde .NET Framework kullanarak çalıştığı ortamlar için tasarlanmıştır.

  • WCF'nin yerleşik güvenliği vardır. WCF, güvenlik göz önünde bulundurularak tasarlanmıştır ve kimlik doğrulaması, aktarım düzeyi güvenliği, ileti düzeyi güvenlik vb. için birçok seçenek sunar. Uzaktan iletişim, uygulamaların birlikte çalışabilmesini kolaylaştırmak için tasarlanmıştır ancak güvenilir olmayan ortamlarda güvenli olacak şekilde tasarlanmamıştır. WCF hem güvenilir hem de güvenilir olmayan ortamlarda çalışacak şekilde tasarlanmıştır.

Geçiş Öneriler

.NET uzaktan iletişiminden WCF'ye geçiş için önerilen adımlar şunlardır:

  • Hizmet sözleşmesini oluşturun. Hizmet arabirimi türlerinizi tanımlayın ve [ServiceContract] özniteliğiyle işaretleyin. İstemcilerin [OperationContract] ile çağırmasına izin verilecek tüm yöntemleri işaretleyin.

  • Veri sözleşmesini oluşturun. Sunucu ve istemci arasında değiş tokuş edilecek veri türlerini tanımlayın ve bunları [DataContract] özniteliğiyle işaretleyin. İstemcinin [DataMember] ile kullanmasına izin verilecek tüm alanları ve özellikleri işaretleyin.

  • Hata sözleşmesini oluşturun (isteğe bağlı). Hatalarla karşılaşıldığında sunucu ve istemci arasında değiş tokuş edilecek türleri oluşturun. Bu türleri serileştirilebilir hale getirmek için [DataContract] ve [DataMember] ile işaretleyin. [OperationContract] ile işaretlediğiniz tüm hizmet işlemleri için, döndürebilecekleri hataları belirtmek için bunları [FaultContract] ile de işaretleyin.

  • Hizmeti yapılandırın ve barındırın. Hizmet sözleşmesi oluşturulduktan sonra bir sonraki adım, hizmeti bir uç noktada kullanıma açmak için bir bağlama yapılandırmaktır. Daha fazla bilgi için bkz . Uç Noktalar: Adresler, Bağlamalar ve Sözleşmeler.

Uzaktan İletişim uygulaması WCF'ye geçirildikten sonra .NET Uzaktan İletişimi bağımlılıklarını kaldırmak yine de önemlidir. Bu, uzaktan iletişim güvenlik açıklarının uygulamadan kaldırılmasını sağlar. Bu adımlar şunlardır:

  • MarshalByRefObject kullanımını sonlandırın. MarshalByRefObject türü yalnızca Uzaktan İletişim için vardır ve WCF tarafından kullanılmaz. MarshalByRefObject alt sınıfı olan tüm uygulama türleri kaldırılmalıdır veya değiştirilmelidir.

  • [Serializable] ve ISerializable kullanımını sonlandırın. [Serializable] özniteliği ve ISerializable arabirimi ilk olarak güvenilen ortamlarda türleri seri hale getirmek için tasarlanmıştır ve Uzaktan İletişim tarafından kullanılır. WCF serileştirmesi, [DataContract] ve [DataMember] ile işaretlenen türleri kullanır. Bir uygulama tarafından kullanılan veri türleri [DataContract] kullanacak şekilde değiştirilmeli ve ISerializable veya [Serializable] kullanılmamalıdır.

Geçiş Senaryoları

Şimdi WCF'de aşağıdaki yaygın Uzaktan İletişim senaryolarını nasıl gerçekleştireceğine bakalım:

  1. Sunucu istemciye değere göre bir nesne döndürür

  2. Sunucu, istemciye bir nesne başvurusu döndürür

  3. İstemci, sunucuya değere göre bir nesne gönderir

Not

WCF'de istemciden sunucuya nesne başvurusu göndermeye izin verilmez.

Bu senaryoları okurken. .NET Uzaktan İletişimi için temel arabirimlerimizin aşağıdaki örneğe benzer olduğunu varsayalım. .NET Uzaktan İletişim uygulaması burada önemli değildir çünkü yalnızca wcf kullanarak eşdeğer işlevlerin nasıl uygulandığını göstermek istiyoruz.

public class RemotingServer : MarshalByRefObject  
{  
    // Demonstrates server returning object by-value  
    public Customer GetCustomer(int customerId) {…}  
  
    // Demonstrates server returning object by-reference  
    public CustomerReference GetCustomerReference(int customerId) {…}  
  
    // Demonstrates client passing object to server by-value  
    public bool UpdateCustomer(Customer customer) {…}  
}  

Senaryo 1: Hizmet Değere Göre Nesne Döndürür

Bu senaryoda, istemciye değere göre bir nesne döndüren bir sunucu gösterilir. WCF her zaman sunucudaki nesneleri değere göre döndürür, bu nedenle aşağıdaki adımlarda normal bir WCF hizmetinin nasıl derlandığı açıklanmaktadır.

  1. WCF hizmeti için bir genel arabirim tanımlayarak başlayın ve [ServiceContract] özniteliğiyle işaretleyin. İstemcimizin çağıracağı sunucu tarafı yöntemlerini tanımlamak için [OperationContract] kullanırız.

    [ServiceContract]  
    public interface ICustomerService  
    {  
        [OperationContract]  
        Customer GetCustomer(int customerId);  
    
        [OperationContract]  
        bool UpdateCustomer(Customer customer);  
    }  
    
  2. Sonraki adım, bu hizmet için veri sözleşmesi oluşturmaktır. Bunu [DataContract] özniteliğiyle işaretlenmiş sınıflar (arabirimler değil) oluşturarak yaparız. hem istemci hem de sunucu tarafından görünmesini istediğimiz tek tek özellikler veya alanlar [DataMember] ile işaretlenir. Türetilmiş türlere izin vermek istiyorsak, bunları tanımlamak için [KnownType] özniteliğini kullanmamız gerekir. WCF'nin bu hizmet için seri hale getirmesine veya seri durumdan çıkarılmasına izin verecek tek türler, hizmet arabirimindeki türler ve bu "bilinen türler"dir. Bu listede bulunmayan başka bir türü değiştirme girişimi reddedilir.

    [DataContract]  
    [KnownType(typeof(PremiumCustomer))]  
    public class Customer  
    {  
        [DataMember]  
        public string FirstName { get; set; }  
    
        [DataMember]  
        public string LastName { get; set; }  
    
        [DataMember]  
        public int CustomerId { get; set; }  
    }  
    
    [DataContract]  
    public class PremiumCustomer : Customer
    {  
        [DataMember]  
        public int AccountId { get; set; }  
    }  
    
  3. Ardından hizmet arabirimi için uygulamayı sağlayacağız.

    public class CustomerService : ICustomerService  
    {  
        public Customer GetCustomer(int customerId)  
        {  
            // read from database  
        }  
    
        public bool UpdateCustomer(Customer customer)  
        {  
            // write to database  
        }  
    }  
    
  4. WCF hizmetini çalıştırmak için, belirli bir WCF bağlamasını kullanarak bu hizmet arabirimini belirli bir URL'de kullanıma sunan bir uç nokta bildirmemiz gerekir. Bu genellikle sunucu projesinin web.config dosyasına aşağıdaki bölümler eklenerek yapılır.

    <configuration>  
      <system.serviceModel>  
        <services>  
          <service name="Server.CustomerService">  
            <endpoint address="http://localhost:8083/CustomerService"  
                      binding="basicHttpBinding"  
                      contract="Shared.ICustomerService" />  
          </service>  
        </services>  
      </system.serviceModel>  
    </configuration>  
    
  5. WcF hizmeti daha sonra aşağıdaki kodla başlatılabilir:

    ServiceHost customerServiceHost = new ServiceHost(typeof(CustomerService));  
        customerServiceHost.Open();  
    

    Bu ServiceHost başlatıldığında, uygun sözleşmeyi, bağlamayı ve uç noktayı oluşturmak için web.config dosyasını kullanır. Yapılandırma dosyaları hakkında daha fazla bilgi için bkz . Yapılandırma Dosyalarını Kullanarak Hizmetleri Yapılandırma. Sunucuyu başlatmanın bu stili kendi kendine barındırma olarak bilinir. WCF hizmetlerini barındırmaya yönelik diğer seçenekler hakkında daha fazla bilgi edinmek için bkz . Barındırma Hizmetleri.

  6. İstemci projesinin app.config dosyasının hizmetin uç noktası için eşleşen bağlama bilgilerini bildirmesi gerekir. Visual Studio'da bunu yapmanın en kolay yolu, app.config dosyasını otomatik olarak güncelleştiren Hizmet Başvurusu Ekle'yi kullanmaktır. Alternatif olarak, bu değişiklikler el ile eklenebilir.

    <configuration>  
      <system.serviceModel>  
        <client>  
          <endpoint name="customerservice"  
                    address="http://localhost:8083/CustomerService"  
                    binding="basicHttpBinding"  
                    contract="Shared.ICustomerService"/>  
        </client>  
      </system.serviceModel>  
    </configuration>  
    

    Hizmet Başvurusu Ekle'yi kullanma hakkında daha fazla bilgi için bkz. Nasıl yapılır: Hizmet Başvurusu Ekleme, Güncelleştirme veya Kaldırma.

  7. Artık istemciden WCF hizmetini çağırabiliriz. Bunu, söz konusu hizmet için bir kanal fabrikası oluşturarak, kanal isteyerek ve doğrudan bu kanalda istediğimiz yöntemi çağırarak yaparız. Kanal hizmetin arabirimini uyguladığından ve temel istek/yanıt mantığını bizim için işlediğinden bunu yapabiliriz. Bu yöntem çağrısından döndürülen değer, sunucunun yanıtının seri durumdan çıkarılmış kopyasıdır.

    ChannelFactory<ICustomerService> factory =  
        new ChannelFactory<ICustomerService>("customerservice");  
    ICustomerService service = factory.CreateChannel();  
    Customer customer = service.GetCustomer(42);  
    Console.WriteLine($"  Customer {customer.FirstName} {customer.LastName} received.");
    

WCF tarafından sunucudan istemciye döndürülen nesneler her zaman değere göredir. Nesneler, sunucu tarafından gönderilen verilerin seri durumdan çıkarılmış kopyalarıdır. İstemci, geri çağırmalar aracılığıyla sunucu kodunu çağırma tehlikesi olmadan bu yerel kopyalardaki yöntemleri çağırabilir.

Senaryo 2: Sunucu Başvuruya Göre Nesne Döndürür

Bu senaryo, sunucunun istemciye başvuruyla bir nesne sağladığını gösterir. .NET Uzaktan İletişimi'nde bu, marshalByRefObject'ten türetilen ve başvuruyla seri hale getirilen her tür için otomatik olarak işlenir. Bu senaryoya örnek olarak, birden çok istemcinin bağımsız oturumlu sunucu tarafı nesneleri olması sağlanır. Daha önce de belirtildiği gibi, WCF hizmeti tarafından döndürülen nesneler her zaman değere göredir, bu nedenle başvuruya göre nesnenin doğrudan eşdeğeri yoktur, ancak nesne kullanarak başvuru semantiğine benzer bir EndpointAddress10 şey elde etmek mümkündür. Bu, istemci tarafından sunucuda oturumlu bir başvuru nesnesi elde etmek için kullanılabilecek serileştirilebilir bir değere göre nesnesidir. Bu, bağımsız oturumlu sunucu tarafı nesneleri olan birden çok istemciye sahip olma senaryosuna olanak tanır.

  1. İlk olarak, oturumlu nesnenin kendisine karşılık gelen bir WCF hizmet sözleşmesi tanımlamamız gerekir.

    [ServiceContract(SessionMode = SessionMode.Allowed)]  
        public interface ISessionBoundObject  
        {  
            [OperationContract]  
            string GetCurrentValue();  
    
            [OperationContract]  
            void SetCurrentValue(string value);  
        }  
    

    İpucu

    Oturumlu nesnenin [ServiceContract] ile işaretlendiğinden ve bunu normal bir WCF hizmet arabirimi haline getirildiğinden emin olun. SessionMode özelliğinin ayarlanması, bunun oturumlu bir hizmet olacağını gösterir. WCF'de oturum, iki uç nokta arasında gönderilen birden çok iletiyi ilişkilendirmenin bir yoludur. Bu, bir istemci bu hizmete bir bağlantı edindikten sonra istemci ile sunucu arasında bir oturum kurulacağı anlamına gelir. İstemci, bu tek oturumdaki tüm etkileşimleri için sunucu tarafı nesnesinin tek bir benzersiz örneğini kullanır.

  2. Ardından, bu hizmet arabiriminin uygulanmasını sağlamamız gerekir. [ServiceBehavior] ile ifade edip InstanceContextMode ayarını yaparak WCF'ye her oturum için bu tür benzersiz bir örneği kullanmak istediğimizi söyleriz.

    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]  
        public class MySessionBoundObject : ISessionBoundObject  
        {  
            private string _value;  
    
            public string GetCurrentValue()  
            {  
                return _value;  
            }  
    
            public void SetCurrentValue(string val)  
            {  
                _value = val;  
            }  
    
        }  
    
  3. Şimdi bu oturumlu nesnenin örneğini almak için bir yönteme ihtiyacımız var. Bunu, EndpointAddress10 nesnesi döndüren başka bir WCF hizmet arabirimi oluşturarak yaparız. Bu, istemcinin oturumlu nesneyi oluşturmak için kullanabileceği bir uç noktanın serileştirilebilir biçimidir.

    [ServiceContract]  
        public interface ISessionBoundFactory  
        {  
            [OperationContract]  
            EndpointAddress10 GetInstanceAddress();  
        }  
    

    Ve bu WCF hizmetini uygularız:

    public class SessionBoundFactory : ISessionBoundFactory  
        {  
            public static ChannelFactory<ISessionBoundObject> _factory =
                new ChannelFactory<ISessionBoundObject>("sessionbound");  
    
            public SessionBoundFactory()  
            {  
            }  
    
            public EndpointAddress10 GetInstanceAddress()  
            {  
                IClientChannel channel = (IClientChannel)_factory.CreateChannel();  
                return EndpointAddress10.FromEndpointAddress(channel.RemoteAddress);  
            }  
        }  
    

    Bu uygulama, oturumlu nesneler oluşturmak için tek kanallı bir fabrika tutar. GetInstanceAddress() çağrıldığında, bir kanal oluşturur ve bu kanalla ilişkilendirilmiş uzak adrese etkili bir şekilde işaret eden bir EndpointAddress10 nesnesi oluşturur. EndpointAddress10 yalnızca istemciye değere göre döndürülebilen bir veri türüdür.

  4. Aşağıdaki örnekte gösterildiği gibi aşağıdaki iki işlemi yaparak sunucunun yapılandırma dosyasını değiştirmemiz gerekir:

    1. Oturumlu nesnenin uç noktasını açıklayan bir <istemci> bölümü bildirin. Sunucu bu durumda bir istemci olarak da davrandığından bu gereklidir.

    2. Fabrika ve oturumlu nesne için uç noktaları bildirin. Bu, istemcinin EndpointAddress10'u almak ve oturumlu kanalı oluşturmak için hizmet uç noktalarıyla iletişim kurmasına izin vermek için gereklidir.

    <configuration>  
      <system.serviceModel>  
         <client>  
          <endpoint name="sessionbound"  
                    address="net.tcp://localhost:8081/SessionBoundObject"  
                    binding="netTcpBinding"  
                    contract="Shared.ISessionBoundObject"/>  
        </client>  
        <services>  
          <service name="Server.CustomerService">  
            <endpoint address="http://localhost:8083/CustomerService"  
                      binding="basicHttpBinding"  
                      contract="Shared.ICustomerService" />  
          </service>  
          <service name="Server.MySessionBoundObject">  
            <endpoint address="net.tcp://localhost:8081/SessionBoundObject"  
                      binding="netTcpBinding"  
                      contract="Shared.ISessionBoundObject" />  
          </service>  
          <service name="Server.SessionBoundFactory">  
            <endpoint address="net.tcp://localhost:8081/SessionBoundFactory"  
                      binding="netTcpBinding"  
                      contract="Shared.ISessionBoundFactory" />  
          </service>  
        </services>  
      </system.serviceModel>  
    </configuration>  
    

    Ardından şu hizmetleri başlatabiliriz:

    ServiceHost factoryHost = new ServiceHost(typeof(SessionBoundFactory));  
    factoryHost.Open();  
    
    ServiceHost sessionHost = new ServiceHost(typeof(MySessionBoundObject));  
    sessionHost.Open();  
    
  5. İstemciyi, projesinin app.config dosyasında aynı uç noktaları bildirerek yapılandırıyoruz.

    <configuration>  
      <system.serviceModel>  
        <client>  
          <endpoint name="customerservice"  
                    address="http://localhost:8083/CustomerService"  
                    binding="basicHttpBinding"  
                    contract="Shared.ICustomerService"/>  
          <endpoint name="sessionbound"  
                    address="net.tcp://localhost:8081/SessionBoundObject"  
                    binding="netTcpBinding"  
                    contract="Shared.ISessionBoundObject"/>  
          <endpoint name="factory"  
                    address="net.tcp://localhost:8081/SessionBoundFactory"  
                    binding="netTcpBinding"  
                    contract="Shared.ISessionBoundFactory"/>  
        </client>  
      </system.serviceModel>  
    </configuration>  
    
  6. Bu oturumlu nesneyi oluşturmak ve kullanmak için istemcinin aşağıdaki adımları gerçekleştirmesi gerekir:

    1. ISessionBoundFactory hizmetine bir kanal oluşturun.

    2. EndpointAddress10 almak üzere bu hizmeti çağırmak için bu kanalı kullanın.

    3. EndpointAddress10 kullanarak oturumlu bir nesne almak üzere bir kanal oluşturun.

    4. Birden çok çağrıda aynı örnek olarak kaldığını göstermek için oturumlu nesneyle etkileşime geçin.

    ChannelFactory<ISessionBoundFactory> channelFactory =
        new ChannelFactory<ISessionBoundFactory>("factory");  
    ISessionBoundFactory sessionFactory = channelFactory.CreateChannel();  
    
    EndpointAddress10 address1 = sessionFactory.GetInstanceAddress();  
    EndpointAddress10 address2 = sessionFactory.GetInstanceAddress();  
    
    ChannelFactory<ISessionBoundObject> sessionObjectFactory1 =
        new ChannelFactory<ISessionBoundObject>(new NetTcpBinding(),
                                                address1.ToEndpointAddress());  
    ChannelFactory<ISessionBoundObject> sessionObjectFactory2 =
        new ChannelFactory<ISessionBoundObject>(new NetTcpBinding(),
                                                address2.ToEndpointAddress());  
    
    ISessionBoundObject sessionInstance1 = sessionObjectFactory1.CreateChannel();  
    ISessionBoundObject sessionInstance2 = sessionObjectFactory2.CreateChannel();  
    
    sessionInstance1.SetCurrentValue("Hello");  
    sessionInstance2.SetCurrentValue("World");  
    
    if (sessionInstance1.GetCurrentValue() == "Hello" &&  
        sessionInstance2.GetCurrentValue() == "World")  
    {  
        Console.WriteLine("sessionful server object works as expected");  
    }  
    

WCF nesneleri her zaman değere göre döndürür, ancak EndpointAddress10 kullanarak başvuruya göre semantiğin eşdeğerini desteklemek mümkündür. Bu, istemcinin oturumlu bir WCF hizmet örneği istemesine izin verir ve bundan sonra diğer tüm WCF hizmetleri gibi bu örnekle etkileşim kurabilir.

Senaryo 3: İstemci Sunucuya Değere Göre Örnek Gönderiyor

Bu senaryo, istemcinin sunucuya değere göre ilkel olmayan bir nesne örneği gönderdiğini gösterir. WCF nesneleri yalnızca değere göre gönderdiği için, bu senaryo normal WCF kullanımını gösterir.

  1. Senaryo 1'den aynı WCF Hizmetini kullanın.

  2. İstemciyi kullanarak yeni bir değere göre nesnesi (Customer) oluşturun, ICustomerService hizmetiyle iletişim kurmak için bir kanal oluşturun ve nesneyi ona gönderin.

    ChannelFactory<ICustomerService> factory =  
        new ChannelFactory<ICustomerService>("customerservice");  
    ICustomerService service = factory.CreateChannel();  
    PremiumCustomer customer = new PremiumCustomer {
    FirstName = "Bob",
    LastName = "Jones",
    CustomerId = 43,
    AccountId = 99};  
    bool success = service.UpdateCustomer(customer);  
    Console.WriteLine($"  Server returned {success}.");
    

    Müşteri nesnesi seri hale getirilir ve sunucuya gönderilir ve burada bu nesnenin yeni bir kopyasına seri durumdan çıkarılır.

    Not

    Bu kod, türetilmiş bir tür (PremiumCustomer) göndermeyi de gösterir. Hizmet arabirimi bir Customer nesnesi bekler, ancak Customer sınıfındaki [KnownType] özniteliği premiumCustomer'a da izin verildiğini belirtir. WCF, bu hizmet arabirimi aracılığıyla başka bir türü seri hale getirme veya seri durumdan çıkarma girişiminde başarısız olur.

Normal WCF veri değişimleri değere göredir. Bu, bu veri nesnelerinden birinde çağrılan yöntemlerin yalnızca yerel olarak yürütülmesini garanti eder; diğer katmanda kod çağırmaz. Sunucudan döndürülen başvuru nesnelerine benzer bir şey elde etmek mümkün olsa da, istemcinin sunucuya bir by-reference nesnesi geçirmesi mümkün değildir. wcf'de çift yönlü hizmet kullanılarak istemci ve sunucu arasında ileri geri konuşma gerektiren bir senaryo elde edilebilir. Daha fazla bilgi için bkz . Çift Yönlü Hizmetler.

Özet

.NET Uzaktan İletişimi, yalnızca tam güvenilir ortamlarda kullanılmak üzere tasarlanmış bir iletişim çerçevesidir. Eski bir üründür ve yalnızca geriye dönük uyumluluk için desteklenir. Yeni uygulamalar oluşturmak için kullanılmamalıdır. Buna karşılık WCF, güvenlik göz önünde bulundurularak tasarlanmıştır ve yeni ve mevcut uygulamalar için önerilir. Microsoft, mevcut Uzaktan İletişim uygulamalarının WCF veya ASP.NET Web API'sini kullanacak şekilde geçirilmesini önerir.