如何:为 PerformancePoint Services 报告创建编辑器

上次修改时间: 2011年8月30日

在 Microsoft SharePoint Server 2010 中的 PerformancePoint Services 中,自定义编辑器使用户能够设置自定义对象的属性。它们提供了编辑控件并在库中检索和更新自定义对象。有关编辑器要求和功能的详细信息,请参阅用于自定义 PerformancePoint Services 对象的编辑器

适用范围: SharePoint Server 2010

报表编辑器还必须初始化报表端点,该端点从记分卡和筛选器提供程序接收参数值。

本主题中的过程和示例基于自定义对象示例中的 SampleReportViewEditor 类。编辑器是一个使用户能够修改报表的名称和说明的瘦 Web 应用程序。本主题的"示例"一节中提供了该类的完整代码。

备注

我们建议您将示例编辑器用作模板。该示例演示了如何调用 PerformancePoint Services API 中的对象,提供了简化库操作(例如创建和更新对象)调用的帮助程序对象,并演示了 PerformancePoint Services 开发的最佳实践。

通过执行两个基本过程来创建报表编辑器,如下所示:

  • 创建和配置编辑器类

  • 定义编辑功能

若要创建自定义编辑器,请首先创建编辑器类。

创建和配置编辑器类

  1. 安装 PerformancePoint Services,或者将您的扩展使用的 DLL(步骤 3 中列出)复制到您的计算机上。有关详细信息,请参阅 开发方案中使用的 PerformancePoint Services DLL

  2. 在 Visual Studio 中,创建一个 C# 类库。如果您已为扩展创建了一个类库,请添加新 C# 类。

  3. 将以下 PerformancePoint Services 和 SharePoint Server 2010 DLL 作为程序集引用添加到项目中:

    • Microsoft.PerformancePoint.Scorecards.Client.dll

    • Microsoft.PerformancePoint.Scorecards.ServerCommon.dll

    • Microsoft.PerformancePoint.Scorecards.Store.dll(由帮助程序类使用)

    • Microsoft.SharePoint.dll(由帮助程序类使用)

    示例编辑器还包含对 System.Web.dll 和 System.Web.Services.dll 的程序集引用。根据您的扩展的功能,可能需要其他项目引用。

  4. 将示例中的以下类添加到项目中。编辑器使用这些帮助程序类来与 PerformancePoint Services 存储库进行交互:

    • DataSourceConsumerHelper.cs

    • ExtensionRepositoryHelper.cs

    • ReportViewRepositoryHelper.cs

    • IDataSourceConsumer.cs

    备注

    示例报表从筛选器获取数据,所以它没有使用 DataSourceConsumerHelper 或 IDataSourceConsumer 对象。不过,如果报表从 PerformancePoint Services 数据源获取数据,则可以使用 DataSourceConsumerHelper 类公开的方法来检索数据源,如如何:为 PerformancePoint Services 筛选器创建编辑器中所述。

  5. 在编辑器类中,为以下 PerformancePoint Services 命名空间添加 using 指令:

    • Microsoft.PerformancePoint.Scorecards

    • Microsoft.PerformancePoint.Scorecards.ServerCommon

    根据您的扩展的功能,可能需要其他 using 指令。

  6. 从支持您的编辑器实现的基类继承。因为示例报表编辑器是 Web 应用程序,所以它从 Page 类继承。其他实现可从基类(例如 UserControlWebPart 类)派生。

创建和配置编辑器类后,必须定义编辑器的功能。

