Introduction Windows Communication Foundation Part3
Posted On Sunday, February 15, 2009 at at 6:48 PM by UnknownBài viết này được dịch từ Chapter 25 - INTRODUCING WINDOWS COMMUNICATION FOUNDATION của sách Pro C# 2008 and the NET 3.5 Platform Fourth Edition.
Các bạn đang xem bài viết về Memory Management trong .NET từ blog của Nguyễn Thoại (http://nthoai.blogspot.com)
The ABCs of WCF
- Các chương trình host(server) và client trong WCF giao tiếp với nhau qua 3 thành phần mà viết tắt của chúng là 3 chữ cái ABC cho dễ nhớ, chúng gồm: address, binding và contract.
- Address: địa chỉ của service. Trong code, giá trị này được thể hiện bằng một System.Uri; tuy nhiên, người ta thường sử dụng file config để lưu giá trị của nó.
- Binding: WCF hỗ trợ nhiều kiểu bindings. Bindings là một khái niệm trong WCF bao gồm các thành phần như network protocol, encoding và transport layer để chương trình server và client có thể giao tiếp với nhau. Giả sử có một ống dẫn giữa A và B thì binding sẽ bao gồm các thông tin như cỡ ống, loại vật chất được truyền trong ống và ống được chôn hay được treo trên trần
- Contract: Những mô tả của các method được exposed từ WCF service. Thực ra không chỉ có các mô tả của method, mà còn mô tả của các dữ liệu (data contract), các kiểu trả về, các custom type.
- Developer không phải xác định các thành phần trên theo đúng thứ tự ABC mà có thể bắt đầu bằng bất cứ cái nào. Thông thường, một WCF developer sẽ bắt đầu viết các contract cho service rồi mới đến hai thứ còn lại. Trước khi chúng ta làm thử một WCF application, hãy xem qua một chút về ABCs:
Understanding WCF Contracts
- Contract là nhân tố chính để build các WCF service. Tuy không cần bắt buộc, nhưng phần lớn các WCF applications sẽ bắt đầu bằng việc khai báo các .NET interface dùng để thể hiện các method mà service của bạn expose ra ngoài. Những interface mô tả một WCF contract được gọi là “service contracts”, còn những classes (hay structures) implement các interface này thì gọi là “service types”.
- WCF service contracts được đánh dấu bằng nhiều attributes khác nhau, phần lớn những attributes thường sử dụng nằm trong namespace System.ServiceModel. Đặc biệt khi các members của một service contract chỉ chứa những simple data types như kiểu số, Booleans, string, bạn có thể build một WCF service chỉ bằng 2 attributes là [ServiceContract] và [OperationContract]. Ngược lại, nếu các members này có expose ra những custome types, bạn phải sử dụng đến một số attribute trong namespace System.Runtime.Serialization như [DataMember] và [DataContract].
- Nói một cách nghiêm túc, bạn không phải sử dụng CLR interfaces để định nghĩa các WCF contract. Bạn vẫn có thể sử dụng các attributes trên để applied cho các public members của những public classes (hoặc structure). Tuy nhiên, để có thể tận dụng được các thế mạnh của interface-based-programming , chúng ta nên sử dụng interface để mô tả các WCF contract.
Understanding WCF Bindings
- Khi một hoặc nhiều contract đã được khai báo và implement xong bên trong service library của bạn, bước tiếp theo sẽ là build một chương trình để host WCF service. Như đã đề cập ở các phần trước, bạn có nhiều cách để host một service, nhưng tất các những cách này đều cần xác định rõ cách bindings để từ đó, những remote callers có thể access và sử dụng các function của service bạn build.
- Có thể tùy chọn giữa các kiều binding khác nhau là điểm khác biệt giữa WCF và .NET remoting/hay XML web service. WCF hỗ trợ nhiều kiểu bindings khác nhau, mỗi loại phù hợp với những yêu cầu riêng. Thậm chí khi không tìm được kiểu binding nào phù hợp, bạn có thể tạo riêng một kiểu binding mới bằng cách extend lớp CustomBinding. Nói tóm lại, một WCF binding sẽ được xác định bởi các yếu tố sau đây:
- Các contracts được implement bởi service tương ứng
- Transport layer để trao đổi các message (HTTP, MSMQ, named pipes, TCP)
- Các channels được dùng khi transport (one-way, request-reply, duplex)
- Cơ chế mã hóa được dùng (XML, binary, etc)
- Các web service protocols khác (tùy loại binding) như WS-Security, WS-Transaction, WS-Reliability, v.v.
HTTP-Based Bindings
- Các option như BasicHttpBinding, WSHttpBinding, WSDualHttpBinding, và WSFederationHttpBinding sẽ được dùng khi bạn muốn expose các contract theo kiểu XML web service. Rõ ràng rằng khi muốn nhiều nguồn khác nhau có thể dùng được service của bạn bất kể hệ điều hành hay công nghệ như thế nào thì ta nên hướng tới các lựa chọn trên, bởi vì những kiểu bindings này sẽ mã hóa dữ liệu dựa trên chuẩn XML như web service thông thường và sẽ được truyền trên giao thức HTTP.
- Bảng dưới đây là các class Binding tương ứng với các element của nó để sử dụng trong file config:
Binding Class | Binding Element | Ý nghĩa |
---|---|---|
BasicHttpBinding | <basicHttpBinding> | Được sử dụng để build một WS-Basic Profile (WS-IBasic Profile 1.1)–conformant WCF service. Loại binding này sử dụng HTTP để truyền dữ liệu dưới dạng Text/XML |
WSHttpBinding | <wsHttpBinding> | Tương tự nhu BasicHttpBinding nhưng hỗ trợ nhiều feature hơn như transactions, reliable session và WS-Addressing |
WSDualHttpBinding | <wsDualHttpBinding> | Tương tự như WSHttpBinding nhưng được dùng cho duplex contracts (client và server có thể send message 2 chiều cho nhau. Loại binding này chỉ support SOAP security và yêu cầu reliable messaging |
WSFederationHttpBinding | <wsFederationHttpBinding> | Là một loại binding rất đáng tin cậy hỗ trợ WS-Federation protocol |
- Như tên đã mô tả, BasicHttpBindings là kiểu binding đơn giản nhất trong các kiểu binding cùng loại. Đặc biệt, loại binding này sẽ đảm bảo rằng WCF service của bạn phù hợp với một đặc tả tên là WS-IBasic Profile 1.1. Lý do chính để sử dụng loại binding này là để maintain những application cũ, để chúng có thể tương tác với service của bạn vì những application này được xây dựng từ trước chỉ gọi được những ASP.NET web services kiểu cũ.
- WSHttpBinding protocol không chỉ support một số nhỏ những WS-* như transaction, security và reliable session, nó còn hỗ trợ khả năng đọc những dữ liệu mã hóa Message Transmission Optimization Mechanism (MTOM).
- Lợi ích chính của WSDualHttpBinding là nó cho phép caller và sender giao tiếp với nhau bằng duplex messaging, nghĩa là chúng có thể giao tiếp hai chiều với nhau. Khi chọn WSDualHttpBinding, bạn có thể hook vào WCF publish/ subscribe event model.
- Cuối cùng, WSFederationHttpBinding là một giao thức dựa trên web service mà bạn nên sử dụng khi vấn đề security được chú trọng. Loại binding này hỗ trợ WS-Trust, WS-Security và WS-SecureConversation, chúng là những đặc tả tiêu biểu trong WCF CardSpace APIs.
TCP-Based Bindings
- Nếu bạn đang build một distributed application để chạy với .NET 3.0/3.5 libraries (mặt khác, tất cả các máy đều sử dụng Windows XP, Windows Server 2003, hoặc Windows Vista), bạn có thể làm tăng performance bằng cách đổi từ web service bindings thành TCP binding, tất cả data sẽ được encoded ở dạng binary thay vì XML. Khi sử dụng các bindings ở bảng dưới đây, client và host phải là .NET applications:
Binding Class | Binding Element | Ý nghĩa |
---|---|---|
NetNamedPipeBinding | <netNamedPipeBinding> | Là một loại binding bảo mật cao và rất đáng tin cậy được sư dụng cho những .NET application trong cùng một máy tính. |
NetPeerTcpBinding | <netPeerTcpBinding> | Là loại binding hỗ trợ giao thức Peer to peer. |
NetTcpBinding | <netTcpBinding> | Là một loại binding tối ưu và có tính bảo mật cao, được sử dụng cho những .NET applications trên những máy khác nhau có thể giao tiếp với nhau. |
Các bạn đang xem bài viết về Introduction WCF từ blog của Nguyễn Thoại (http://nthoai.blogspot.com)
- NetTcpBinding class sử dụng TCP để trao đổi dữ liệu giữa client và các WCF service. Như đã nói, cách này tất nhiên sẽ tăng performance so với web service protocol, nhưng như vậy bạn đang bị giới hạn sản phẩm của mình như các in-house application. Thêm nữa, NetTcpBinding còn hỗ trợ transactions, reliable sessions và secure communications.
- Giống như NetTcpBinding, NetNamedPipeBinding hỗ trợ transactions, reliable sessions và secure communications, nhưng nó không hỗ trợ việc giao tiếp trên 2 máy khác nhau. Nhưng nếu bạn muốn chọn một giao thức nhanh nhất để truyền dữ liệugiữa các WCF applications trên cùng một máy thì đây là lựa chọn tối ưu nhất. Ngoài ra, nếu quan tâm đến NetPeerTcpBinding, hãy tham khảo .NET Framework 3.5 documentation.
MSMQ-Based Bindings
- Cuối cùng, nếu bạn định kết hợp sử dụng Microsoft MSMQ server thì NetMsmqBinding và MsmqIntegrationBinding là những thứ bạn nên tìm hiểu. 2 loại bindings này sẽ không được đề cập chi tiết trong bài này, nhưng bảng dưới đây sẽ thể hiện sơ lượt chức năng của 2 loại bindings này:
Binding Class | Binding Element | Ý nghĩa |
---|---|---|
MsmqIntegrationBinding | <msmqIntegrationBinding> | Loại binding này có thể được sử dụng để viết những WCF applications có thể gửi/nhận những message tới những MSMQ application |
NetMsmqBinding | <netMsmqBinding> | Loại queue binding này phù hợp với những .NET application cần giao tiếp với nhau từ những machine khác nhau. |
Understanding WCF Addresses
- Khi contract và bindings đều đã được xác định, thì thành phần cuối cùng là address. Cũng như contract và bindings thì address cũng khá quan trọng, nếu chúng ta config sai thì remote callers sẽ không tài nào sử dụng được các services. Như những thành phần khác trong WCF, một address cũng có thể được hard-code bằng một giá trị System.Uri hoặc có thể sử dụng file config.
- Dù sử dụng cách nào, định dạng chính xác của WCF address sẽ khác nhau phụ thuộc vào loại binding bạn lựa chọn. WCF addresses có thể xác định những thông tin sau:
- Scheme: Transport protocol (HTTP, v.v.)
- MachineName: domain đầy đủ của server host service
- Port: thông tin này là tùy chọn trong hầu hết các trường hợp. Ví dụ như giá trị mặc định là 80 sẽ được hiểu khi chọn HTTP bindings
- Path: đường dẫn tới WCF service
- Những thông tin này có thể được mô tả theo một template sau đây (giá trị Port là tùy chọn, vì một số loại bindings sẽ không cần sử dụng giá trị port):
- Khi bạn sử dụng web service-based binding (basicHttpBinding, WsHttpBinding, WsDualHttpBinding hay WsFederationHttpBinding), address sẽ có giá trị tương tự như sau (giả sử rằng bạn không xác định Port, HTTP-based protocols sẽ sử dụng port 80):
- Nếu bạn sử dụng TCP Bindings (như NetTcpBinding hay NetPeerTcpBinding), URI sẽ có format như sau:
- Trong khi đó, MSMQ bindings (như NetMsmqBinding và MsmqIntegrationBinding) sẽ có một định dạng thống nhất, MSMQ có thể sử dụng public hoặc private queues (chỉ available trong local machine) và port numbers thì không có ý nghĩa gì đối với một MSMQ URI. Một URI như sau sẽ mô tả một WCF address với private queue tên là MyPrivateQ:
- Cuối cùng, định dạng address cho một named-pipe binding, NetNamedPipeBinding sẽ như sau (chú ý rằng named pipes cho phép mọi giao tiếp giữa các applications đang chạy chỉ trên cùng một máy tính):
- Một WCF service nào đó có thể expose chỉ duy nhất một address (tất nhiên là dựa trên một kiều binding nào đó). Chúng ta có thể chỉnh trong file config để một service có thể có expose ra bên ngoài nhiều loại bindings khác nhau, cụ thể là ta sẽ tạo ra nhiều <endpoint> elements trong file config (Chi tiết chờ phần sau sẽ rõ). Cách làm này rất hữu ích khi bạn muốn các chương trình callers có thể lựa chọn nhiều loại protocol khác nhau khi muốn giao tiếp với service của bạn.
Building a WCF Service
- Bây giờ khi đã hiểu các thành phần của một WCF applications, chúng ta sẽ tạo một sample application để xem ABCs sẽ kết hợp với nhau như thế nào trong code. Bước đầu tiên của chúng ta là tạo ra một WCF service library bao gồm các contracts và implementations của chúng.
- Trong ví dụ này sẽ không sư dụng Visual Studio WCF project template. Để bắt đầu, chúng ta tạo một class library project tên là MagicEightBallServiceLib, sau đó thêm reference đến assembly System.ServiceModel.dll. Chúng ta sẽ thêm vào một interface tên là IEightBall với một method tên là ObtainAnswerToQuestion.
- WCF service interfaces sẽ được đánh đấu bằng attribute [ServiceContract], các method trong interface này sẽ được đánh dấu bằng attribute [OperationContract]. Sau đây là code của interface IEightBall:
[ServiceContract]
public interface IEightBall
{
// Ask a question, receive an answer!
[OperationContract]
string ObtainAnswerToQuestion(string userQuestion);
}
public interface IEightBall
{
// Ask a question, receive an answer!
[OperationContract]
string ObtainAnswerToQuestion(string userQuestion);
}
Code 1: Interface IEightBall
Các bạn đang xem bài viết về Introduction WCF từ blog của Nguyễn Thoại (http://nthoai.blogspot.com)
- Tiếp theo chúng ta sẽ tạo ra một class để implement interface này. Lớp MagicEightBallService sẽ implement interface IEightBall, lớp này sẽ được gọi là service type và interface IEightBall chính là service contract. Sau đây là code của lớp MagicEightBallService:
public class MagicEightBallService : IEightBall
{
// Just for display purposes on the host.
public MagicEightBallService()
{
Console.WriteLine("The 8-Ball awaits your question...");
}
public string ObtainAnswerToQuestion(string userQuestion)
{
string[] answers = { "Future Uncertain", "Yes", "No", "Hazy", "Ask again later", "Definitely" };
// Return a random response.
Random r = new Random();
return string.Format("{0}? {1}.", userQuestion, answers[r.Next(answers.Length)]);
}
}
{
// Just for display purposes on the host.
public MagicEightBallService()
{
Console.WriteLine("The 8-Ball awaits your question...");
}
public string ObtainAnswerToQuestion(string userQuestion)
{
string[] answers = { "Future Uncertain", "Yes", "No", "Hazy", "Ask again later", "Definitely" };
// Return a random response.
Random r = new Random();
return string.Format("{0}? {1}.", userQuestion, answers[r.Next(answers.Length)]);
}
}
Code 2: Lớp MagicEightBallService
- Như vậy là WCF service library của chúng ta xem như đã xong. Tuy nhiên, trước khi chúng ta chuẩn bị host cho service này, hãy tìm hiểu thêm một chút về các attributes [ServiceContract] và [OperationContract]
The [ServiceContract] Attribute
- Để một CLR interface nào đó trong library của bạn trở thành một service trong WCF, nó phải được đánh dấu bằng attribute [ServiceContract]. Như những .NET attributes khác, ServiceContractAttribute type cũng hỗ trợ một số properties để developer tùy chỉnh theo ý muốn. Hai property là Name và Namespace được dùng để thay đổi tên của service type và tên của XML namespace. Nếu bạn đang sử dụng kiểu binding như web-service, những giá trị này được dùng để xác định <portType> elements của WSDL document.
- Ở đây, chúng ta không cần phải quan tâm nhiều đến giá trị của Name, bởi vị giá trị mặc định sẽ là tên của class implement service contract. Tuy nhiên, giá trị mặc định của namespace sẽ là http://tempuri.org (thực sự nên thay giá trị này đối với toàn bộ các service WCF của chúng ta)
- Khi bạn đang build một WCF service mà có sử dụng những custom data types (ví dụ như kiểu dữ liệu trả về của một method là một custom type), khi đó rất quan trọng để bạn xác định namespace của XML để làm cho custom type này là unique. Có thể bạn đã có kinh nghiệm làm việc với XML web services, XML namespaces giúp những custom type của bạn không bị nhầm lẫn với những type khác cùng tên.
- Ngoài Namespace và Name, [ServieContract] attribute có thể được kết hợp với những properties khác trong bảng dưới đây. Chú ý rằng một số những settings dưới đây có thể bị bỏ qua tùy vào loại bindings chúng ta sử dụng:
Bảng 4: Various Named Properties of the [ServiceContract] attribute:
- CallbackContract: dùng setting này nếu bạn muốn service contract cần một callback function để có thể giao tiếp 2 chiều.
- ConfigurationName: dùng để xác định các setting của service trong file config, giá trị mặc định là tên của class
- ProtectionLevel: cho phép bạn xác định xem contract binding nào cần mã hóa, digital signatures, v.v.
- SessionMode: được dùng để xác định xem session có hoặc không được phép hoặc có bắt buộc đối với một service contract
The [OperationContract] Attribute
- Những methods mà bạn muốn sử dụng bên trong WCF framework phải được đánh dấu bằng attribute [OperationContract]. Cũng như attribute [ServiceContract], attribute này có thể được kết hợp với một số property trong bảng dưới đây.
Bảng 5: Various Named Properties of the [OperationContract] attribute:
- Action: dùng để Get hoặc Set WS-Addressing action của request message
- AsyncPattern: dùng setting này khi quá trình thực thi của method xảy ra bất đồng bộ sử dụng 2 Begin/End method của service. Nó cho phép service có thể được excute trong một server-side thread.
- IsInitiating: dùng setting này để xác định xem một method có phải method được chạy đầu tiên để init trong một session hay không.
- IsOneWay: dùng để xác định xem một operation có cần giá trị trả về hay không.
- IsTerminating: dùng seting này để xác định xem WCF runtimes có phải chấm dứt session hiện tại sau khi method được excute hay không.
Service Types As Operational Contracts
- Như đã nói ở trên, chúng ta có thể sử dụng luôn các attributes [ServiceContract] và [OperationContract] để biến 1 class thành 1 contract mà không cần sử dụng interface:
// This is only for illustrative purposes
// and not used for the current example.
[ServiceContract(Namespace = "http://Intertech.com")]
public class ServiceTypeAsContract
{
[OperationContract]
void SomeMethod() { }
[OperationContract]
void AnotherMethod() { }
}
// and not used for the current example.
[ServiceContract(Namespace = "http://Intertech.com")]
public class ServiceTypeAsContract
{
[OperationContract]
void SomeMethod() { }
[OperationContract]
void AnotherMethod() { }
}
Code 3: Service contract không sử dụng interface
Các bạn đang xem bài viết về Introduction WCF từ blog của Nguyễn Thoại (http://nthoai.blogspot.com)
- Mặc dù có thể làm như vậy, có nhiều điểm thuận lợi hơn khi chúng ta sử dụng một interface để làm service contract. Điểm rõ ràng nhất chính là một interface có thể được applied cho nhiều service type khác nhau theo nguyên tắc polymorphism. Một điểm thuận lợi khác là service contract interface có thể được dùng để tạo ra một contract mới (dựa trên tính interface inheritance).
(Còn tiếp)
Hi a.Thoai,
Em là beginner tìm hiểu WCF. Theo như anh viết bài này NetTcpBinding bị giới hạn bởi in-house application. Điều này có nghĩa chỉ dùng WCF Service trong môi trường local ở tổ chức/công ty?
Nếu em muốn host WCF service lên server A, Web application host lên server B gọi WCF service ở A. Thì binding nào em nên dùng trong trường hợp này?
Mong anh trả lời
Cảm ơn anh
Khoa Diep
Dùng WCF với NetTCPBinding thì thường bị giới hạn do các firewall thường block những port TCP lạ.
Server A với B của bạn nếu trong mạng LAN hoặc VPN với nhau thì ko có gì để nói, binding nào cũng được. Nếu là trên Internet thì dùng httpbinding cho lành.
anh cho em hoi, sau khi em tao project WCF service library em phai bo xung thanh phan gi de no tro thanh mot host (hay endpoint) de phia client co the truy xuat
em cam on anh
phthlap : hướng dẫn click quảng cáo và signup kiếm tiền online : http://get-dola.blogspot.com/
phthlap : hướng dẫn click quảng cáo và signup kiếm tiền online : http://get-dola.blogspot.com/