SharePoint 2010 における .aspx ページ (リストフォームなど) のサンドボックス配置


※ SharePoint 2013 以降では、サンボボックス ソリューションは非推奨です。SharePoint アドイン (SharePoint Add-ins) による開発手法を使用してください。

環境 : Visual Studio 2010, SharePoint 2010

裏 10 行でズバリ ! サンドボックス ソリューション 

本シリーズは、「10 行でズバリ ! SharePoint 2010 開発」を理解された開発者向けに、さらに踏み込んだ内容を記載しています。(ちなみに、10 行にはおさまっていません。。。)

こんにちは。

サンドボックス配置に関するつぎの内容として、.aspx ページ (ASP.NET ページ) のサンドボックス ソリューション (sandboxed solution) におけるカスタマイズ方法とそのポイントを説明します。

補足 : ここではフォーム (List Form) を例に説明しますが、ビュー (List View) のカスタマイズについては こちら を参照してください。サンドボックス ソリューションにおけるリスト ビューの開発では、XSL を使用することができます。

.aspx (ASP.NET ページ), .ascx (ユーザーコントロール) のサンドボックスでの配置

.aspx ファイルや .ascx ファイルなどのマークアップファイル自身は、こちら で記載した方法を使ってモジュールとして配置できます。

しかし、通常の ASP.NET ページ、ユーザーコントロールでは、単なるマークアップだけではなく、「処理」 (CodeBehind) を含んでいることでしょう。しかし、サンドボックス ソリューションで配置される dll は GAC には登録されないため (専用のプロセス上にロードされるため)、こうした処理を含んだ .aspx ファイル、.ascx ファイルは、サンドボックス ソリューションでモジュールとして配置しても、この dll の中に含まれる処理を呼び出すことができません。(処理を含んだアセンブリが参照できません。)
このため、こうした「処理」を含んだ ASP.NET ページ (.aspx ファイル)、ユーザーコントロール (.ascx ファイル) をサンドボックス ソリューションで使用する場合は、以下の回避方法が考えられます。

  • ASP.NET ページ (.aspx) の上に、こちら で記載した方法で .xap ファイル (Silverlight アプリケーション) を配置し、この .xap ファイルの中で Silverlight 用の Client OM を使って処理をおこなう
  • ASP.NET ページ (.aspx) の上で、JavaScript の Client OM を使用して処理を記述する
  • ASP.NET ページ (.aspx) の上に、サンドボックス ソリューションの Web パーツを貼り付け、ここで処理を記述する
  • ASP.NET ページ (.aspx) やユーザー コントロール (.ascx) をマークアップで記述せずに、すべてプログラムコードで記述する

補足 : 上記の 4 番目の方法は、ページ (LayoutsPageBase クラス)、またはコントロール (UserControl クラス) を継承して独自のクラスを作成し、初期化時に、通常、ASP.NET が内部で自動生成するコントロールツリーを、以下の例の通りコードを使って実装する方法です。

// コントロール ツリー作成のサンプル
IParserAccessor accessor = this;
TextBox textbox1 = new TextBox();
textbox1.ID = "TextBox1";
accessor.AddParsedSubObject(textbox1);
accessor.AddParsedSubObject(new LiteralControl(" "));
Button button1 = new Button();
button1.ID = "Button1";
button1.Text = "OK";
accessor.AddParsedSubObject(button);

なお、このコードのようにプログラムコードでコントロールを実装した場合、.ascx ファイルや .aspx ファイルが物理的に配置されるわけではないので、このコントロールを使用する側もプログラムコードを用いて使用する必要があります。例えば、同じサンドボックス ソリューション内の Web パーツ内から使用することはできますが、.aspx をフォルダに配置して外からこのファイルをリンクすることや、リスト定義の編集フォーム (.aspx) として使用することができないので注意してください。(この場合、上記の 1 ~ 3 の方法を使用することになります。)
以下の Visual Studio 2010 の拡張機能マネージャー (アドイン) をインストールすると、上記の 4 番目の手法を用いて、.ascx ファイルを使用した視覚的 Web パーツ (Visual Web パーツ) をサンドボックス用のプログラムコードに自動変換します。(開発者は、.ascx ファイルをビジュアルに編集することで、サンドボックス用の Web パーツを作成できます。)