定义编辑功能

  1. 声明公开您希望用户查看或修改的属性的控件的变量。示例报表编辑器首先声明用户界面组件(这是一个 ASPX 页)中定义的 Web 服务器控件的变量。示例编辑器还定义使用户能够提交更改的按钮控件。然后,编辑器调用 CreateChildControls() 方法使控件可在该页上使用。

    备注

    编辑器独立于用户界面定义编程逻辑。有关创建编辑器的用户界面组件的说明不在本文档的讨论范围内。

  2. AllowUnsafeUpdates 属性设置为 true。这使报表编辑器能够将数据写入库中,而无需使用表单发布操作。

    示例报表编辑器在 Page_Load 方法中执行步骤 2 至 6。Page_Load 还用于初始化和验证变量和控件、填充控件以及保存自定义报表和帮助程序对象的状态信息。

  3. 从查询字符串检索参数并将它们设置为本地变量的值,如以下代码示例中所示。

    // The URL of the site collection that contains the PerformancePoint Services repository.
    string server = Request.QueryString[ClickOnceLaunchKeys.SiteCollectionUrl];
    
    // The location of the report in the repository.
    string itemLocation = Request.QueryString[ClickOnceLaunchKeys.ItemLocation];
    
    // The operation to perform: OpenItem or CreateItem.
    string action = Request.QueryString[ClickOnceLaunchKeys.LaunchOperation];
    

    有关查询字符串参数的信息,请参阅用于自定义 PerformancePoint Services 对象的编辑器

  4. 检索 ReportViewRepositoryHelper 对象,它用于调用库,如以下代码示例中所示。

    reportviewRepositoryHelper = new ReportViewRepositoryHelper();
    
  5. 基于查询字符串参数设置报表位置,如以下代码示例中所示。

    RepositoryLocation repositoryReportViewLocation = RepositoryLocation.CreateFromUriString(itemLocation);
    
  6. 从查询字符串检索要执行的操作(OpenItem 或 CreateItem),然后检索或创建自定义报表,如以下代码示例中所示。

    if (ClickOnceLaunchValues.OpenItem.Equals(action, StringComparison.OrdinalIgnoreCase))
        {
    
            // Use the repository-helper object to retrieve the report.
            reportview = reportviewRepositoryHelper.Get(repositoryReportViewLocation);
            if (reportview == null)
            {
                displayError("Could not retrieve the report view for editing.");
                return;
            }
        }
        else if (ClickOnceLaunchValues.CreateItem.Equals(action, StringComparison.OrdinalIgnoreCase))
        {
            reportview = new ReportView
            {
                RendererClassName = typeof(SampleReportRenderer).AssemblyQualifiedName, 
                SubTypeId = "SampleReportView"
            };
        }
        else
        {
            displayError("Invalid Action.");
            return;
        }
    
    • 若要检索自定义报表,请使用 ReportViewRepositoryHelper.Get 方法。

    • 若要创建自定义报表,请使用 ReportView() 构造函数,然后定义报表的 NameRendererClassNameSubTypeId 属性。

      SubTypeId 是报表的唯一标识符,它必须与您在 PerformancePoint Services web.config 文件中为自定义报表指定的 subType 属性相匹配。RendererClassName 是定义呈现器 Web 服务器控件的类的完全限定名称。如果没有在编辑器中定义,则此值默认为 web.config 文件中指定的呈现器类。

    备注

    默认情况下,用户只能从 PerformancePoint 仪表板设计器创建自定义对象。若要使用户能够在仪表板设计器之外创建自定义对象,您必须添加一个菜单项以将 CreateItem 请求从库中的内容类型发送到编辑器。有关详细信息,请参阅用于自定义 PerformancePoint Services 对象的编辑器

  7. 定义报表的端点,这使报表能够从筛选器和记分卡检索数据。示例报表编辑器定义了所需的端点属性,如以下代码示例中所示。

    if (0 == reportview.EndPoints.Count)
    {
        EndPoint endpoint = new EndPoint
        {
            Category = EndPointCategory.None,
            UniqueName = "SampleReportView_EndPoint",
    
            // The display name is shown to users in Dashboard Designer.
            // It represents the endpoint that can be connected 
            // to a filter or scorecard.
            DisplayName = "Sample Report View EndPoint"
        };
    
        reportview.EndPoints.Add(endpoint);
    }
    

    示例编辑器在 VerifyReportView 方法中定义端点。它还使用 VerifyReportView 来验证是否设置了所需属性并定义可选的 CustomData 属性,后者可用来存储报表信息。

  8. 使用用户定义的更改来更新报表。示例报表编辑器中的 buttonOK_Click 方法调用 ReportViewRepositoryHelper.Update 方法来更新库中报表的 NameDescription 属性。buttonOK_Click 还用于验证控件内容并检索自定义报表和帮助程序对象的状态信息。

    备注

    用户可以编辑自定义对象的 NameDescriptionOwner("负责人")属性,并直接从仪表板设计器和 PerformancePoint Services 库中删除自定义对象。

    **下一步:**在创建报表编辑器(如果需要,包括其用户界面)和报表呈现器后,部署扩展,如如何:手动注册 PerformancePoint Services 扩展中所述。有关如何安装和配置示例报表扩展的说明,请参阅代码示例:自定义报表、筛选器和表格数据源对象中的"安装示例报表、筛选器和数据源对象"一节。

