升级 Web 部件
上次修改时间: 2011年9月1日
适用范围: SharePoint Foundation 2010
本主题介绍用于升级 Web 部件的最正确、最全面的方法。此方法考虑以下问题:Web 部件是否为 SharePoint Foundation、混合或 ASP.NET Web 部件,Web 部件是否要从一种类型的 Web 部件转换为另一种类型,将执行哪种类型的升级操作,以及运行或不运行升级代码的情况。如果要创建新版本的 Web 部件,并且需要对为以前版本的 Web 部件存储的属性值执行升级逻辑,Microsoft SharePoint Foundation 2010 将提供下列选项。
实现 AfterDeserialize
如果旧版本都是 Microsoft SharePoint Foundation Web 部件,并且新版本是 SharePoint Foundation 2010 Web 部件或混合 Web 部件,请实现 AfterDeserialize() 方法以升级 Web 部件。将旧版本反序列化为新版本时,将始终调用此方法,如果 Web 部件在页面中是静态的(即在区域外)、是动态的(即在区域内)或者已通过对象模型调用实例化,则会如此。但是,在从旧反序列化版本升级到新版本时,仅调用 AfterDeserialize() 一次,将 Web 部件升级到混合 Web 部件后,将不再调用 AfterDeserialize()。因此,如果已将 SharePoint Foundation Web 部件转换为混合 Web 部件,并在将它部署为混合 Web 部件后向混合 Web 部件中添加一些升级逻辑,则必须实现 AfterDeserialize() 以处理 SharePoint Foundation Web 部件到混合 Web 部件 2.0 的升级过程。还必须实现下面所述的接口,以处理混合 Web 部件 1.0 到混合 Web 部件 2.0 的升级过程。为此,建议您创建 AfterDeserialize() 方法和接口实现都调用的共享升级函数(此处为 TransformMyString)。
如果旧版本的 Web 部件是混合 Web 部件或 ASP.NET Web 部件,并且新版本是混合 Web 部件或 ASP.NET Web 部件,则不会调用 AfterDeserialize(),并且必须从 OnInit()、EndLoad() 和 Load() 调用 Web 部件的升级逻辑,具体取决于升级必须实现的目标。
有关如何使用 AfterDeserialize() 方法的详细信息,请参阅升级 Microsoft SharePoint 产品和技术的 Web 部件程序集和 AfterDeserialize()。
检测属性状态
假定您具有名为 SampleProperty 的字符串属性并且格式已经更改,因此升级代码需要将 SampleProperty 的内容从旧格式转换为新格式。建议您创建一个 TransformSampleProperty 方法,以有效地检测 SampleProperty 是否已转换,并在未转换时执行转换。以下示例介绍如何执行此操作:
using Asp = System.Web.UI.WebControls.WebParts
public class MyWebPart : Asp.WebPart
{
private m_dirty = false;
[Insert your standard Web Part logic here…]
private void TransformMyString()
{
if ([SampleProperty is in the old format…])
{
[Transform the SampleProperty value to the new format…]
m_dirty = true;
}
if (m_dirty && null != WebPartManager)
{
SetPersonalizationDirty();
m_dirty = false;
}
}
}
从 OnInit() 和 EndLoad() 方法调用 TransformSampleProperty 将确保 Web 部件在页面中是静态的、动态的,或已通过对象模型调用实例化时调用升级代码。可能需要向 Web 部件添加"upgraded"或"version"属性,以便 TransformSampleProperty 可以在升级后设置该属性,以便对 TransformSampleProperty 的后续调用能够有效检测 MyString 是否已升级。请考虑使用 IPersonalizable 接口来存储"version"属性,因为此属性将与其余 Web 部件属性一起存储。不过,编辑 Web 部件的属性时,此属性不显示在用户界面的工具窗格中,并且在 Microsoft SharePoint Designer 中编辑 Web 部件时,它不会显示在 Web 部件的标记中。
在上面的示例中,将 Web 部件反序列化后,将调用 EndLoad(),并且因为 SampleProperty 采用旧格式,所以用于转换 SampleProperty 值的代码将运行。因为 Web 部件尚未添加到 WebPartManager 中,所以 MyWebPart.WebPartManager 保持为 Null,并且不会调用 SetPersonalizationDirty。将 Web 部件添加到页面中的 WebPartManager 中后,其生命周期将变为当前,并且将调用 MyWebPart.OnInit。不过,之后 MyString 将不再采用旧格式,并且 MyWebPart.WebPartManager 将生效。因此,将调用 SetPersonalizationDirty,这将导致升级的 Web 部件自动保存回内容数据库,而不考虑当前用户的权限。
如果 Web 部件在页面中是静态的,则不支持在运行 Web 部件的升级代码后更改页面中的标记,这意味着标记始终保持为升级前的状态,并且每次浏览页面时总是在 OnInit() 中重新运行升级代码。一种特殊情况是内容数据库在 SQL Server 中处于只读状态时 Web 部件会尝试将属性写回内容数据库。因为 Web 部件升级将有效延迟到每个实例的第一次使用,并且第一次使用可能发生在数据库处于只读状态时,所以可能会发生这种情况。Web 部件应该可以呈现,但正常情况下无法将更新保存到数据库。
更改属性名称
假定旧版本具有属性 X,在新版本中已经将其重命名为 Y。在这种情况下,应实现 Load() 并将用于存储在 X 中的值复制到 Y 中,并设置已更新标志。然后在 OnInit() 方法中检查已更新标志并调用 SetPersonalizationDirty。以下示例介绍如何执行此操作:
using Asp = System.Web.UI.WebControls.WebParts
public class MyWebPart : Asp.WebPart
{
private m_dirty = false;
[Standard Web Part logic here...]
void IVersioningPersonalizable.Load(IDictionary unknownProperties)
{
[Copy X into Y here…]
m_dirty = true;
}
protected override void OnInit(EventArgs e)
{
if (m_dirty && null != WebPartManager)
{
SetPersonalizationDirty();
m_dirty = false;
}
}
}
在上面的示例中,如果部件是动态的或者已通过对象模型调用实例化,将调用 Load();如果 Web 部件在页面中是静态的,则不调用此方法。
Web 部件框架调用 IVersioningPersonalizable 接口方法,而不考虑用户的凭据,并且如果 IVersioningPersonalizable 代码在以上示例中正确地将 Web 部件标记为已更新,则会使用不检查凭据的内部代码将升级的 Web 部件自动保存回存储。因此,即使具有有限权限的用户(例如读者)是第一个浏览页面的用户,升级仍可以按预期方式执行。
如果在页面中是静态的,则不会调用 Load()。但是,可以在 OnInit() 调用中添加代码,以查看 Web 部件的 Expando 属性(Asp.Net 控件概念,不是 Web 部件框架概念),从 Expando 属性复制 X 值并将此值分配给 Y。此外,在这种情况下,不支持在运行 Web 部件的升级代码后更改页面中的标记,这意味着标记始终保持为升级前的状态,并且每次浏览页面时总是重新运行 OnInit() 升级代码。
请参阅
概念
SharePoint Foundation 中的 Web 部件