11.6.1  概述

ASP.NET 2.0的Web部件构的实现已经支持Web部件之间的连接。一个连接包含两个Web部件一个是提供者,负责向其他Web部件发布数据另一个是消费者,负责检索使用数据。听起来虽然简单,但这种性能支持Web部件对的开发,Web部件对同时使用时可提供强壮的解决方案。假设一个灵活的报告报表解决方案需要用到Web部件。一个一种方法是创建一个显示Web部件,用以显示可用的预生成报告报表的列表。选择列表中的一个报告报表时,另一个Web部件就会在页面的其他地方显示该报另一个另一种方法是创建一个Web部件,该Web部件允许用户从后端企业系统中选择和过滤数据。数据被过滤和管理时,连接的Web部件就会将数据作为图片呈现,向用户提供包含原始数据和形象化可视化数据的视图。

11.6.2  Web部件连接的类型

在WSS v3中,连接有两种类型:静态和动态。在WSS v3中,当连接中的一个或两个Web部件不在Web部件区域内时,可用静态连接建立Web部件间的连接。但是,在ASP.NET 2.0中,静态连接只是ASPX页面标记中定义声明的那部分。静态连接的局限性在于它不能通过Web浏览器接口来建立。相反,静态连接必须通过使用SPWebPartManager.AddConnectin方法的对象模型或使用微软的SPD建立。

动态连接要求连接内的两个Web部件都驻入位于Web部件区域。这是最为通用的连接类型,可通过Web浏览器接口建立。

11.6.3  Web部件连接的实现——连接点

ASP.NET 2.0连接是根据“拉”模型建立的,而不是根据“推”模型或订阅模型。如果两个Web部件间事先建立了连接,那么消费者部件装载时,会向已连接的提供者部件请求数据。要使Web部件间能互相通信,它们必须使用同一种语言。这通过实现同一接口的提供对象和消费对象来实现。要使两个Web部件参与到一个连接中,则提供者和消费者都必须至少有一个连接点。连接点包含连接到其他Web部件所必需的所有消息,包括控件ID、控件可识别的数据类型等。Web部件添加连接点时,只需用ConnectionProvider属性修改提供者的特定方法、用ConnectionConsumer属性修改消费者的特定方法即可。用ConnectionProvider属性修改的方法必须返回一个接口,用ConnectionConsumer属性修改的方法必须接收该接口的一个参数。用必要的属性完成实现和修改后,Web部件酒会构就会在连接的通信过程中使用注册的callback回调方法。下面的代码片断片段给出了ConnectionProvider属性和ConnectionConsumer属性的使用方法:

[ConnectionProvider("Connection Provider Name")]

public Ifoo GetProviderInterface()

{

  return foo;

}

ConnetionConsumer attribute:

[connectionConsumer("Connection Consumer Name")]

public void SetConsumerInterface(Ifoo foo)

{}

初始化连接过程时,Web部件会调用提供者部件上的已注册callback的回调方法,在上述代码中是GetProviderInterface。该方法返回IFoo类型的对象。会获取该对象,并调用消费者部件上的已注册callback的回调方法(本例中是指SetConsumerInterface),以传递提供者的callback回调方法返回的对象。

注意,ConnectionProvider和ConnectionComsumerConnectionConsumer的构造函数都只有一个参数。这是连接的显示名称,也是抽象类ConnectionPoint中定义的唯一必需的属性。其他要注意的是抽象类ConnectionPoint中的一些可用属性,如表11-3所示。

表11-3  ConnectionPoint的属性

属  性  名

描    述

ControlType

返回与连接点关联的服务器控件类型。一般为WebPart类型

DisplayName

将Web部件的名称作为字符串返回。创建连接点时,用户界面中要用到该字符串

ID

识别连接点的唯一字符串。如果在Web部件中只指定一个连接点,那么Web部件就会自动设置该值。但是,如果指定了多个连接点,就必须为每个连接点都指定一个ID

InterfaceType

返回连接点所使用的接口类型

