3.3. Công nghệ WebPart
3.3.5. Tương tác giữa các WebPart
Phần lớn các Web sites và đặc biệt là các Portal đều có một vị trí nào đấy để hiển thị một số lượng lớn các nội dung. Điều này có thể làm nên một niềm hứng thú cho người sử dụng nhưng về lâu dài đây có thể là nguồn tạo ra sự lộn xộn. Các nghiên cứu gần đây về tính tiện dụng khi dùng Web đã chỉ ra rằng khả năng cá nhân hóa là một nhân tố cực kỳ quan trọng để đưa đến sự thành công của các Web sites. Đưa đến cho người dùng các chức năng để xây dựng các khung nhìn mang tính cá nhân chính là một sự khác biệt quan trọng giữa các trang Web thông thường và một siêu Web (chẳng hạn các trang Portal). Các Web sites xây dựng dựa trên SharePoint sẽ đảm bảo rằng các module được tạo ra sẽ có khả năng cá nhân hóa.
Nội dung của các trang SharePoint không nhất thiết phụ thuộc vào cơ sở hạ tầng ở bên dưới nhưng khả năng mềm dẻo cũng như độ sâu của các module sẽ giúp cho người xây dựng trang đưa ra các nội dung phong phú nơi mà cách thức hiển thị cũng như cấu trúc được quyết định bởi người dùng cuối. Các SharePoint Web Part là những khối xây dựng nên các trang SharePoint vì chúng hiển thị các dữ liệu trong một vùng cửa sổ của người dùng. Trong phần này ta sẽ đề cập đến cơ chế của việc kết nối các Web Parts và thể hiện cách thức xây dựng hai Web Parts làm việc cùng nhau theo lược đồ master/detail.
3.3.5.1. Mơ hình kết nối
Hai Web Parts kết nối với nhau được thực thi trong một cặp publisher/subscriber. Bất cứ giá trị thay đổi nào đưa ra bởi Provider đều được phản hồi bởi consumer, mơ hình này bao gồm hai thực thể tương tác với nhau: một provider cung cấp và một hoặc nhiều consumer khách hàng.
Provider được gọi để thu thập các dữ liệu cơng cộng của nó và làm cho nó có khả năng đăng ký với người gọi. Consumers được gọi để thu về các dữ liệu hiển thị và dựa vào đó cập nhật các vùng giao diện của nó. Hình sau cung cấp một khung nhìn mức cao của mơ hình kết nối này:
Hình vẽ 3.19: Khung nhìn mức cao về mơ hình kết nối
Trong phần này ta chỉ đề cập đến mơ hình kết nối ICellProvider/ICellConsumer. Thơng thường có một vài cặp giao diện mà các Web Parts có thể thi hành để thực hiện kết nối, hai giao diện đơn giản nhất đó là ICellProvider và ICellConsumer.
Một provider Web Part là một Web Part mà thực thi giao diện ICellProvider, mặt khác một consumer Web Part phải thực thi giao diện ICellConsumer. ICellProvider được định nghĩa như sau:
public interface ICellProvider {
// Events
event CellProviderInitEventHandler CellProviderInit; event CellReadyEventHandler CellReady;
// Methods
void CellConsumerInit(object sender,
CellConsumerInitEventArgs cellConsumerInitEventArgs); }
Một provider phải chứa mã để sinh ra một cặp các sự kiện tới consumer và chứa đựng mã điều khiển các sự kiện của consumer , giao diện ICellConsumer mang tính đối ngẫu với giao diện ICellProvider và như sau:
public interface ICellConsumer {
// Events
// Methods
void CellProviderInit(object sender,
CellProviderInitEventArgs cellProviderInitArgs); void CellReady(object sender,
CellReadyEventArgs cellReadyArgs); }
Hai giao diện trên ánh xạ lẫn nhau: mỗi sự kiện phát sinh bởi giao diện này sẽ tìm một phương thức điều khiển trong giao diện kia và ngược lại. Chẳng hạn sự kiện CellReady của ICellProvider theo thiết kế nó sẽ được phát sinh để báo cho consumers biết rằng dữ liệu mới đã có hiệu lực. Vậy thì bằng cách nào mà một consumer có thể được báo tin về điều đó? Vấn đề được giải quyết như sau, cónumer thực thi phương thức CellReady trong giao diện ICellConsumer. Lưu ý ở đây là khơng có sự tương tác trực tiếp giữa hai Web Part mà có một thành phần trung gian (chính là SharePoint người tạo ra môi trường thực thi) đã đảm bảo việc ánh xạ mỗi sự kiện với phương thức tương ứng theo cả 2 hướng (từ provider đến consumer và ngược lại).
3.3.5.2. Sinh ra các Web Part kết nối
Ngoài các giao diện đã kể ở trên, có một vài phương thức phức tạp hơn để các Web Parts tương tác với nhau và chúng được định nghĩa trong lớp cơ sở WebPart. Môi trường mà SharePoint tạo ra sẽ gọi đến các phương thức đó trước khi các Web Part được sinh ra. Sau đây ta sẽ liệt kê ra các bước cơ bản về vòng đời của các Web Parts kết nối:
Với mỗi cặp các Web Parts kết nối thì cơ sở hạ tầng Web Parts sẽ gọi phương thức EnsureInterfaces trên provider và consumer. EnsureInterfaces
là một phương thức Web Parts có khả năng cài đè, nó cung cấp cơ sở hạ tầng với các thông tin cho mỗi loại giao diện đang được thực thi, một tham chiếu tới Web Part và số lượng tối đa các kết nối được phép.
Với mỗi cặp các Web Parts kết nối, cơ sở hạ tầng Web Part gọi phương thức
CanRunAt để biết được mỗi Web Parts có thể thi hành từ đâu (từ client
và/hoặc từ server dựa trên cấu hình hiện tại).
Phương thức PartCommunicationInit được gọi cho provider và sau đó là cho consumer, cả hai Web Part được báo tin rằng kết nối đã được thiết lập và đảm bảo rằng các điều khiển con của chúng đã được thiết lập.
Phương thức PartCommunicationInit được gọi cho provider. Phương thức
này có thể tùy biến phát sinh ra sự kiện CellProviderInit, nếu phát sinh sự kiện thì nó phải được điều khiển bởi cơ sở hạ tầng Web Part và nhất thiết phải gọi đến phương thức tương ứng trên consumer. Trong sự kiện
CellProviderInit, provider cung cấp một đặc tả về các trường mà nó đang
loại giữ liệu gì provider sẽ gửi đi. Với những trường khơng được chấp nhận thì một ngoại lệ sẽ được ném ra.
Phương thức PartCommunicationInit cũng được gọi trên consumer và có thể tùy biến phát sinh sự kiện CellConsumerInit. Nếu sự kiện phát sinh, nó sẽ
được điều khiển bởi cơ sở hạ tầng Web Part và được phục vụ thông qua phương thức CellConsumerInit của provider.
Phương thức PartCommunicationMain được triệu gọi trên provider để đóng gói bất cứ dữ liệu công cộng nào và báo tin cho consumer thông qua sự kiện
CellReady. Một lần nữa sự kiện được nắm bắt bởi cơ sở hạ tầng bên dưới và
được điều khiển thông qua phương thức CellReady của consumer.
Đoạn mã chương trình sau cho thấy một sự thi hành đặc thù của phương thức
PartCommunicationMain trên một Web Part provider. Trong ví dụ này ta đề cập
đến một Web Part có tên là EmployeeViewer, nó hiển thị một thuộc tính integer – EmployeeID. Theo đoạn mã này thì Web Part xuất ra ID của nhân viên hiện tại đã được lựa chọn.
public override void PartCommunicationMain() {
if (CellReady != null) {
CellReadyEventArgs cellReadyArgs = new CellReadyEventArgs(); cellReadyArgs.Cell = _employeeID;
CellReady(this, cellReadyArgs); }
}
Đoạn mã sau chứa sự phản hồi thông thường của consumer cho sự kiện CellReady:
public void CellReady(object sender, CellReadyEventArgs cellReadyArgs) {
if(cellReadyArgs.Cell != null) {
_employeeID = (int) cellReadyArgs.Cell; }
Consumer lưu trữ dữ liệu hợp quy cách vào một biến cục bộ cho việc sử dụng sau này. Khi tất cả các bước trên đã hoàn thành, sự kiện OnPreRender được phát sinh trên tất cả các Web Parts cũng như các điều khiển của chúng.
Lưu ý quan trọng ở đây là tất cả các phương thức và sự kiện được liệt kê ở trên thì chỉ sự kiện CellReady của provider và phương thức CellReady của consumer là thực sự cần thiết.
3.3.5.3. Thi hành Provider
Trước hết ta tạo ra một Project Web Part từ Visual Studio .NET, sau đó tạo các Web Part provider và consumer bằng cách thêm vào Project đang xây dựng:
Hình vẽ 3.20: Chọn Provider Web Part
Trình winzard sẽ tự động tạo ra một lớp Web Part mới đã thực thi các giao diện
ICellProvider và ICellConsumer. Mục đích của ta ở đây là tạo ra một
EmployeeViewer Web Part mà hiển thị một vài thông tin cá nhân của một nhân viên đã được định sẵn. ID của nhân viên là một thuộc tính cơng cộng của Web Part và được định nghĩa các vùng thuộc tính như sau:
[Browsable(true),
Category("Miscellaneous"),
Description("The ID of the selected employee"), DefaultValue(1),
FriendlyName("EmployeeID"),
public int EmployeeID {
get {return _employeeID;} set {_employeeID = value;} }
Như đã nói ở trên, trong sự kiện CellReady ta đã đóng gói dữ liệu của nó và chuyển cho consumer; với khả năng có thể hiển thị và cá nhân hóa thì các thuộc tính cũng hiển thị trên thanh editing box chuẩn của Web Part như hình sau:
Hình vẽ 3.21: Thay đổi thuộc tính Employee ID
Việc dịch mã của Web Part sẽ thi hành các truy vấn dựa vào SQL Server, nắm lấy các thông tin cá nhân về các đặc trưng người dùng như employee ID và đưa ra một bảng hiển thị HTML để hiển thị thơng tin, ở đây để làm ví dụ ta có thể chọn cơ sở dữ liệu Northwind.
3.3.5.4. Thi hành Consumer
Viết một consumer Web Part khơng khó hơn việc thiết lập một provider. Ta lặp lại cùng các bước ở trên để thêm vào một consumer Web Part cho dự án. Nếu cả hai Web part chứa trong cùng một Asembly ta cần tạo ra một DWP file thứ hai. Trong trường hợp đơn giản nhất ta chỉ cần cài đè phương thức ảo CellReady và thu về bất cứ giá trị nào mà provider cung cấp và cất dữ các giá trị đó.
Phương thức CellReady thu về một đối tượng CellReadyEventArgs mà trong nó có chứa thuộc tính Cell chỉ đến bất cứ giá trị nào mà provider đã cung cấp trong một tham số đối tượng tương tự trong phương thức PartCommunicationMain của
nó. Thuộc tính Cell có kiểu object, ta cần ép kiểu để chuyển nó về dạng dữ liệu phù hợp trước khi sử dụng.
Consumer cũng có thể muốn kiểm tra xem dữ liệu mà provider đưa ra có hợp khn dạng hay không, để làm điều này ta cần thực thi phương thức
CellProviderInit. Lưu ý ở đây là phương thức này khơng thể bị bỏ qn vì nó là một
phần của giao diện ICellConsumer.
public void CellProviderInit(object sender,
CellProviderInitEventArgs cellProviderInitArgs) {
if (cellProviderInitArgs.FieldName != "EmployeeID") {
throw new NotSupportedException(); }
}
Ở đây lớp CellProviderInitEventArgs đã được điền đầy dữ liệu bởi provider khi provider phát sinh sự kiện CellProviderInit. Sau đây là một đoạn mã chuẩn để làm điều này:
public override void PartCommunicationInit() {
if (CellProviderInit != null) {
CellProviderInitEventArgs cellProviderInitArgs;
cellProviderInitArgs = new CellProviderInitEventArgs(); cellProviderInitArgs.FieldName = "EmployeeID";
cellProviderInitArgs.FieldDisplayName = "Employee ID"; CellProviderInit(this, cellProviderInitArgs);
} }
Thuộc tính FieldName cho biết tên của đối tượng dữ liệu đang được chuyển giao,
dữ liệu này khơng có cú pháp chính xác – nó có thể là bất cứ thứ gì.
Sau đây là một consumer Web Part đơn giản đọc employee ID thông qua kết nối với provider và hiển thị tất cả các hàng được cung cấp trong thuộc tính year tương ứng.
year là một thuộc tính của Web Part mà ta tạo ra, nó là một thuộc tính cơng cộng và
có thể hiển thị được, ta định nghĩa nó như sau:
[Browsable(true),
Category("Miscellaneous"),
Description("Year of selected orders"), DefaultValue(1997),
FriendlyName("Year"),
WebPartStorageAttribute(Storage.Personal)] public int Year
{
get {return _year;} set {_year = value;} }
Employee ID và year là hai tham số được sử dụng trong truy vấn SQL mà kết quả truy vấn được hiển thị thông qua một DataGrid đã được thiết lập để trình bày dữ liệu.
private void BuildUI(HtmlTextWriter writer) {
DataGrid _grid = new DataGrid(); _grid.AutoGenerateColumns = true; _grid.Font.Name = "verdana"; _grid.Font.Size = FontUnit.Point(8); _grid.HeaderStyle.Font.Bold = true; _grid.HeaderStyle.BackColor = Color.PaleTurquoise; _grid.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
_grid.DataSource = _data; _grid.DataBind();
_grid.RenderControl(writer); }
Hình sau cho thấy hai Web Part làm việc cùng nhau trong một Web Page.
Hai Web Part đã được kết nối với nhau
3.3.5.5. Thiết lập kết nối
Ở phần trên ta đã trình bày cách viết một provider và consumer, các hàm giao diện làm cho chúng làm việc cùng nhau. Để thiết lập môt kết nối giữa hai Web Part theo cách thông thường, ta thiết lập trang Web ở chế độ design và kích vào menu Web Part của Provider (hoặc consumer). Sau đó lựa chọn menu thả xuống Connections và làm theo các chỉ dẫn sau đó, hình sau minh họa điều đó:
Hình vẽ 3.22: Hai Web Part đang kết nối với nhau
3.3.5.6. Một số mơ hình kết nối khác
Sự kết nối giữa hai Web Part dựa trên một cặp giao diện phản chiếu lẫn nhau; tồn tại một mơi trường trung gian ở giữa có trách nhiệm gọi các phương thức ở hai bên một cách thích hợp. Các giao diện kết nối khác dành cho việc chu chuyển các dữ liệu được liệt kê ở bảng sau:
Giao diện Ý nghĩa
ICellProvider, ICellConsumer Dùng để trao đổi các giá trị đơn giữa các Web Part
IRowProvider, IRowConsumer Dùng để trao đổi một dịng thơng tin đơn giữa các Web Part
IListProvider, IListConsumer Trao đổi một danh sách các dữ liệu
IFilterProvider, IFilterConsumer Lọc qua các biểu thức mà chứa một hoặc nhiều cặp tên cột và giá trị
Bảng 3.5: Các cặp giao diện provider/consumer thông dụng
Thông thường, một Web Part mà thi hành giao diện consumer có thể kết nối tới và nhận các dữ liệu từ một Web Part mà thi hành một giao diện provider tương thích. Các giao diện tương thích và bổ sung được liệt kê ở bảng trên.
Tất cả giao diện ở bảng 1 có thể kết nối tới mỗi giao diện khác trong một trình duyệt. Tuy nhiên có hai cặp giao diện khác nữa mà ta có thể sử dụng để kết nối
các Web Part trong FrontPage 2003 nhưng khơng phải trong trình duyệt, bảng sau sẽ liệt kê hai cặp giao diện đó:
Interfaces Description
IParametersOutProvider, IParametersOutConsumer
Giao diện provider định nghĩa ra một tập các tham số mà nó có thể gửi cho consumer
IParametersInProvider, IParametersInConsumer
Giao diện consumer định nghĩa một tập các tham số mà nó có thể nhận được từ Provider
Bảng 3.6: Các giao diện chỉ dùng cho FrontPage 2003
Sự khác biệt giữa các cặp giao diện IParametersOut và IParametersIn là một sự tinh tế. Một mặt, provider định nghĩa ra các tham số cái mà được chuyển giao cho consumer. Mặt khác consumer định nghĩa ra những tham số nào sẽ được thu về. Thông thường consumer thể hiện vai trò bị động so với provider. Có thể xảy ra trường hợp một provider không thể kết nối tới một consumer thích hợp được. Để giải quyết vấn đề đó, cơ sở hạ tần Web Part cung cấp một vài biến thể khác để cho phép các Web Part có thể kết nối được với nhau ngay cả khi các giao diện của chúng không khớp với nhau. Các biến thể được liệt kê như sau:
Biến thể Cách thức hoạt động
IRowProvider to ICellConsumer Một hộp thoại xuất hiện cho phép ta lựa chọn những ô nào bên trong hàng chuẩn bị được ánh xạ
IRowProvider to IFilterConsumer Một hộp thoại xuất hiện để ép buộc consumer lựa chọn một cột đơn trong hàng để lọc các thông tin
IParametersOutProvider to
IParametersInConsumer
Một hộp thoại xuất hiện để người dùng định nghĩa ra cách thức mà các tham số từ provider có thể ánh xạ tới các tham số của consumer. (Khơng có khả năng kết nối trong trình duyệt)
IRowProvider to
IParametersInConsumer
Một hộp thoại xuất hiện chỉ dẫn cho người dùng ánh xạ những cột nào ở trong hàng tới các tham số của consumer. (Khơng có khả năng kết nối trong trình duyệt)
Bảng 3.7: Các giao diện biến thể bên trong
Một số mơ hình kết nối khác cho phép kết nối hai Web Part ở hai trang khác biệt. Bảng sau liệt kê các giao diện có thể thực hiện kết nối xuyên qua các trang:
Trong trang nguồn Trong trang đích
IRowProvider IFilterConsumer
IRowProvider IParametersInConsumer
IFilterProvider IFilterConsumer
IParametersInProvider IParametersInConsumer
Bảng 3.8: Các giao diện hỗ trợ các kịch bản kết nối xuyên trang
Trang nguồn phải chứa đựng một provider Web Part thực thi tất cả các giao diện liệt kê ở cột bên phải của bảng trên. Mặt khác trang đích phải chứa một Web Part thực thi các giao diện tương ứng được liệt kê ở cột thứ hai của bảng trên.
Như vậy Khả năng kết nối các Web Part đưa thêm tính linh động cũng như sức mạnh đến cho công nghệ Share Point lên một mức mới. Các Web Part có khả năng kết nối cũng tương tự như các Web Part thông thường ngoại trừ việc chúng thực thi các giao diện đặc biệt mà cho phép chúng “nói chuyện” được với các Web Part tại thời điểm thực thi.
Kết chương: chương này đã trình bày khá chi tiết về công nghệ SharePoint, bao
gồm: Windows SharePoint Services, SharePoint Portal Server, cơng nghệ lập trình Web Parts. Có thể nói Windows Server 2003, SQL Server, SharePoint và MS Office đi với nhau sẽ tạo thành một hệ thống cực kì mạnh mẽ, có thể phát triển những ứng dụng (về Portal nói riêng) có quy mơ lớn. Đặc biệt SharePoint rất phù hợp với bài toán về cổng nội bộ quản lý doanh nghiệp vì SharePoint hướng đến một nền cộng tác rất cao. Chương sau sẽ trình bày việc ứng dụng SharePoint để xây