Visual Studio 2010 SharePoint Power Tools :

http://visualstudiogallery.msdn.microsoft.com/ja-jp/8e602a8c-6714-4549-9e95-f3700344b0d9 

ここでは、リストフォーム (.aspx ファイル) のカスタマイズを例に、この具体的なカスタマイズ方法を見ていきましょう。(このあと見ていくように、以下では、上記の 2 番目、3 番目の方法を使用しています。)

Step 1 : サンドボックスによるリスト フォーム (List Form) の配置

ここでは、「10 行でズバリ!! SharePoint のリスト定義の作成」で作成したリスト定義 (および、リストインスタンス) のプロジェクトを使用して、このプロジェクトに編集用のリストフォーム (List Form) を追加します。

まず、このプロジェクトを開いて、プロジェクトのプロパティで [サンドボックス ソリューション] を「True」に設定します。(また、こちら に記載したように、今回も、このフィーチャーのスコープを「Site」に変更しておきましょう。)

つぎに、このリスト定義にリスト フォームを追加します。プロジェクトの「ListDefinition1」を右クリックして、[追加] – [新しい項目] を選択し、[全般] タブで [テキスト ファイル] を追加します (下図)。この際、追加するテキスト ファイルの名前を「MyEditForm.aspx」とします。

作成された MyEditForm.aspx のプロパティウィンドウを表示し、[配置タイプ] を [ElementFile] に設定します。

MyEditForm.aspx のテキストを開き、以下の通り記述します。ここでは、フォームのタイトルを「テストタイトル」とし、編集フォームの上に (HTML の) テーブルを表示し、その右側にリスト (一覧) を表示します。(SharePoint のリスト フォームでは、下記の通り、ID 属性が「Main」の WebPartZone に、自動的にリスト フォーム コントロールを挿入します。)

<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="Utilities" Namespace="Microsoft.SharePoint.Utilities" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Register Tagprefix="asp" Namespace="System.Web.UI" Assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" %>
<%@ Register Tagprefix="WebPartPages" Namespace="Microsoft.SharePoint.WebPartPages" Assembly="Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Assembly Name="Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page language="C#" 
  MasterPageFile="~masterurl/default.master"  
  Inherits="Microsoft.SharePoint.WebPartPages.WebPartPage,Microsoft.SharePoint,Version=14.0.0.0,Culture=neutral,PublicKeyToken=71e9bce111e9429c"%>

<asp:Content ContentPlaceHolderId="PlaceHolderPageTitle" runat="server">
テストタイトル
</asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderPageTitleInTitleArea" runat="server">
テストタイトル
</asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderLeftNavBar" runat="server" >

</asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
  <table cellpadding="0" cellspacing="0" id="onetIDListForm" style="width:100%">
    <tr>
      <td bgcolor="#00ff00" valign="middle"></td>
      <td>
        <WebPartPages:WebPartZone runat="server" FrameType="None" ID="Main" Title="loc:Main" />
      </td>
    </tr>
  </table>
</asp:Content>

<asp:Content ContentPlaceHolderId="PlaceHolderAdditionalPageHead" runat="server">

</asp:Content>

さいごに、schema.xml を下記太字の通り変更します

    . . .
    <Forms>
      <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="EditForm" Url="MyEditForm.aspx" WebPartZoneID="Main" />
      <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
    </Forms>
  </MetaData>
</List>

注意 : なお、開発中に schema.xml を変更していると、時折、schema.xml の内容がキャッシュされる (すなわち、schema.xml におこなった変更が反映されない) ことがあります。この場合は、申し訳ありませんが、このリストが含まれている Feature の Id を変更するか、SharePoint で使用している IIS のアプリケーション プールを再起動してください。(Feature Id は、Feature Designer を表示して、プロパティ ウィンドウで変更できます。)

Step 2 : Web パーツを使った表示処理の実装

つぎに、上記のテーブルの左側に独自な処理を実装してみましょう。

プロジェクトに [Web パーツ] を追加し、以下の通り実装します。

public class WebPart1 : WebPart
{
    private Label label1, label2;