WSS v2开发者可能会记得ICellConsumer/ICellProvider和IRowConsumer/IRowProvider接口。目前,已使用Obsolete属性修改了这两个方法,而且WSS v3也不提倡两个接口的使用因此,可以使用前面提到的两个接口创建自定义的接口,如果可能的话,也可以使用.NET Web部件包含的接口:IWebPartField、IWebPartRow和IWebPartTable,以在接口未知的Web部件间传递数据。

创建两个对接的Web部件

要了解对接的Web部件的工作方式,就要创建参与同一连接的提供者部件和消费者部件。在这个例子中,创建一个总统提供者President Provider部件,它包含一个列表,在该列表中,用户可选择前五任美国总统的一个。当用户选择了一个总统时,页面就会刷新,President Provider总统消费部件就会显示所选总统的全名。

1. 创建Web部件连接所使用的接口

首先,创建一个提供者和消费者都能识别的接口。

(1) 创建VS.NET类库Web Part Techniques.Second

(2) 在VS.NET中创建一个新接口IPresident.cs,其代码如代码清单11-19所示

代码清单11-19  接口IPresident.cs

using System;

namespace WebPartTechniques.Second

{

  public interface IPresident

  {

    int PresidentNumber { get;}

  }

}

 

2. 创建对接的提供者部件

两个Web部件都要用到接口IPresident.cs。创建提供者部件,一旦建立连接,该部件就向消费者部件提供数据。

(31) 在VS.NET中创建一个新类PresidentProvider.cs,其代码如代码清单11-20所示(注意实现IPresident接口的Web部件):

代码清单11-20  PresidentProviderPart类

using System.Web.UI.WebControls;

using System.Web.UI.WebControls.WebParts;

namespace WebPartTechniques.Second

{

  public class PresidentProviderPart :

    System.Web.UI.WebControls.WebParts.WebPart,

    ProviderWebParts.IPresident

  {

    DropDownList presidentPicker = null;

  }

}

(42) 在PresidentProvider类中添加私有的下拉列表。

(53) 添加代码清单11-21的代码,以重载重写CreateChildControls方法,该方法将初始化Web部件,并在Web部件中添加按钮和总统选项选择器

代码清单11-21  PresidentProviderPart的CreateChildControls方法

protected override void CreateChildControls()

{

  base.CreateChildControls();

  try

  {

    //Instantiate, Initialize,

    // wIreup (in this case, require a post back on change)

    // and Insert the control into the Web Part class

    //Note: The ListItem value is provided to the consumer of

    // the Web Part connection

    presidentPicker = new DropDownList();

    presidentPicker.Items.Add(new ListItem("Pick a President", "0"));

    presidentPicker.Items.Add(new ListItem("Washington", "1"));

    presidentPicker.Items.Add(new ListItem("Adams", "2"));

    presidentPicker.Items.Add(new ListItem("Jefferson", "3"));

    presidentPicker.Items.Add(new ListItem("Madison", "4"));

    presidentPicker.Items.Add(new ListItem("Monroe", "5"));

    presidentPicker.AutoPostBack = true;

    this.Controls.Add(presidentPicker);

  }

  catch (Exception ex)

  {

    this.Controls.Clear();

    Literal msg = new Literal();

    msg.Text = ex.Message;

    this.Controls.Add(msg);

  }

}

实现PresidentProvider类中IPresident的必要部分。在这个中,添加一个只读属性。

(64) 在PresidentProvider类添加代码清单11-22中的只读属性:

代码清单11-22  PresidentNumber属性

public int PresidentNumber

{

  get { return int.Parse(presidentPicker.SelectedValue); }

}

创建提供者Web部件的最后一步是创建提供者连接点。为此,要创建返回IPresident接口的实现实例,并用ConnectionProviderAttribute修改该方法。

(75) 添加代码清单11-23的代码,使得Web部件作为提供者参与连接:

代码清单11-23  提供者连接点

[System.Web.UI.WebControls.WebParts.ConnectionProvider(

  "President Number")]

public IPresident GetPresidentProvider()

{

  return this;

}

经过Web部件签名创建.webpart文件后,该Web部件的创建就完成了。只要将总统提供者President Provider部件部署到WSS v3站点,就可以将其添加到Web页上的任意Web部件区域了。该Web部件的视图如图11-11所示。

