Roland Weigelt's G h o s t D o c
Posted On Friday, February 27, 2009 at at 10:06 AM by UnknownCode của bạn thường thiếu comment:
12 public partial class Main : Form
13 {
14 public Main()
15 {
16 InitializeComponent();
17 }
18
19
20
21
22 private void buttonCommand_Click(object sender, EventArgs e)
23 {
24 this.txtResult.Text = "";
25 this.lblFindResult.Text = "";
26 System.Nullable<System.Guid> personId = null;
27 System.Nullable<System.Guid> surveyID = null;
Chỉ việc sử dụng Ghost Doc:
Code sẽ thành thế này
12 public partial class Main : Form
13 {
14 public Main()
15 {
16 InitializeComponent();
17 }
18
19
20
21
22 /// <summary>
23 /// Handles the Click event of the buttonCommand control.
24 /// </summary>
25 /// <param name="sender">The source of the event.</param>
26 /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
27 private void buttonCommand_Click(object sender, EventArgs e)
28 {
29 this.txtResult.Text = "";
30 this.lblFindResult.Text = "";
31 System.Nullable<System.Guid> personId = null;
32 System.Nullable<System.Guid> surveyID = null;
Download ở đây: http://www.roland-weigelt.de/ghostdoc/
Introduction Windows Communication Foundation Part5 (Last)
Posted On Tuesday, February 24, 2009 at at 5:10 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.
Hosting the WCF Service As a Windows Service
- Cũng dễ dàng nhận thấy rằng nếu host một WCF service trong một Console application hay trong một GUI desktop application không thích hợp lắm trong môi trường server bởi vì người ta thường muốn chương trình host phải chạy liên tục ở backgroud và luôn available cho các client request. Bởi vậy dù bạn vẫn có thể minimize host application xuống taskbar, nhưng vẫn có khả năng bạn sẽ vô tình shutdown chương trình host dẫn đến mọi kết nối của client sẽ bị đứt.
* Tuy ta có thể làm một chương trình desktop application chạy bình thường mà không cần main Windows, nhưng nó vẫn cần phải được execute bởi một người nào đó khi login vào Windows. Trong khi đó Windows service có thể start dễ dàng mà không cần ai login vào Windows.
- Một đặc điểm dễ thấy nhất của Windows service là nó có thể start ngay sau khi machine vừa khởi động. Ngoài ra như đã nói, một Windows service có thể chạy ngầm dưới background và không cần đến một tương tác nào của người dùng Windows.
- Chúng ta sẽ thử build một service như vậy bằng cách sử dụng Windows service project template. Ta hãy tạo một project dạng Windows service tên là MathWindowsServiceHost (Hình 1). Sau đó hãy đổi tên Service1.cs thành MathWinService.cs
Hình 1: Creating a Windows service to host our WCF service
Specifying the ABCs in Code
- Tương tự như những lần trước, ta cũng add reference tới những assembly như System.ServiceModel.dll và project MathServiceLibrary. Chúng ta cần tạo ra một ServiceHost bên trong function OnStart() như sau:
{
// A member variable of type ServiceHost.
private ServiceHost myHost;
public MathWinService()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
// Just to be really safe.
if (myHost != null)
{
myHost.Close();
myHost = null;
}
Uri address = new Uri("http://localhost:8888/MathServiceLibrary");
// Create the host.
myHost = new ServiceHost(typeof(MathService), address);
WSHttpBinding binding = new WSHttpBinding();
Type contract = typeof(IBasicMath);
// Add this endpoint.
myHost.AddServiceEndpoint(contract, binding, address);
AddMexEndpoint(myHost);
// Open the host.
myHost.Open();
}
protected void AddMexEndpoint(ServiceHost myHost)
{
ServiceMetadataBehavior smb = myHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
myHost.Description.Behaviors.Add(smb);
// Add MEX endpoint
myHost.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex"
);
}
protected override void OnStop()
{
// Shut down the host.
if (myHost != null)
myHost.Close();
}
}
Code 1: Code method OnStart
- Đoạn code ở trên chỉ thể hiện cách build một service host từ code, bạn hoàn toàn có thể sử dụng file config để làm tất cả những việc này.
Enabling MEX
- Chúng ta cũng có thể enable MEX từ code như trên (Trong code sample bên dưới có implement MEX endpoint). Nhưng dễ dàng nhất là thêm một file App.config vào Windows service project như sau:
<configuration>
<endpoint address="mex"
contract="IMetadataExchange" />
<!-- Need to add this so MEX knows the address of our service -->
<host>
</baseAddresses>
</host>
</service>
</services>
<!-- A behavior definition for MEX -->
<behaviors>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Code 2: MEX settings
Creating a Windows Service Installer
- Một Windows service khi install thì sẽ được đăng kí vào hệ điều hành. Do đó, bạn cần phải tạo một project installer cho nó. Project installer này sẽ chứa những phần code cần thiết để bạn đăng kí service này vào hệ thống. Để tạo ra một installer, bạn right-click lên màn hình design của MathWinService và chọn “Add Installer” (Hình 2)
Hình 2: Thêm installer cho Windows service
- Sau khi chọn “Add Installer”, bạn sẽ thấy có hai components được thêm vào màn hình designer. Thành phần đầu tiên (mặc định được đặt tên là serviceProcessInstaller1) sẽ được dùng để install một service mới vào hệ thống. Bạn hãy chọn nó, và sử dụng cửa sổ Properties để set property “Account” thành “LocalSystem”
- Thành phần thứ hai (mặc định được đặt tên là serviceInstaller1) sẽ thực sự install service của bạn. Tương tự, hãy sử dụng cửa sổ Properties, đổi “ServiceName” thành “Math Order Service” (Đây là một friendly name của service khi đăng kí vào hệ thống, bạn sẽ thấy nó trong chương trình services.msc của Windows), sau đó set “StartType” thành “Automatic”, bạn cũng có thể set giá trị cho Description nếu muốn. Sau cùng, hãy build lại project.
Installing the Windows Service
- Một Windows service có thể được install bằng một chương trình setup quen thuộc (như một file msi installer) hoặc bằng chương trình installutil.exe command-line tool. Nếu bạn muốn sử dụng cách thứ 2, hãy dùng Visual Studio 2008 command prompt, đổi thư mục hiện hành vô \bin\Debug trong project MathWindowsServiceHost. Và gõ lệnh sau đây:
installUtil MathWindowsServiceHost.exe
- Nếu như install thành công, bạn sẽ thấy friendly name của Windows service này hiển thị bên trong Services list của hệ thống. Bạn có thể mở chương trình này trong Administrator Tools (bên trong Control Panel) hoặc sử dụng lệnh services.msc /s
Hình 3: Xem windows service của bạn sau khi đã install vào hệ thống
- Bây giờ service của bạn đã chạy, bạn có thể build một client application để gọi thử service này. Nếu nó chưa chạy (như hình trên là chưa chạy), bạn hãy start nó.
Invoking a Service Asynchronously
- Bạn hãy tạo một Console Application và đặt tên là MathClient. Sau đó add Service Reference đến Windows service vừa nãy. Nhưng đừng có click button OK vội mà hãy click vào button “Advanced…” như trong hình dưới đây:
Hình 4: Reference our MathService
- Khi click button “Advanced”, bạn sẽ thấy những configuration khác cho proxy. Ta có thể chọn để generate code để có thể call những “remote methods” asynchronous (bất đồng bộ, gọi xong không phải chờ mà có thể thực hiện những dòng lệnh khác, khi nào remote method trả kết quả về sẽ có nơi để nhận và xử lý kết quả đó) bằng cách check vào “Generate Asynchoronous Operators”.
- Có một option khác trong dialog box này đáng quan tâm là Add Web Reference. Nếu bạn đã từng sử dụng XML webservice trong VS.NET 2005 hay trước đó, bạn có thể thấy Add Web Reference thay vì Add Service Reference. Nếu bạn click vào button này, proxy code sẽ được generate theo kiểu cũ để có thể gọi những web service *.asmx.
- Những option khác được sử dụng để control quá trình generate các data contracts mà ta sẽ bàn tới sau. Bạn hãy chọn “Generate Asynchronous Operators” rồi click OK để quay về Visual Studio IDE.
Hình 5: Advanced client-side proxy configuration options
- Lúc này, proxy code sẽ chứa những methods giúp bạn gọi các members của service contract bằng cách sử dụng Begin/End asynchoronous invocation pattern. Sau đây là code sample :
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** The Async Math Client *****\n");
using (BasicMathClient proxy = new BasicMathClient())
{
proxy.Open();
// Add numbers in an async manner, using a lambda expression.
IAsyncResult result = proxy.BeginAdd(2, 3,
ar =>
{
Console.WriteLine("2 + 5 = {0}", proxy.EndAdd(ar));
}, null);
while (!result.IsCompleted)
{
Thread.Sleep(200);
Console.WriteLine("Client working...");
}
}
Console.ReadLine();
}
}
}
Code 3: Gọi remote methods asynchoronous
Designing WCF Data Contracts
- Ở phần cuối này chúng ta sẽ tìm hiểu thêm về Data Contracts. WCF services trước bao gồm một method rất đơn giản và chỉ sử dụng các type built-in của CLR. Khi bạn sử dụng bất kì web-service binding types (basicHttpBindings, wsHttpinding, …), dữ liệu vào và ra được tự động format thành XML elements nhờ vào System.Runtime.Serialization.XmlFormatter trong assembly System.Runtime.Serialization.dll. Nếu bạn sử dụng TCP binding (chẳng hạn như netTcpBinding), các parameters và dữ liệu return lại được format theo dạng binary.
- Tuy nhiên, khi bạn tạo những service contract có sử dụng những kiểu dữ liệu (struct/class) mà bạn build, những kiểu dữ liệu này phải được defined như là một data contract. Vậy, một data contract là một kiểu dữ liệu được đánh dấu bằng attribute [DataContract]. Mỗi field mà bạn có sử dụng của DataContract sẽ được đánh dấu bằng attribute [DataMember]. Nếu như một field nào không được đánh dấu bằng attribute [DataMember], nó sẽ không được serialized bởi WCF runtime.
- Để minh họa thêm về data contracts, ta hãy tạo một WCF service khác. Sample lần này sẽ được tạo bằng WCF service project template. Chúng ta hãy nhớ lại rằng loại WCF service này sẽ được tự động host trong IIS, và chúng sẽ hoạt động như một .NET XML web service. Khi đã nắm được tính chất của các WCF service như vậy, bạn sẽ ít gặp phải problem khi port một WCF service có sẵn vào IIS virtual directory.
Using the Web-Centric WCF Service Project Template
- Bạn hãy tạo new ASP.NET website hoặc ASP.NET webservice application, rồi xóa hết những thứ mà project template này sinh ra như các file cs, các file asmx:
Hình 6: Tạo một project web để host service trong IIS
* Trong sample gốc của sách, họ sử dụng đến code của một phần của chương khác nên tui sẽ dùng một sample khác sử dụng database NorthWind.
- Trong ví dụ này tui sẽ tạo một class library và call library này trong project web. Bạn hãy tạo một WCF Service Library project, lưu ý là đổi tên file App.config hoặc xóa nó đi để khi start project web, nó không tự động start WCF Service host luôn. Bây giờ ta tạo service contract INorthWindService.cs và code của service contract như sau:
public interface INorthWindService
{
[OperationContract]
Customer GetCustomer(string customerId);
[OperationContract]
void AddCustomer(Customer customer);
[OperationContract]
void AddCustomer(string customerId, string companyName, string contactName, string contactTitle, string address, string city, string region,
string postalCode, string country, string phone, string fax);
}
Code 4: NorthWind service contract
- Interface bên trên gồm 3 methods, một trong số đó returns một mảng các object Customer. Sau đây là code của lớp Customer:
[DataContract]
public class Customer
{
public Customer()
{ }
private string _CustomerID;
[DataMember]
public string CustomerID
{
get { return _CustomerID; }
set { _CustomerID = value; }
}
private string _CompanyName;
[DataMember]
public string CompanyName
{
get { return _CompanyName; }
set { _CompanyName = value; }
}
private string _ContactName;
[DataMember]
public string ContactName
{
get { return _ContactName; }
set { _ContactName = value; }
}
private string _ContactTitle;
[DataMember]
public string ContactTitle
{
get { return _ContactTitle; }
set { _ContactTitle = value; }
}
private string _Address;
[DataMember]
public string Address
{
get { return _Address; }
set { _Address = value; }
}
private string _City;
[DataMember]
public string City
{
get { return _City; }
set { _City = value; }
}
private string _Region;
[DataMember]
public string Region
{
get { return _Region; }
set { _Region = value; }
}
private string _PostalCode;
[DataMember]
public string PostalCode
{
get { return _PostalCode; }
set { _PostalCode = value; }
}
private string _Country;
[DataMember]
public string Country
{
get { return _Country; }
set { _Country = value; }
}
private string _Phone;
[DataMember]
public string Phone
{
get { return _Phone; }
set { _Phone = value; }
}
private string _Fax;
[DataMember]
public string Fax
{
get { return _Fax; }
set { _Fax = value; }
}
}
Code 5: Code data contract Customer
- Nếu bạn cứ implement interface như thông thường, tạo một host và call những methods này từ client, bạn sẽ bị runtime exception . Lý do là mỗi method exposed từ service phải có tên duy nhất, ở đây ta có 2 method có cùng tên là AddCustomer. Overloading không work trong web service specifications. Nhưng thật may mắn là [OperationContract] attribute support một property là Name giúp bạn đổi tên của method này trong WSDL description. Chúng ta hãy update method này như sau trong service contract:
public interface INorthWindService
{
...
[OperationContract(Name="AddCustomerDetails")]
void AddCustomer(Customer customer);
}
Code 6: Sử dụng property Name trong OperationContract
Implementing the Service Contract
- Bạn hãy download code sample ở link bên dưới của bài viết này để xem code hoàn chỉnh của solution. Database sử dụng là NorthWind, sẽ tự động attach vào SQL EXPRESS của bạn, nếu trong database server của bạn đã có sẵn database NorthWind thì hãy sửa lại connection string trong file Web.config.
The Role of the *.svc File
- Khi bạn tạo một WCF service theo style của web-service, bạn sẽ thấy trong project có một file tên là *.svc. File này được sử dụng bởi IIS để host service của bạn; nó mô tả tên và location của service implementation. Chúng ta đã đổi tên của WCF types nên phải đổi luôn contents của file Service.svc như sau:
<%@ ServiceHost Language="C#"
Service="nthoai.blogspot.com.WCFSample.ServiceLibary.NorthWindService"
Factory="System.ServiceModel.Activation.ServiceHostFactory" %>
Code 7: File service.svc
- Các bạn chú ý rằng khi host service của mình trong IIS, thì trong file service.svc bắt buộc có một attribute là Factory. Attribute này mặc định ta có thể để là System.ServiceModel.Activation.ServiceHostFactory. Người ta thường extend class ServiceHostFactory để thêm vào một số xử lý đặc biệt như logging,… Trong ví dụ này chúng ta sẽ để giá trị mặc định cho attribute Factory.
Updating the Web.config File
- Bước cuối cùng là update <system.serviceModel> trong web.config:
behaviorConfiguration="WCFSample.ServiceLibary.NorthWindServiceBehavior">
<!-- Unless fully qualified, address is relative to base address supplied above -->
<endpoint address="" binding="wsHttpBinding" contract="nthoai.blogspot.com.WCFSample.ServiceLibary.INorthWindService">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically. -->
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<!-- The Metadata Exchange endpoint is used by the service to describe itself to clients. -->
<!-- This endpoint does not use a secure binding and should be secured or removed before deployment -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Code 8: File web.config
Testing the Service
- Bây giờ chúng ta có thể build bất kì một chương trình client nào để call thử service này. Ở đây, ta sẽ thử bằng chương trình WcfTestClient như đã giới thiệu ở phần trước (Trong code sample, address của service sẽ khác so với trong bài viết):
- Hình dưới đây sẽ là kết quả khi ta gọi method GetCustomer()
Hình 7: Kết quả gọi method GetCustomer
Tổng kết:
- Loạt bài này giới thiệu sơ lược các tính năng và cách sử dụng Windows Communication Foundation (WCF) API. WCF là một trong 3 công nghệ mới của .NET 3.0. Như đã giới thiệu, động cơ chính của sự ra đời WCF là để thống nhất các công nghệ .NET distributed được giới thiệu trước đây. Một WCF service hoàn chỉnh được xác định bởi address, bindings và contracts nên sẽ rất dễ nhớ khi ta chú ý các từ đầu tiên của các thành phần này: ABC.
- Một WCF application điển hình cần 3 assemblies. Assembly đầu tiên sẽ định nghĩa service contract và service types, các thành phần này sẽ tạo thành những chức năng của service. Assembly này kế tiếp sẽ được host trong một chương trình nào đó, một IIS virtual directory hay một Windows service. Cuối cùng, một client assembly sẽ sử dụng một tool để generate các proxy code và client config để có thể thực hiện việc gọi các remote methods.
- Trong các bài viết cũng có nhắc đến một số các WCF programming tool như SvcConfigEditor.exe (giúp bạn modify các file config dễ dàng trên GUI), WcfTestClient.exe application (giúp bạn test nhanh bất kì một WCF service nào), và nhiều Visual Studio 2008 WCF project templates.
(Hết)
Code sample : Download
Xem Introduction Windows Communication Foundation Part1
Xem Introduction Windows Communication Foundation Part2
Xem Introduction Windows Communication Foundation Part3
Xem Introduction Windows Communication Foundation Part4
Introduction Windows Communication Foundation Part4
Posted On Tuesday, February 17, 2009 at at 11:04 AM 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.
Hosting the WCF Service
- Trong phần này chúng ta đã sẵn sàng mọi thứ để tạo một host cho service. Bản thân WCF service chỉ là một class library nên nó cần được thực thi bên trong một chương trình nào đó gọi là host. Trong thực tế, service có thể được host trong một Windows service hoặc trong một virtual directory của IIS. Nhưng trong phần này chúng ta sẽ tạo một host dạng console application tên là MagicEightBallServiceHost.
- Đầu tiên chúng ta tạo mới một project loại Console Application, thêm reference đến System.ServiceModel.dll và MagicEightBallServiceLib project ở phần trước, rồi thêm 2 namespace System.ServiceModel và MagicEightBallServiceLib vào file programe.cs như hình:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using MagicEightBallServiceLib;
namespace MagicEightBallServiceHost
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Console Based WCF Host *****");
Console.ReadLine();
}
}
}
Code 1: Code file program.cs
- Có một việc chúng ta phải quyết định trước khi build một host cho WCF service là nên chọn việc xác định những hosting logic bên trong code hay đưa chúng vào file config của chương trình. Như đã nói, điểm lợi ích của file config là bạn có thể thay đổi nhiều thứ mà không phải build và deploy lại chương trình. Lựa chọn thế nào là tùy ý người developer, trong ví dụ này chúng ta sẽ sử dụng file config. Vì vậy, bạn hãy thêm một file App.config vào project.
Establishing the ABCs Within an App.config file
- Khi bạn build một host cho WCF service, bạn phải làm theo một số bước như sau, một số bước sẽ làm với file config và một số sẽ làm trong code:
- Xác định “endpoint” cho WCF service sắp được host bên trong file config.
- Bên trong code, sử dụng class “ServiceHost” để expose các service của bạn từ “endpoint” trên
- Đảm bảo rằng chương trình host của bạn lúc nào cũng chạy khi vẫn có những request từ client. Hiển nhiên, bước này không bắt buộc khi bạn đang host trong một window service hoặc trong IIS
- Trong WCF, thuật ngữ “endpoint” đơn giản chỉ tượng trưng cho ba thành phần là “address”, “binding” và “contract” mà chúng ta đã biết. Trong file XML config, một endpoint được thể hiện bên trong element <endpoint>, bên trong element này sẽ có các element con gồm address, binding và contract. Bây giờ bạn hãy update file config mới thêm vào lúc nãy bằng một endpoint như sau (trong ví dụ này chúng ta sử dụng port 8888):
<configuration>
binding="basicHttpBinding"
contract="MagicEightBallServiceLib.IEightBall"/>
</service>
</services>
</system.serviceModel>
</configuration>
Code 2: Xml endpoint bên trong file config
- Chú ý rằng element <system.serviceModel> là node root của tất cả các settings. Mỗi service exposed từ host của bạn sẽ được xác định bởi element <service> bên trong node <services>. Ở đây, element <service> có sử dụng một attribute tên là name (không bắt buộc) để xác định friendly name của service type.
- Node con <endpoint> chịu trách nhiệm xác định address, loại binding (ví dụ như basicHttpBinding trong ví dụ này), và tên đầy đủ của interface của WCF service contract (IEightBall). Bởi vì chúng ta đang dùng HTTP-based binding, nên scheme ở đây sẽ là http://
Coding Agains the ServiceHost Type
- Sau khi đã có file config với các setting đầy đủ, những thứ còn lại cần code khá đơn giản. Khi chương trình chính chạy (console application host), chúng ta sẽ tạo một instance của ServiceHost. Lúc runtime, object này sẽ tự động đọc những thông tin trong file config và xác định đúng address, binding và contract tương ứng:
{
Console.WriteLine("***** Console Based WCF Host *****");
using (ServiceHost serviceHost = new ServiceHost(typeof(MagicEightBallService)))
{
// Open the host and start listening for incoming messages.
serviceHost.Open();
// Keep the service running until the Enter key is pressed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press the Enter key to terminate service.");
Console.ReadLine();
}
}
Code 3: Đoạn code để khai báo một instance ServiceHost object
- Nếu bây giờ bạn run application, bạn sẽ thấy hình như sau, service của bạn đã sẵn sàng để nhận các request từ phía clients (mặc dù chúng ta chưa làm tới chương trình client nào... hê hê)
***** Console Based WCF Host *****
The service is ready.
Press the Enter key to terminate service.
Hình 1: Service host đã sẵn sàng cho các external request qua HTTP binding
Host Coding Options
- Ở code trên, chúng ta đang tạo ServiceHost bằng constructor chỉ với tên của service type. Tuy nhiên, ta có thể sử dụng constructor khác với các thông tin về các addresses mà service có thể được access. Lúc này, giá trị của address được xác định trong file config; ta có thể sử dụng cách sau để làm tất cả trong code, dân gian còn gọi là hard-code
new Uri[]{new Uri("http://localhost:8080/MagicEightBallService")}))
{
...
}
Code 4: Hard-code một endpoint trong code
- Một trong những điều phiền phức nho nhỏ khi chọn cách sử dụng file config là …có nhiều cách để config, tùy thuộc vào lượng thông tin bạn hard-code. Bạn hãy xem ví dụ sau:
<configuration>
<endpoint address="" binding="basicHttpBinding"
contract="MagicEightBallServiceLib.IEightBall"/>
<!-- List all of the base addresses in a dedicated section-->
<host>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
Code 5: Config file XML theo nhiều cách
- Trong trường hợp này, attribute “address” của element “endpoint” giữ giá trị rỗng, và cho dù bạn không hard-code address Uri khi tạo instance ServiceHost đi nữa, chương trình host vẫn chạy như trước vì giá trị address sẽ được lấy từ “baseAddress”. Cách lưu trữ những address trong <baseAddresses> có nhiều điểm thuận lợi, đó là có thể một số phần khác của file config sẽ cần sử dụng đến giá trị address, nên để nó riêng một chỗ ta có thể sử dụng ở nhiều nơi. Vì thế, thay vì phải copy và paste các giá trị adddress vào trong một file config, bạn có thể để riêng giá trị này như trên.
* Ở những ví dụ sau, chúng ta sẽ được giới thiệu một tool để thay đổi những config này dễ dàng hơn
- Trước khi chúng ta build một client application để giao tiếp với service, chúng ta hãy tìm hiểu thêm vai trò của lớp ServiceHost, element <service.serviceModel> cũng như vai trò của metadata exchange (MEX) services.
Details of the ServiceHost Type
- Lớp ServiceHost được sử dụng để config và expose một WCF service từ chương trình host. Tuy nhiên, chúng ta chỉ nên sử dụng lớp này nếu cần trực tiếp sử dụng nó để build một chương trình đặc biệt để host các services. Nếu bạn sử dụng IIS (trong Vista là WAS) để expose service, object ServiceHost sẽ được tạo tự động thay cho bạn.
- Như bạn thấy, lớp này đòi hỏi một service description từ file config. Những thông tin này có thể được đọc tự động trong quá trình tạo object, nó cũng có thể được config bằng một số members. Ngoài method Open() và Close(), bảng dưới đây sẽ liệt kê một số members khác của lớp này:
Bảng 1: Select Members of the ServiceHost Type
Members | Ý nghĩa |
---|---|
Authorization | Property này dùng để lấy authentication level của service |
AddServiceEndpoint() | Method này dùng để đăng kí một endpoint cho chương trình host |
BaseAddresses | Trả về một list các baseAddresses của service hiện tại |
BeginOpen() BeginClose() | Method này cho phép bạn đóng và mở một ServiceHost object theo cách bất đồng bộ |
CloseTimeout | Property này dùng đế set và get thời gian cho phép để close 1 Service |
Credentials | Property này dùng lấy giá trị security credentials đang sử dụng bởi service hiện tại |
EndOpen() EndClose() | Property này dùng kết hợp với BeginOpen và BeginClose |
OpenTimeout | Property này dùng để set và get thời gian tối đa để một service start up |
State | Property này dùng để lấy trạng thái của communication object |
Details of the <system.serviceModel> Element
- Tương tự như một XML element bất kì, <system.serviceModel> có thể chứa một số element con với nhiều attributes khác nhau. Bạn có thể tham khảo .NET Framework 3.5 SDK để tìm hiểu chi tiết các attributes này, còn sau đây là bộ khung những sub elements:
</behaviors>
<client>
</client>
<commonBehaviors>
</commonBehaviors>
<diagnostics>
</diagnostics>
<serviceHostingEnvironment>
</serviceHostingEnvironment>
<comContracts>
</comContracts>
<services>
</services>
<bindings>
</bindings>
</system.serviceModel>
Code 6: Các sub elements của <system.serviceModel>
Bảng sau đây sẽ mô tả ý nghĩa của các element này:
Bảng 2: SubElements of <service.serviceModel>
SubElement | Ý nghĩa |
---|---|
behaviors | WCF hỗ trợ nhiều endpoints và service behaviors. Behavỉors cho phép bạn customize những chức năng của host và client |
bindings | Element này cho phép bạn xác định các loại binding cho host |
client | Element này chứa danh sách các endpoints được sử dụng bởi client để connect đến service |
comContracts | Element này định nghĩa một COM contract cho phép WCF và COM có thể giáo tiếp với nhau |
commonBehaviors | Element này chỉ được set bên trong một machine.config, nó có thể được dùng để xác định tất cả behaviors được sử dụng bởi các WCF service trên một machine |
diagnostics | Element này chứa những setting cho các diagnostic features của WCF, user có thể enable/disable tracking, performance counters, và WMI provider, và có thể thêm những custom message filters |
serviceHostingEnvironment | Element này được dùng để xác định xem một operation có phải là một initial operation trong một session hay không |
services | Element này chứa các WCF services exposed từ chương trình host |
Enabling Metadata Exchange
- Một WCF client application sẽ giao tiếp với WCF service nhờ vào một lớp proxy được sinh ra tự động. Bạn có thể tự tạo ra lớp proxy này nhưng không nên mất công làm chi, nhất là có thể sinh ra rất nhiều lỗi. Có một tool để sinh ra mọi thứ cho bạn, kể cả file config cho client application: svcutil.exe. Đó là một command line tool mà bạn có thể dùng lệnh console để sử dụng, còn trong VS.NET 2008, bạn có thể làm tương tự bằng cách chọn Menu Project rồi chọn Add Service Reference option.
- Tuy nhiên, để những tool này có thể sinh ra proxy code cũng như file config, chúng phải biết được format của WCF service interfaces và các data contracts.
- Metadata exchange (MEX) là một WCF “service behavior” có thể được dùng để thay đổi và điều chỉnh cách WCF runtime “handle” service của bạn. Mỗi <behavior> element có thể định nghĩa một số những activities mà service có thể thực hiện. WCF cung cấp sẵn một số behavior và bạn cũng có thể tự build những behavior của mình.
- MEX behavior (mặc định sẽ bị disabled) sẽ chặn các request được gửi qua HTTP GET. Do đó nếu bạn muốn svcutil.exe hay VS.NET 2008 có thể sinh các proxy code và file config, bạn phải enable nó lên.
- Có thể enable MEX bằng cách thêm vào một số setting trong file config. Đầu tiên, bạn phải thêm một node <endpoint> cho MEX setting. Sau đó, bạn phải định nghĩa một WCF behavior để cho phép HTTP GET access. Tiếp đó, bạn cần kết hợp behavior này với service của bạn thông qua “behaviorConfiguration” element. Cuối cùng, bạn cần thêm một node <host> để định nghĩa base addess cho service này (MEX sẽ dựa vào đây để xác định location của types được mô tả).
* Bước này có thể được bỏ qua nếu bạn sử dụng một System.Uri object để thay cho base address trong trường hợp này.
- Đoạn config sample dưới đây sẽ tạo một custom <behavior> element tên là EightBallMEXBehavior tương ứng với service:
<configuration>
<!-- Enable the MEX endpoint -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<!-- Need to add this so MEX knows the address of our service -->
<host>
</baseAddresses>
</host>
</service>
</services>
<!-- A behavior definition for MEX -->
<behaviors>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Code 7: Một MEX config sample
- Bây giờ bạn có thể restart service và xem metadata description bằng một web browser bất kì ở địa chỉ sau đây:
- Khi bạn mở homepage của WCF này, bạn được cung cấp những chi tiết kĩ thuật về cách sử dụng service cũng như cách xem WSDL contract, v.v.
Hình 2: WCF service homepage
Building the WCF Client Application
- Chương trình host service đã chạy ngon lành, công việc cuối cùng là build một chương trình client để thử service của chúng ta. Như đã giới thiệu, .NET Framework 3.5 SDK hỗ trợ một vài cách để generate proxy code và file config cho client application. Để bắt đầu, hãy tạo một console application tên là MagicEightBallServiceClient.
Generating Proxy Code Using svcutil.exe
- Cách đầu tiên để build một client side proxy là sử dụng tool svcutil.exe. Sử dụng tool này, bạn có thể generate một file C# proxy code và một file config tương ứng cho client application. Trước hết bạn cần phải xác định được service’s endpoint. Parameter /out: của tool này được dùng để xác định tên file proxy C# được sinh ra, và /config: để xác định tên file config.
- Hãy chạy chương trình service host, rồi đánh lệnh sau đây trong VS.NET 2008 conmmand prompt, nó sẽ generate 2 files trong thư mục hiện hành:
svcutil http://localhost:8888/MagicEightBallService /out:myProxy.cs /config:app.config
- Nếu mở file myProxy.cs, bạn sẽ thấy một client side code thể hiện interface IEightBall và một class mới EightBallClient, đó chính là lớp proxy. Class này derives từ một generic class, System.ServiceMode.ClientBase<T>, T chính là serviceType interface.
- Ngoài một số constructors, bạn sẽ thấy các method được đánh dấu bằng attribute [OperationContract](trong service contract) thì ở đây sẽ có một method tương ứng, trong đó property Channels của parrent class sẽ được dùng để invoke chính xác method của service. Sau đây là một phần code của proxy type được sinh ra:
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class EightBallClient : System.ServiceModel.ClientBase<IEightBall>, IEightBall
{
...
public string ObtainAnswerToQuestion(string userQuestion)
{
return base.Channel.ObtainAnswerToQuestion(userQuestion);
}
}
Code 8: Partial snapshot of the proxy type
- Khi bạn tạo một instance của proxy type để sử dụng, base class của nó sẽ tự động thiết lập một connection đến endpoint dựa trên những settings trong client site config. Cũng giống như file config ở phía server, file config phía client cũng chứa một <endpoint> element và những chi tiết mà basicHttpBinding sử dụng để giao tiếp với service.
- Thêm vào đó, bạn sẽ thấy một <client> element, node này cũng tương tự như phía server sẽ thiết lập các ABCs cho phía client
<endpoint
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IEightBall"
contract="ServiceReference.IEightBall"
name="BasicHttpBinding_IEightBall" />
</client>
Code 9: Một XML config phía client
- Bây giờ, bạn có thể include 2 file mới được sinh ra vào client project (nhớ add reference đến System.ServiceModel.dll) và sử dụng proxy type để giao tiếp với remote WCF service. Tuy nhiên, hãy tạm hoãn việc đó, chúng ta hãy xem VS.NET sinh các file cho phía client như thế nào
Generating Proxy Code Using Visual Studio 2008
- Nếu không muốn sử dụng svcutil.exe tool, bạn có thể sinh các client code bằng VS.NET 2008 bằng cách chọn option Add Service Reference từ menu Project. Khi activate menu này xong, bạn sẽ bị yêu cầu nhập vào server URI:
Hình 3: Generating the proxy files using Visual Studio 2008
- Không chỉ tạo và tự động insert những proxy files vào project hiện tại cho bạn, tool này còn tự thêm những reference đến các WCF assemblies. Proxy class khi được sinh ra từ tool này sẽ tự động được định nghĩa trong namespace ServiceReference, là nested namespace trong client’s namespace. Sau đây là code của client:
using MagicEightBallServiceClient.ServiceReference;
namespace MagicEightBallServiceClient
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Ask the Magic 8 Ball *****\n");
using (EightBallClient ball = new EightBallClient())
{
Console.Write("Your question: ");
string question = Console.ReadLine();
string answer = ball.ObtainAnswerToQuestion(question);
Console.WriteLine("8-Ball says: {0}", answer);
}
Console.ReadLine();
}
}
}
Code 10: Code C# của chương trình Client
- Bây giờ nếu chương trình service host vẫn đang chạy, bạn hãy run chương trình client và sẽ thấy kết quả trên màn hình:
***** Ask the Magic 8 Ball *****
Your question: Will I get this book done soon
8-Ball says: Will I get this bok done soon? No.
Hình 4: Kết quả chạy chương trình client
Configuring a TCP-Based Binding
- Trong ví dụ trên, cả client và server đều được config để sử dụng loại binding đơn giản nhất là HTTP-based bindings, basicHttpBinding. Bởi vì những setting này đều được đặt trong file config nên ta có thể dễ dàng thay đổi sang loại binding khác. Bạn hãy thử copy các chương trình chạy của client và server sang các thư mục khác, sau đó lần lượt sửa đổi 2 file config sang netTcpBinding rồi chạy thử để thấy kết quả.
Using the WCF Service Library Project Template
- Trong phần này, chúng ta sẽ tìm hiểu một số chủ đề khác không kém quan trọng, bao gồm lợi ích của WCF service library project template, chương trình WCF Test Client, tool WCF configuration editor, host một WCF services bên trong một Windows service và call service theo kiểu bất đồng bộ (asynchronous).
Building a Simple Math Service
- Trước hết, hãy tạo một project mới dạng WCF Service Library tên là MathServiceLibrary. Sau đó đổi tên file IService1.cs thành IBasicMath.cs. Sau đó xoá tất cả code sinh tự động và thay bằng đoạn code như sau:
{
[ServiceContract(Namespace="www.Intertech.com")]
public interface IBasicMath
{
[OperationContract]
int Add(int x, int y);
}
}
Code 11: interface IBasicMath
- Kế tiếp, đổi tên Service1.cs thành MathService.cs, và thay thế code sinh tự động bằng đoạn code dưới đây:
{
public class MathService : IBasicMath
{
public int Add(int x, int y)
{
// To simulate a lengthy request.
System.Threading.Thread.Sleep(5000);
return x + y;
}
}
}
Code 12: class MathService
- Cuối cùng, hãy mở file App.config và replace những nơi xuất hiện IService1 bằng IBasicMath, Service1 bằng MathService. Nếu để ý bạn sẽ thấy rằng file config này đã tự động enable MEX và sử dụng wsHttpBinding.
Testing the WCF Service with WcfTestClient.exe
- Một điểm thuận lợi của WCF Service Library project là khi bạn debug hay run library này, nó sẽ tự động đọc file config và từ đó load một WCF Test Client application (WcfTestClient.exe). Chương trình này cho phép bạn từng method của service interface như khi bạn build một WCF service và rõ ràng bạn không phải mất công sức để build các chương trình host/client chỉ để test.
- Hình bên dưới mô tả môi trường test của MathService. Chú ý là khi bạn double click lên một interface method, bạn có thể nhập vào các giá trị input rồi invoke method đó.
- Không chỉ dùng để test các service library của bạn, tool này còn có thể dùng để test bất kì một WCF service nào khi bạn chạy nó trong command line với một MEX endpoint. Ví dụ, bạn có thể test service MagicEightBallService bằng command sau đây (mở bằng Visual Studio 2008 command prompt):
Hình 5: Testing the WCF service using WcfTestClient.exe
Altering Configuration Files Using SvcConfigEditor.exe
- Một lợi ích nữa khi sử dụng WCF Service Library project là bạn có thể right-click lên App.config trong Solution Explorer và activate tool Service Configuration Editor, SvcConfigEditor.exe.
Hình 6: Start chương trình config editor
- Khi bạn chạy tool này, bạn có thể thay đổi những setting trong file XML config dễ dàng hơn nhiều. Có nhiều điểm thuận lợi khi sử dụng tool này hơn so với tự tay thay đổi file config. Bạn có thể tin chắc rằng những code setting sinh ra bởi tool này sẽ đúng format và định dạng như mong muốn. Kế đến, bạn sẽ dễ dàng thấy được giá trị chính xác của một values nào đó được gán vào một attribute tương ứng. Điều hay nhất là bạn không cần phải làm mọi thứ trên bằng tay.
Hình 7: Giao diện chương trình config editor
Code sample : Download
(Còn tiếp phần cuối)
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.
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. |
- 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:
public interface IEightBall
{
// Ask a question, receive an answer!
[OperationContract]
string ObtainAnswerToQuestion(string userQuestion);
}
Code 1: Interface IEightBall
- 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:
{
// 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:
// 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
- 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)