示例

以下代码示例在库中创建、检索和更新自定义报表并为 ASPX 页中定义的控件提供编程逻辑。

备注

在编译此代码示例之前,您必须配置开发环境,如创建和配置编辑器类中所述。

using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using Microsoft.PerformancePoint.Scorecards;
using Microsoft.PerformancePoint.Scorecards.ServerCommon;

namespace Microsoft.PerformancePoint.SDK.Samples.SampleReport
{

    // Represents the class that defines the sample report editor. 
    public class SampleReportViewEditor : Page
    {

        // Declare private variables for the ASP.NET controls defined in the user interface.
        // The sample's user interface is an ASPX page that defines the controls in HTML.
        private TextBox textboxName;
        private TextBox textboxDescription;
        private Label labelErrorMessage;
        private Button buttonOK;

        // Make the controls available to this class.
        protected override void CreateChildControls()
        {
            base.CreateChildControls();

            if (null == textboxName)
                textboxName = FindControl("textboxName") as TextBox;
            if (null == textboxDescription)
                textboxDescription = FindControl("textboxDescription") as TextBox;
            if (null == labelErrorMessage)
                labelErrorMessage = FindControl("labelErrorMessage") as Label;
            if (null == buttonOK)
                buttonOK = FindControl("buttonOK") as Button;
        }

        // Handles the Load event of the Page control.
        // Methods that use a control variable should call the Control.EnsureChildControls
        // method before accessing the variable for the first time.
        protected void Page_Load(object sender, EventArgs e)
        {

            // Required to enable custom report and filter editors to
            // write data to the repository.
            ServerUtils.AllowUnsafeUpdates = true;

            // Initialize controls the first time the page loads only.
            if (!IsPostBack)
            {
                EnsureChildControls();
                ReportViewRepositoryHelper reportviewRepositoryHelper = null;
                try
                {

                    // Get information from the query string parameters.
                    string server = Request.QueryString[ClickOnceLaunchKeys.SiteCollectionUrl];
                    string itemLocation = Request.QueryString[ClickOnceLaunchKeys.ItemLocation];
                    string action = Request.QueryString[ClickOnceLaunchKeys.LaunchOperation];

                    // Validate the query string parameters.
                    if (string.IsNullOrEmpty(server) ||
                        string.IsNullOrEmpty(itemLocation) ||
                        string.IsNullOrEmpty(action))
                    {
                        displayError("Invalid URL.");
                        return;
                    }

                    // Retrieve the repository-helper object.
                    reportviewRepositoryHelper =
                        new ReportViewRepositoryHelper();

                    // Set the report location by using the location from the query string.
                    RepositoryLocation repositoryReportViewLocation = RepositoryLocation.CreateFromUriString(itemLocation);

                    ReportView reportview;

                    // Retrieve or create the report object, depending on the operation
                    // passed in the query string (OpenItem or CreateItem).
                    if (ClickOnceLaunchValues.OpenItem.Equals(action, StringComparison.OrdinalIgnoreCase))
                    {

                        // Retrieve the report object by using the repository-helper object.
                        reportview = reportviewRepositoryHelper.Get(repositoryReportViewLocation);
                        if (reportview == null)
                        {
                            displayError("Could not retrieve the report view for editing.");
                            return;
                        }
                    }
                    else if (ClickOnceLaunchValues.CreateItem.Equals(action, StringComparison.OrdinalIgnoreCase))
                    {

                        // Create a report view.
                        // CreateItem requests can be sent from a SharePoint list, but
                        // you must create a custom menu item to send the request.
                        // Dashboard Designer can send edit requests only.
                        reportview = new ReportView
                        {
                            RendererClassName = typeof(SampleReportRenderer).AssemblyQualifiedName, 
                            SubTypeId = "SampleReportView"
                        };
                    }
                    else
                    {
                        displayError("Invalid Action.");
                        return;
                    }

                    VerifyReportView(reportview);

                    // Save the original report and helper objects across page postbacks.
                    ViewState["action"] = action;
                    ViewState["reportview"] = reportview;
                    ViewState["reportviewrepositoryhelper"] = reportviewRepositoryHelper;
                    ViewState["itemlocation"] = itemLocation;

                    // Populate the child controls.
                    textboxName.Text = reportview.Name.ToString();
                    textboxDescription.Text = reportview.Description.ToString();
                }
                catch (Exception ex)
                {
                    displayError("An error has occurred. Please contact your administrator for more information.");
                    if (reportviewRepositoryHelper != null)
                    {

                        // Add the exception detail to the server event log.
                        reportviewRepositoryHelper.HandleException(ex);
                    }
                }
            }
        }