图11-11  President Provider总统提供者部件

3. 创建对接的消费者部件

现在来创建消费者Web部件

(1) 用代码清单11-24的代码在VS.NET中创建新的公共类PresidentConsumer.cs。

代码清单11-24  PresidentConsumerPart类

using System.Web.UI.WebControls;

namespace WebPartTechniques.Second

{

  public class PresidentConsumerPart :

    System.Web.UI.WebControls.WebParts.WebPart,

    ProviderWebParts.IPresident

  {

    int m_selectedPresidentIndex = 0;

    ProviderWebParts.IPresident m_presidentProvider = null;

    Label lbl = null;

  }

}

(2) 在PresidentConsumer类中添加一些私有字段:

添加Web部件特定的代码之前,要创建一个帮助方法(helper method),以根据President Provider总统提供者部件传递的编号确定总统。可以使用简单的switch语句实现。

(3) 将代码清单11-25的代码添加到PresidentConsumer类中:

代码清单11-25  PresidentConsumerPart的GetPresidentByIndex方法

private string GetPresidentByIndex(int index)

{

  switch (index)

  {

    case 1:

      return "George Washington";

    case 2:

      return "John Adams";

    case 3:

      return "Thomas Jefferson";

    case 4:

      return "James Madison";

    case 5:

      return "James Monroe";

    default:

      return "No president selected";

  }

}

(4) 将代码清单11-26的代码添加到PresidentConsumerPart类中,以重载重写原有的RenderContents方法:

代码清单11-26  PresidentConsumerPart的RenderContents方法

protected override void CreateChildControls()

{

  base.CreateChildControls();

  try

  {

    lbl = new Label();

    lbl.Text = "No president selected";

    this.Controls.Add(lbl);

  }

  catch (Exception ex)

  {

    this.Controls.Clear();

    Literal msg = new Literal();

    msg.Text = ex.Message;

    this.Controls.Add(msg);

  }

}

protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)

{

  //This must be done late in the Page Life Cycle

  if (this.m_selectedPresidentIndex > 0)

  {

    lbl.Text = "President #" +

      this.m_selectedPresidentIndex +

      ": " +

      GetPresidentByIndex(this.m_selectedPresidentIndex) +

      " was selected.";

  }

  base.RenderContents(writer);

}

重载重写连接建立后要调用的OnPreRender方法。该方法会通过PresidentNumber属性(定义于IPresident接口,实现于President Provider总统提供者部件)检索所选的总统编号。如果连接没有建立,就不会执行任何操作。

(5) 将代码清单11-27的代码添加到PresidentConsumer类中。

代码清单11-27  PresidentConsumerPart的OnPreRender重载重写方法

protected override void OnPreRender(EventArgs e)

{

  if (this.m_presidentProvider != null)

  {

    this.m_selectedPresidentIndex =

      this.m_presidentProvider.PresidentNumber;

  }

}

(6) 将代码清单11-28的代码添加到PresidentConsumer类中,使Web部件作为消费者参与连接:

代码清单11-28  PresidentConsumerPart类的消费者连接点

[System.Web.UI.WebControls.WebParts.ConnectionConsumer(

  "President Number")]

public void GetConnectedProviderInterface(

  ProviderWebParts.IPresident connectionProvider)

{

  m_presidentProvider = connectionProvider;

}

保存更改,构建编译项目。完成部署Web部件的其他必要任务,并将其添加到WSS v3站点之后将该Web部件添加到同一页面(即添加President Provider总统提供者部件的页面)的任意Web部件区域。该Web部件的视图如图11-12所示。

图11-12  President Consumer总统消费者部件

4. 连接提供者部件和消费者部件

President Provider总统提供者部件和消费者President Consumer部件添加到Web页后,所剩的工作就是连接这两个部件。选择Site Actions菜单Edit Page选项。单击标题栏的编辑菜单或Web部件时,Connections菜单项就会发亮高亮显示。提供者部件Connections菜单的子菜单项(如图11-13所示)和消费者部件Connections菜单的子菜单项(如图11-14所示)有点不同。提供者使用“Send…To”方式,而消费者使用“Get..From”方式。

 

