Bắt đầu từ phần trước: Xây dựng ứng dụng dịch vụ WCF
Trong bài viết trước, chúng ta đã hoàn thành việc tạo ra ứng dụng dịch vụ WCF. Bây giờ, hãy cùng tìm hiểu cách xây dựng chương trình đăng ký (host) cho dịch vụ WCF và thiết lập ứng dụng khách để truy cập vào dịch vụ này.
Các hướng dẫn liên quan đến việc triển khai dịch vụ WCF có thể tham khảo tại các bài viết sau:
- WCF học tập – Chuẩn bị trước khi triển khai (8)
- WCF học tập – Triển khai dịch vụ lên IIS 7.5 (9)
- WCF học tập – Triển khai dịch vụ vào ứng dụng (10)
- WCF học tập – Triển khai dịch vụ dưới dạng Windows Service (11)
- WCF học tập – Triển khai dịch vụ qua WAS (12)
- WCF học tập – Triển khai nhiều dịch vụ cùng lúc (13)
7. Tạo ứng dụng đăng ký dịch vụ WCF
- Dịch vụ WCF cần được chạy trong một tiến trình (host). Việc đăng ký dịch vụ là quá trình chỉ định một host cụ thể cho dịch vụ.
- Chúng ta sẽ thực hiện toàn bộ cấu hình đăng ký dịch vụ trong dự án
BookMgr.Hostingbằng file cấu hình. Dưới đây là đoạn mã thực hiện đăng ký dịch vụBookServicethông qua ứng dụng dòng lệnh. - Nếu gặp lỗi như: "Không tìm thấy hợp đồng tên ‘BookMgr.Contracts.IBookService’ trong danh sách hợp đồng của dịch vụ ‘BookService’", hãy kiểm tra lại file interface trong dự án
BookMgr.Contracts:
using System.ServiceModel;
namespace BookMgr.Contracts
{
[ServiceContract]
public interface IBookService
{
[OperationContract]
string Add(string bookInfo);
[OperationContract]
string Edit(string bookInfo);
[OperationContract]
string Get(string bookId);
[OperationContract]
string Delete(string bookInfo);
[OperationContract]
string Search(string category, string keyword);
}
}
File cấu hình App.config trong BookMgr.Hosting:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework,
Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
<connectionStrings>
<add name="BookEntities"
connectionString="metadata=res://*/BookModel.csdl|res://*/BookModel.ssdl|res://*/BookModel.msl;
provider=System.Data.SqlClient;provider connection string="data source=.\sqlexpress;initial catalog=Test;
integrated security=True;MultipleActiveResultSets=True;App=EntityFramework""
providerName="System.Data.EntityClient" />
</connectionStrings>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<diagnostics>
<messageLogging logEntireMessage="true" logKnownPii="false" logMalformedMessages="true"
logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
<endToEndTracing propagateActivity="true" activityTracing="true"
messageFlowTracing="true" />
</diagnostics>
<behaviors>
<serviceBehaviors>
<behavior name="metadataBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:8088/BookService/metadata" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="metadataBehavior" name="BookMgr.Service.BookService">
<endpoint address="http://127.0.0.1:8088/BookService"
binding="wsHttpBinding"
contract="BookMgr.Contracts.IBookService" />
</service>
</services>
</system.serviceModel>
</configuration>
File Program.cs trong BookMgr.Hosting:
using BookMgr.Service;
using System;
using System.ServiceModel;
namespace BookMgr.Hosting
{
class Program
{
static void Main(string[] args)
{
try
{
using (var host = new ServiceHost(typeof(BookService)))
{
host.Opened += (sender, e) =>
{
Console.WriteLine("Dịch vụ BookService đã khởi động. Nhấn bất kỳ phím nào để dừng.");
};
host.Open();
Console.ForegroundColor = ConsoleColor.Yellow;
foreach (var endpoint in host.Description.Endpoints)
{
Console.WriteLine("[Điểm cuối]: {0}\r\n\t[Địa chỉ]: {1} \r\n\t[Binding]: {2} \r\n\t[Hiệp định]: {3}",
endpoint.Name, endpoint.Address, endpoint.Binding.Name, endpoint.Contract.Name);
}
Console.Read();
}
}
catch (Exception ex)
{
Console.WriteLine("Lỗi: " + ex.Message);
}
}
}
}
8. Tạo ứng dụng khách Windows Forms
- Mở menu Tệp → Thêm → Dự án mới.
- Chọn Visual C# → Windows → Windows Form Application, đặt tên là
BookMgr.Client. - Trong Giải pháp Tài nguyên, thêm các tham chiếu cần thiết.
- Chọn Dự án → Đặt làm dự án khởi chạy.
- Chọn dự án
BookMgr.Client, nhấn chuột phải → Thêm → Mới → Windows Form, tạo fileFrmBook.cs. - Thiết kế giao diện trên form bằng cách kéo thả các điều khiển từ Toolbox.
9. Thêm chức năng lọc dữ liệu theo loại sách
- Mở file
FrmBook.csđể chỉnh sửa. - Thêm các điều khiển:
Label,TextBox,Buttonvào form. - Chọn nút
btnSearchCategory, mở menu ngữ cảnh → Xem mã, bổ sung đoạn mã sau vào sự kiệnClick:
private void btnSearchCategory_Click(object sender, EventArgs e)
{
try
{
using (var factory = new ChannelFactory<IBookService>("WSHttpBinding_IBookService"))
{
var proxy = factory.CreateChannel();
using (proxy as IDisposable)
{
textBoxMsg.Text = proxy.Search(txtCategory.Text, string.Empty);
var books = XMLHelper.DeSerializer<List<Books>>(textBoxMsg.Text);
gridBooks.DataSource = books;
}
}
}
catch (Exception ex)
{
textBoxMsg.Text = "Lỗi: " + ex.Message;
}
}
- Chọn Gỡ lỗi → Bắt đầu gỡ lỗi để chạy ứng dụng.
- Nhập từ khóa IBM vào ô nhập, nhấn nút Tìm kiếm. Chỉ những sách thuộc loại IBM sẽ được hiển thị.
Lưu ý về lỗi phát sinh:
Nếu gặp lỗi:
Communication object 'System.ServiceModel.Channels.ServiceChannel' cannot be used for communication because it is in the 'Faulted' state.
Khi xem xét kỹ, nguyên nhân thực tế nằm ở việc thiếu thư viện EntityFramework.SqlServer.dll trong dự án BookMgr.Hosting. Lỗi xảy ra do không tải được cung cấp dịch vụ Entity Framework cho ADO.NET.
Giải pháp: Sử dụng NuGet Package Manager để thêm gói EntityFramework vào dự án BookMgr.Hosting.