    protected override void CreateChildControls()
    {
        SPContext context = SPContext.Current;
        label1 = new Label();
        label1.Text = "リスト ID は" + context.ListId;
        this.Controls.Add(label1);
        this.Controls.Add(new LiteralControl("<BR />"));
        label2 = new Label();
        label2.Text = "アイテム ID は" + context.ItemId.ToString();
        this.Controls.Add(label2);
    }
}

Visual Studio でパッケージデザイナーを表示すると、プロパティウィンドウに、ソリューション ID という GUID が表示されていますので、これをコピーします。
つぎに、上記 Step 1 で作成した MyEditForm.aspx に、以下 (太字) の通り追記し、上記で作成した Web パーツをこの .aspx ファイルに挿入します。なお、下記で、SolutionId は、上記でコピーしたソリューション ID になりますので、作成したプロジェクトにあわせて値を設定しておいてください。

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
  <table cellpadding="0" cellspacing="0" id="onetIDListForm" style="width:100%">
    <tr>
      <td bgcolor="#00ff00" valign="middle">
        <WebPartPages:SPUserCodeWebPart runat="server"
          Title="testpart"
          Description="This is test."
          SolutionId="b01977f5-f003-4eeb-9fc7-d4fe65cc414b"
          AssemblyFullName="$SharePoint.Project.AssemblyFullName$"
          TypeFullName="ListDefinitionProject1.WebPart1.WebPart1">
        </WebPartPages:SPUserCodeWebPart>
      </td>
      <td>
        <WebPartPages:WebPartZone runat="server" FrameType="None" ID="Main" Title="loc:Main" />
      </td>
    </tr>
  </table>
</asp:Content>

ここで、いったん、動作を確認してみましょう。上記のプロジェクトでパッケージ (.wsp ファイル) の作成をおこない、SharePoint の画面 (ソリューションギャラリー) から、作成された .wsp をアップロードしてアクティブ化をおこないます。
アクティブ化をおこなうと、こちら に記載した通り、「出張費一覧」のリスト (リストインスタンス) が作成されます。このリストにアイテムを追加し、アイテムの編集フォーム (Edit Form) を表示すると、下図の通り、左に Web パーツが配置され、文字列が表示されているのがわかります。(下図の通り、Web パーツ内からリスト ID やアイテム ID が取得できます。これらの情報を使って、そのリストやアイテム独自の処理を作成できます。)

なお、上図で、右側のリスト フォームそのものを変更したい場合は、かなりやっかいになります。理由は以下の通りです。

まず、SharePoint 2010 でリスト フォーム内のリストそのもの (上図の右) をカスタマイズするには、通常は、こちら (MSDN) に記載されているように、以下の手順でカスタマイズをおこないます。

  1. コントロール テンプレート (.ascx ファイル) を独自に作成します
    (この際、DataFormWebPart, ListFormWebPart などのコントロールを使用して、XSLT を使った独自のレンダリングをおこなうことができます)
  2. %ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\CONTROLTEMPLATES に、このコントロール テンプレート (.ascx ファイル) を配置します
  3. schema.xml (上記) で Template 属性を使用して、編集フォームで使用するコントロール テンプレートとして上記を指定します

しかし、残念ながら、サンドボックス ソリューション (sandboxed solution) では、%ProgramFiles%\Common Files\Microsoft Shared\web server extensions\14\TEMPLATE\CONTROLTEMPLATES にコントロールテンプレート (.ascx ファイル) を配置することができません。
また、カスタムのフィールドタイプを作成することで、フィールドの表示をカスタマイズできます。(この場合、編集フォームそのものの変更は必要ありません。) しかし、サンドボックス ソリューション (sandboxed solution) では、やはり、このカスタムのフィールドタイプのタイプ情報 (XML ファイル) が配置できないため、フィールドの UI 自体をカスタマイズする方法も不可能です。

しかし、以下の手順で、上記で配置した Web パーツそのもの (左に貼り付けた Web パーツ) だけを使用して、リスト フォームと同じ機能をもった独自なフォームが提供できます。
まず、Schema.xml を編集して、下記太字の通り UseLegacyForm 属性を設定することで、コントロール テンプレートによるリスト フォームのレンダリング (つまり、上図の右の表示) を抑制できます。