图11-13  President Provider总统提供者部件的Connections菜单

 

图11-14  President Consumer总统消费者部件的Connections菜单

单击Web部件标题栏的Edit菜单就可建立两Web部件间的连接。单击Site Actions菜单下方的Exit Edit Mode。从President Provider总统提供者部件的选择列表中选择一个编号,并单击Show president按钮。

页面会自动刷新,并在President Display Consumer总统显示消费者部件中显示所选总统的编号和姓名,如图11-15所示。

 

图11-15  证实Web部件连接的President Provider总统提供者部件和President Consumer总统消费者部件

如实例所示,除了要构建一个典型的Web部件外,不需要大量的编码工作,就可添加提供者和消费者连接能力,创建一个Web部件连接。

11.6.4  Web部件连接的实现——转换器

提供者部件和消费者部件是否必须返回和识别同一个接口类型?如果两个Web部件不能识别相同的接口,它们就不兼容,也就不能实现连接。但这并不是尽头Web部件包含了一个机制,该机制支持用户连接识别不同接口的两个Web部件。要建立这种Web部件间的连接,就必须实现一个自定义的转换器,以将提供者部件的数据转换成消费者部件可接收的形式。ASP.NET 2.0包含了两个转换器RowToFieldTransformer和RowToParameterTransformer,它们是用接口IWebPartField和IWebPartRow实现的。如果Web部件使用的是自定义接口,则只需继承基类WebPartTransformer并实现Transform方法,就可创建一个自定义转换器。Transform方法只接收一个对象作为参数(不管提供者部件连接点返回什么),并返回调用消费者部件连接点所需的对象。

11.6.5  ASP.NET 2.0和WSS v3的Web部件连接之间的区别

ASP.NET团队采用了修正的Web部件,该最早在WSS v2中引入,WSS的最新版本WSS v3则建立在ASP.NET 2.0的基础上,继承了新的实现。虽然WSS v3融合了.NET Web部件的实现,但两个环境还是存在些许差异。推荐.NET Web部件在WSS v3中使用.NET Web部件,因为这样可以通过继承WSS v3的WebPart类(取代ASP.NET 2.0的WebPart类),来克服.NET Web部件的一些局限性。

Web部件的ASP.NET 2.0实现引入了与单个Web部件相关联的消费者连接数量的限制。WSS v2中,Web部件有无数的提供者和消费者连接。然而在ASP.NET 2.0中,虽然Web部件仍然有无数的提供者连接,但却只由一个消费者连接。如果需要无数的消费者连接,Web部件就要继承WSS v3的WebPart类,并设置UnlimitedConnections属性。这借鉴了WSS v2的连接行为。

两个环境的另一个区别是,ASP.NET 2.0不支持不同页面上Web部件间的连接。跨页连接是WSS v2的特性之一,但.NET Web部件的实现中没有采用该特性。但是然而,出于向后兼容性的原因,WSS v3的WebPart类支持不同页面上Web部件间的连接。

WSS v3 Web部件实现和WSS v2实现的最大改变在于安全策略。在WSS v2中,连接两个Web部件时,WSS站点要以CAS设置方式运行Web应用程序(该Web应用程序必须定义了WebPartPermission,而且要将Connections属性的值设为true)。虽然WSS v3仍然支持这种方式,但在WSS站点的CAS策略中已没必要包含该方法。原因很简单:底层体系结构发生了变化。在.NET Web部件实现中,连接绑定接口归WebPartManager(或WSS v3中的SPWebPartManager)所有。WebPartManager不需要为每个ASP.NET 2.0站点在CAS策略文件中定义这种许可。因此,由于WSS v3不再拥有连接绑定接口,也是通过ASP.NET 2.0的 WebPartManager来控制,所以,建立或处理连接时,就不能声明该许可。WSS v2相比看起来,WSS v3的站点主人主持可能会丧失一些控制权,但仍然保留了其他的控制机制,作为站点管理员,仍能通过虚拟的服务器级设置阻止新的Web部件连接的创建。

posted on 2010-06-09 16:10  寂寞的DBOY  阅读(319)  评论(0编辑  收藏  举报