        // Handles the Click event of the buttonOK control.
        protected void buttonOK_Click(object sender, EventArgs e)
        {
            EnsureChildControls();

            // Verify that the textboxName control contains a value.
            if (string.IsNullOrEmpty(textboxName.Text))
            {
                labelErrorMessage.Text = "A report view name is required.";
                return;
            }

            // Clear any pre-existing error message.
            labelErrorMessage.Text = string.Empty;

            // Retrieve the report and helper objects from view state.
            string action = (string)ViewState["action"];
            string itemLocation = (string) ViewState["itemlocation"];
            ReportView reportview = (ReportView)ViewState["reportview"];
            ReportViewRepositoryHelper reportviewRepositoryHelper = (ReportViewRepositoryHelper)ViewState["reportviewrepositoryhelper"];

            // Update the report object with form changes.
            reportview.Name.Text = textboxName.Text;
            reportview.Description.Text = textboxDescription.Text;

            // Save the report object to the PerformancePoint Services repository.
            try
            {
                reportview.Validate();
                if (ClickOnceLaunchValues.CreateItem.Equals(action, StringComparison.OrdinalIgnoreCase))
                {
                    reportview.CreatedDate = DateTime.Now;
                    ReportView newReportView = reportviewRepositoryHelper.Create(
                        string.IsNullOrEmpty(reportview.Location.ItemUrl) ? itemLocation : reportview.Location.ItemUrl, 
                        reportview);
                    ViewState["reportview"] = newReportView;
                    ViewState["action"] = ClickOnceLaunchValues.OpenItem;
                }
                else
                {
                    reportviewRepositoryHelper.Update(reportview);
                }
            }
            catch (Exception ex)
            {
                displayError("An error has occurred. Please contact your administrator for more information.");
                if (reportviewRepositoryHelper != null)
                {
                    // Add the exception detail to the server event log.
                    reportviewRepositoryHelper.HandleException(ex);
                }
            }
        }

        // Displays the error string in the labelErrorMessage label. 
        void displayError(string msg)
        {
            EnsureChildControls();

            labelErrorMessage.Text = msg;

            // Disable the OK button because the page is in an error state.
            buttonOK.Enabled = false;
            return;
        }

        // Verifies that the properties for the report object are set.
        static void VerifyReportView(ReportView reportview)
        {

            // Verify that all required properties are set. 
            if (string.IsNullOrEmpty(reportview.SubTypeId))
            {

                // This value must match the subType attribute specified
                // in the web.config file.
                reportview.SubTypeId = "SampleReportView";
            }

            if (string.IsNullOrEmpty(reportview.RendererClassName))
            {
                reportview.RendererClassName = typeof (SampleReportRenderer).AssemblyQualifiedName;
            }

            // Reports are consumers and do not use provider endpoints.
           reportview.BeginPoints.Clear();

            // If there are no consumer endpoints, create one so we can connect a filter or a scorecard to the report.
            if (0 == reportview.EndPoints.Count)
            {
                EndPoint endpoint = new EndPoint
                {
                    Category = EndPointCategory.None,
                    UniqueName = "SampleReportView_EndPoint",

                    // The display name is shown to users in Dashboard
                    // Designer to represent the endpoint that can be 
                    // connected to a filter or scorecard.
                    DisplayName = "Sample Report View EndPoint"
                };

                reportview.EndPoints.Add(endpoint);
            }
            
            // Set optional properties for reports.
            reportview.CustomData = "You can use this property to store custom information for this filter as a string or a serialized object.";
        }
    }
}

编译代码

在编译此代码示例之前,您必须配置开发环境,如创建和配置编辑器类中所述。

安全性

必须使用强名称对 DLL 进行签名。另外,确保 DLL 引用的所有程序集都具有强名称。有关如何使用强名称对程序集进行签名以及如何创建公钥/私钥对的信息,请参阅How to: Create a Public/Private Key Pair

请参阅

任务

如何:为 PerformancePoint Services 报告创建呈现器

概念

用于自定义 PerformancePoint Services 对象的编辑器

其他资源

为 PerformancePoint Services 创建自定义对象

SharePoint Server 2010 中的 PerformancePoint Services 的代码示例