<?xml version="1.0" encoding="utf-8"?>
<List xmlns:ows="Microsoft SharePoint" . . .>
    . . .

    <Forms>
      <Form Type="DisplayForm" Url="DispForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
      <Form Type="EditForm" Url="MyEditForm.aspx" WebPartZoneID="Main" UseLegacyForm="TRUE" />
      <Form Type="NewForm" Url="NewForm.aspx" SetupPath="pages\form.aspx" WebPartZoneID="Main" />
    </Forms>
  </MetaData>
</List>

注記 : 通常、この UseLegacyForm 属性は、リストをコントロール テンプレートを使用せず、レガシーな CAML を使った手法でレンダリングする場合に使用します。(上記では CAML が記述されていないため、右側のリストフォームが空になります。)
つまり、通常は、以下の通り、CAML を使用したフォームカスタマイズをおこないます。(なお、SharePoint 2010 で、この CAML を使用したレガシーな記述をおこなうと、リボンが Disable となるため、ファイル添付などの処理もすべて CAML で構築する必要があるので注意してください。結構大変です。。。)

<Form Type="EditForm" Url="MyEditForm.aspx" WebPartZoneID="Main" UseLegacyForm="TRUE">
   <ListFormOpening>
     ここに、Form タグ開始時の HTML レンダリングを記述します
   </ListFormOpening>
 <ListFormButtons>
     ここに、保存、キャンセルなど、コマンドの HTML レンダリングを記述します
   </ListFormButtons>
 <ListFormBody>
     ここに、リストフォームの HTML レンダリングを記述します
   </ListFormBody>
 <ListFormClosing>
     ここに、Form タグ終了時の HTML レンダリングを記述します
   </ListFormClosing>
 </Form>

あとは、上記の Web パーツ (上図の左) を使用して、この中で、リスト アイテムの作成 / 編集 / 表示などの処理をおこなえば OK です。

Step 3 : JavaScript を使った機能連携

サンドボックス ソリューションでは、サーバー リソースの過度な消費や、サーバーを停止させるような危険な処理など、セキュリティ上のさまざまな理由から、サーバー側の処理を制限しています。つまり、クライアント上で実行する処理は制限下に置かれません。
例えば、サンドボックス ソリューションでは、FileUpload コントロールや HtmlInputFile コントロールを使用したファイルのアップロード処理ができませんが (サーバー側で、送られてきたデータを受け取ることができません)、このような場合には、JavaScript を使用して、SharePoint 2010 が標準で提供しているファイル添付用のページ (つまり、既存の機能) を呼び出すと良いでしょう。(ブラウザ上から操作をするのと同等な処理です。)

以下に、サンドボックス ソリューションでファイル添付をおこなう例を具体的に見てみましょう。

まず、下記の太字の通り、上記の MyEditForm.aspx にスクリプトファイルへの参照を追加します。

. . .

<asp:Content ContentPlaceHolderId="PlaceHolderMain" runat="server">
  <SharePoint:ScriptLink runat="server" name="core.js" Defer="true"/>
  <SharePoint:ScriptLink runat="server" name="sp.js" Localizable="false" LoadAfterUI="true" />
  . . .
 

注記 : サンドボックス ソリューションでは、本来、Microsoft.SharePoint.WebControls 名前空間のオブジェクトは使用できません。しかし、上記の通り、モジュールなどで追加された .aspx 上では Microsoft.SharePoint.WebControls 名前空間のオブジェクト (今回の場合、Microsoft.SharePoint.WebControls.ScriptLink) を使用することができます。(ただし、こうしたオブジェクトをサンドボックス ソリューションのプログラム コードから利用することはできません。)

Web パーツのコードを下記 (太字) の通り追記します。
ここでは、ボタンを貼り付けて、このボタンを押すと、SharePoint が標準で持っているファイル添付用のページをダイアログ フレームワークで表示します。

public class WebPart1 : WebPart
{
    private Label label1, label2;
    private Button attachButton;

