Việc phát triển ứng dụng Silverlight có khả năng gọi và sử dụng các dịch vụ WCF (Windows Communication Foundation) là một yêu cầu phổ biến, nhưng đôi khi có thể gây ra những thách thức nhất định. Để thực hiện kết nối này một cách hiệu quả, cần chú ý đến một số cấu hình quan trọng ở cả phía dịch vụ WCF và phía ứng dụng Silverlight.
Cấu hình phía Dịch vụ WCF
1. Thiết lập Chính sách Miền chéo (Cross-domain Policy)
Do mô hình bảo mật của Silverlight, ứng dụng không được phép truy cập tài nguyên từ một miền khác mà không có sự cho phép rõ ràng. Để khắc phục điều này, bạn cần tạo một tệp tin crossdomain.xml và đặt nó ở thư mục gốc của dịch vụ WCF. Tệp này cho phép Silverlight thực hiện các yêu cầu HTTP xuyên miền.
<?xml version="1.0" encoding="utf-8"?>
<cross-domain-policy>
<!-- Cho phép truy cập từ bất kỳ miền nào. Để hạn chế, thay "*" bằng tên miền cụ thể. -->
<allow-access-from domain="*" />
</cross-domain-policy>
2. Điều chỉnh Cấu hình Dịch vụ (web.config hoặc app.config)
Bạn cần đảm bảo rằng dịch vụ WCF được cấu hình với binding tương thích với Silverlight. Hiện tại, Silverlight chủ yếu hỗ trợ basicHttpBinding cho các hoạt động đồng bộ và không đồng bộ cơ bản.
Trong tệp web.config (đối với dịch vụ được host trên IIS) hoặc app.config (đối với dịch vụ tự host), hãy kiểm tra hoặc thêm các cấu hình endpoint như sau:
<configuration>
<system.serviceModel>
<services>
<service name="MyNamespace.MyService">
<!-- Endpoint chính sử dụng basicHttpBinding -->
<endpoint address=""
binding="basicHttpBinding"
contract="MyNamespace.IServiceContract"/>
<!-- Endpoint metadata để client có thể khám phá dịch vụ -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Lưu ý: Nếu bạn muốn hỗ trợ nhiều loại binding (ví dụ: wsHttpBinding cho các ứng dụng .NET khác), mỗi endpoint phải có địa chỉ duy nhất. Tuy nhiên, đối với Silverlight, basicHttpBinding là lựa chọn an toàn nhất.
Cấu hình phía Silverlight Client
Sau khi thêm Service Reference vào dự án Silverlight, một tệp cấu hình (thường là ServiceReferences.ClientConfig) sẽ được tạo. Bạn cần đảm bảo địa chỉ của dịch vụ WCF được chỉ định chính xác trong tệp này.
<configuration>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IServiceContract" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://localhost:12345/MyService.svc"
binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding_IServiceContract"
contract="MyServiceRef.IServiceContract"
name="BasicHttpBinding_IServiceContract" />
</client>
</system.serviceModel>
</configuration>
Đảm bảo rằng address trong cấu hình client trùng khớp với địa chỉ của dịch vụ WCF đang hoạt động.
Thực hiện gọi Dịch vụ WCF từ Silverlight
Silverlight sử dụng mô hình gọi dịch vụ không đồng bộ. Sau khi thêm Service Reference, bạn có thể tương tác với dịch vụ thông qua một proxy client được tạo tự động.
Dưới đây là ví dụ về cách gọi một phương thức dịch vụ không đồng bộ và xử lý kết quả:
using System;
using System.Windows;
using System.Windows.Controls; // Sử dụng cho Button hoặc TextBlock
using MyServiceRef; // Thay bằng namespace của Service Reference của bạn
namespace MySilverlightApp
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}
private void OnLoadDataButtonClick(object sender, RoutedEventArgs e)
{
// Khởi tạo proxy client cho dịch vụ WCF
ServiceContractClient serviceClient = new ServiceContractClient();
// Đăng ký sự kiện hoàn thành để nhận kết quả
serviceClient.GetDataCompleted += OnGetDataOperationCompleted;
serviceClient.CloseCompleted += OnServiceClientClosed; // Xử lý khi proxy đóng
// Gọi phương thức dịch vụ không đồng bộ
// Giả sử GetDataAsync nhận một số nguyên làm tham số
serviceClient.GetDataAsync(123);
// Cập nhật giao diện người dùng tạm thời
this.resultDisplayButton.Content = "Đang tải dữ liệu...";
}
private void OnGetDataOperationCompleted(object sender, GetDataCompletedEventArgs e)
{
// Xử lý lỗi nếu có
if (e.Error != null)
{
this.resultDisplayButton.Content = "Lỗi: " + e.Error.Message;
return;
}
// Kiểm tra xem thao tác có bị hủy không
if (e.Cancelled)
{
this.resultDisplayButton.Content = "Thao tác đã bị hủy.";
return;
}
// Hiển thị kết quả nhận được từ dịch vụ
// Giả sử GetData trả về một chuỗi
this.resultDisplayButton.Content = e.Result;
// Đóng proxy client sau khi hoàn thành thao tác
// serviceClient.CloseAsync(); // Gọi này nếu bạn muốn đóng client ngay lập tức
}
private void OnServiceClientClosed(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
// Xử lý khi proxy client đã được đóng
// Có thể bỏ qua nếu không cần xử lý cụ thể khi đóng
}
}
}
Trong ví dụ trên, OnLoadDataButtonClick là một phương thức sự kiện cho một nút (Button) trong giao diện người dùng. Khi nút được nhấn, proxy ServiceContractClient sẽ được khởi tạo, sự kiện GetDataCompleted được đăng ký và phương thức GetDataAsync được gọi. Kết quả hoặc thông báo lỗi sẽ được hiển thị trên một điều khiển UI có tên resultDisplayButton.