    protected override void CreateChildControls()
    {
        SPContext context = SPContext.Current;
        label1 = new Label();
        label1.Text = "リスト ID は" + context.ListId;
        this.Controls.Add(label1);
        this.Controls.Add(new LiteralControl("<BR />"));
        label2 = new Label();
        label2.Text = "アイテム ID は" + context.ItemId.ToString();
        this.Controls.Add(label2);
        this.Controls.Add(new LiteralControl("<BR />\n"));
        this.Controls.Add(new LiteralControl("<script language=javascript>\n"));
        this.Controls.Add(new LiteralControl("function GoToAttachFile() {\n"));
        this.Controls.Add(new LiteralControl("  var url=\"" + context.Site.ServerRelativeUrl + "/_layouts/AttachFile.aspx?\"+\"ListId=" + context.ListId.ToString() + "&ItemId=" + context.ItemId.ToString() + "&Source=\"+GetSource();\n"));
        //this.Controls.Add(new LiteralControl("  GoToPage(url);\n"));
        this.Controls.Add(new LiteralControl("  OpenPopUpPage(url, RefreshPage);\n"));
        this.Controls.Add(new LiteralControl("  return false;\n"));
        this.Controls.Add(new LiteralControl("}\n"));
        this.Controls.Add(new LiteralControl("</script>\n"));
        this.Controls.Add(new LiteralControl("<BR />\n"));
        attachButton = new Button();
        attachButton.Text = "File Attach";
        attachButton.Attributes["onclick"] = "javascript:return GoToAttachFile();";
        this.Controls.Add(attachButton);
    }
}

これをサンドボックス ソリューションとして配置して実行すると、下図のように、ファイル添付のダイアログが表示され、アイテムにファイルを添付することができます。

また、ページのリダイレクト (Redirect) などもサンドボックス ソリューションでは許可されていないため、同じく、SharePoint が提供している標準フレームワークを JavaScript から呼び出して終了処理などを実装します。

例えば、OK ボタンを押してダイアログを終了し、(背景の) リスト アイテムの一覧ページ (AllItems.aspx) を更新するには、以下の通り実装します。(キャンセルの場合には、下記で SP.UI.DialogResult.cancel を指定します。)

private Button okButton;

protected override void CreateChildControls()
{
    . . .

    okButton = new Button();
    okButton.Text = "OK";
    okButton.Attributes["onclick"] = "javascript:SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, 'Item updated !');";
    this.Controls.Add(okButton);
}

補足 : なお、登録処理などと同時にフォームを閉じるには、例えば、イベント ハンドラの中で、以下の通り記述すると良いでしょう。

void OKButton_Click(object sender, EventArgs e)
{
 . . .

 this.Controls.Add(new LiteralControl(“<script type=’text/javascript’>n”));
 this.Controls.Add(new LiteralControl(“_spBodyOnLoadFunctionNames.push(‘CloseAndUpdate’);n”));
 this.Controls.Add(new LiteralControl(“function CloseAndUpdate() {n”));
 this.Controls.Add(new LiteralControl(” SP.UI.ModalDialog.commonModalDialogClose(SP.UI.DialogResult.OK, ‘Item updated !’);n”));
 this.Controls.Add(new LiteralControl(“}n”));
 this.Controls.Add(new LiteralControl(“</script>n”));
}

 

まとめ (要件に応じた最適な技術選択) 

ここでは、Web パーツや JavaScript を使ってサンドボックス ソリューションで動く ASP.NET ページの例を紹介しました。
この方法以外にも、JavaScript のクライアント オブジェクト モデル (Client OM) を使用して、SharePoint へのデータの更新処理も含むすべての処理を JavaScript のみで構築することもできます。(大規模な処理で、サーバー側の処理とクライアント側の処理 (JavaScript) が混在して管理がむずかしくなるような場合には、こうした方法も考慮に入れておきましょう。)

また、要件によっては、上述した 1 番目の方法を使用して Silverlight で画面を構築しなければならない場合もあります。
例えば、Microsoft.SharePoint.WebControls 名前空間のコントロールを使用したコードは作成できないため、InputFormTextBox を使用した Rich Text の処理などは作成できません。こうした豊かな表現が必要な場合には、Silverlight が適しています。(実際、SharePoint 2010 では、サイトやリストの作成画面など、いくつかの標準の画面で Silverlight が使用されています。)

上記で見てきたように、サンドボックス ソリューションにおける ASP.NET ページの作成では、サンドボックス ソリューションのさまざまな制約事項の背景 (考え方) を理解して適切な手法を選択する必要があるので、注意してください。

 

Comments (0)

Skip to main content