Welcome to MSDN Blogs Sign in | Join | Help

Visual Studio で Office SharePoint Server 2007 Workflow を作成するチュートリアル (第2回: コード実装編) 【Beta2版】

環境:Office SharePoint Server 2007 Beta 2

(Beta2TR版については ここ を参照)

こんにちは。

では、早速、前回 (第1回) の続きから開発していきましょう。

【ステップ:ワークフロープロパティの設定】

第1回で保存したワークフローの Visual Studio のプロジェクトを起動してください。
ワークフローのデザイナーを表示し、以下の手順で、第1回で配置したアクティビティにプロパティを設定していきます。

  • [CreateTask1] の [TaskId] プロパティに taskId という変数を新規設定します。設定方法は、プロパティウィンドウを表示し、該当のプロパティ値の入力欄の [...] ボタンをクリックし、表示される画面で、[Bind to a new menber] タブを選択し、プロパティ名を記入して [Create Field] にチェックを付けて [OK] ボタンを押します。
    この手順で作成することによって、変数定義などのコードも自動生成 (コードジェネレート) してくれます。
  • さらに、上記と同じ方法で、[CreateTask1] の [TaskProperties] プロパティに taskProps という変数を新規設定してください。
  • つぎに、[CreateTask1] の [CorrelationToken] プロパティに taskToken という変数を新規設定してください。[Correlation Token] に「taskToken」と入力し、[OwnerActivityName] に「Workflow1」と入力します。
  • つぎに、[onTaskChanged1] の [CorrelationToken] プロパティとして、リストから taskToken (先程作成した変数) を選択してください。
  • 同様に、[onTaskChanged1] の [TaskId] プロパティとして taskId を選択してください。
  • 同様に、[completeTask1] の [CorrelationToken] プロパティとして taskToken を選択してください。
  • 同様に、[completeTask1] の [TaskId] プロパティとして taskId を選択してください。
  • つぎに、タスク更新時の更新前のタスク情報と更新後のタスク情報を入れておく変数 (タスクプロパティという型の変数) を作成するため、まず、タスクの開始時と終了時のタスクプロパティを入れておくプロパティバッグを作成するため、上記で新規設定したときと同じ手順で、[onTaskChanged1] の [AfterProperties] プロパティ、[BeforeProperties] プロパティに、変数名 afterProps、beforeProps を設定してください。
  • さいごに、[logHistoryListActivity1] の [EventId] プロパティとして [WorkflowCompleted] をリストから選択し、[HistoryDescription] プロパティに上述と同様の方法で変数名 historyDesc の変数を新規設定してください。
    これらはタスクの終了処理で使います。

(誤って taskToken, taskId などが複数作成された場合は、workflow1.Designer.cs のコードを直接編集して修正してください。)

【ステップ:ハンドラコードの実装】

つぎに、以下の手順で、ASP.NET 上にホストされた InfoPath フォームのデータとワークフローを連携するコードを記載していきましょう。

SharePoint のワークフローでは、WorkflowProperties というプロパティバッグが渡され、ここにワークフローを起動したアイテムの情報などなど SharePoint 固有のワークフローに関する情報が入っています。そこでこの属性情報を抽出して処理するため、ワークフローのデザイナー上で、配置した onWorkflowActivated1 アクティビティのプロパティウィンドウに表示されている [Invoked] のハンドラーに onWorkflowActivated という名前を入力して Enter キーを押し、ハンドラーのコードを作成していきます。
が、、、このコードを記入する前に、2 つ準備しておくことがあります。

まず1 つは、上記で作成したフォームのデータをこのワークフローのプロジェクト内でデシリアライズ (逆シリアライズ) する必要があるため、準備として、第1回で作成した Initiation Form を InfoPath でデザインモードで開いて、メニュー [File] - [Save As Source Files] を選択して xsd ファイルを出力してください。(myschema.xsd というファイルが作成されます。)
プロセスがファイルを握ってしまうため、一旦、InfoPath を閉じて (作成したフォームは保存してください)、Visual Studio Command Prompt を起動して、以下のコマンドを実行してください。プロキシ用の cs ファイル (ソースコード) が作成されます。

xsd.exe myschema.xsd /c

上記で作成した cs のソースファイルをワークフローのプロジェクト (Visual Studio のプロジェクト) に取り込んでください。

もう 1 つの準備は、InfoPath から抽出した値をワークフローで憶えておくため、作成された workflow1 クラスに以下の変数を宣言しておきます。

        public string assignee = default(string);
        public string instructions = default(string);

では、先程作成した onWorkflowActivated ハンドラーに以下のコードを記載してください。

        private void onWorkflowActivated(object sender, ExternalDataEventArgs e)
        {
            // desiriarize xml to the instance
            workflowId = workflowProperties.WorkflowId;
            XmlSerializer serializer = new XmlSerializer(typeof(InitForm));
            XmlTextReader reader = new XmlTextReader(new System.IO.StringReader(workflowProperties.InitiationData));
            InitForm initform = (InitForm)serializer.Deserialize(reader);

            // set value
            assignee = initform.asignee;
            instructions = initform.instructions;
        }

この処理をみておわかり頂けるように、Initiation Form では、InfoPath で出力される XML のデータがプロパティバッグの InitiationData にテキストのまま入っていますので、このようにデシリアライズをおこなって中身を取り出しています。

つぎに、createTask1 の MethodInvoking ハンドラーとして以下のコードを記載した createTask という名称のハンドラーを作成します。(ハンドラコードの作成方法は上述と同様です。)

        private void createTask(object sender, EventArgs e)
        {
            taskId = Guid.NewGuid();
            taskProps.TaskType = 0;
            taskProps.AssignedTo = assignee;
            taskProps.Title = "Please review this";
            taskProps.Description = instructions;
            taskProps.ExtendedProperties["instructions"] = instructions;
        }

この処理について補足しておきます。
さきほど、ワークフロープロパティというプロパティバッグについてご説明しましたが、SharePoint のタスクにおいても、同様に、タスクに関する情報がタスクプロパティというプロパティバッグに設定されます。Title や AssignedTo などのような SharePoint で事前定義されているプロパティは上記のように取得・設定できますが、第1回で InfoPath フォームの中で指定した instructions のようなカスタムのプロパティは、上述のコードのように、ExtendedProperties という名前付き配列に設定されます。先ほどの Initiation Form のように、XML のソースそのものをデシリアライズする必要はなく、第1回のようにフォームを作成しておくことでワークフローが InfoPath のフォームのアイテムを自動的に ExtendedProperties に設定してくれます。ここは、ワークフロープロパティで使う Initiation Form や Association Form とは勝手が違いますので注意してください。

つぎに、タスク onTaskChanged1 のハンドラを以下の通り記述していきましょう。ここでは、第1回にシナリオとしてご説明した通り、InfoPath のフォームで、タスクの実行者が [isFinishied] のチェックボックスをチェックした場合のみワークフローを完了し、それ以外は、再度ループして同じ処理を実施するように実装します。

まず、完了(Finish)したか否かを判断する変数を作成するため、以下の変数を workflow1 クラスに定義してください。

private bool isFinished = false;

つぎに、onTaskChanged1 の Invoked ハンドラーとして以下のコードを記載した onTaskChanged という名称のハンドラーを上述と同様の方法で作成します。

        private void onTaskChanged(object sender, ExternalDataEventArgs e)
        {
            isFinished = bool.Parse(afterProps.ExtendedProperties["isFinished"].ToString());
        }

つぎに、以下の手順で、While アクティビティの条件を設定していきましょう。
ワークフローのデザイナー (workflow1.cs [Design]) で whileActivity1 を選択してプロパティウィンドウを表示し、[Condition] として [Code Condition] を選択します。[Condition] プロパティの階層を展開して、[Condition] の中に関数名として notFinished と入力して Enter を入力してください。(Condition の定義関数のコードが自動作成され、コードが表示されます。)
ここに、以下の通りコードを記載します。

        private void notFinished(object sender, ConditionalEventArgs e)
        {
            e.Result = !isFinished;
        }

さいごに、以下の手順で、タスクの終了処理を記述していきましょう。
CompleteTask1 の MethodInvoking ハンドラーとして、以下の completeTask という名称の関数をハンドラーを作成します。

        private void completeTask(object sender, EventArgs e)
        {
            historyDesc = "Workflow completed by " + assignee;
        }

今回はここまでで終了です。
この段階でも、まだワークフローと InfoPath フォームは個別に開発された状態でお互いに関係付けされていないことにお気づきでしょう。相互の関係付けは、次回の「配置」でご説明します。

ここまでで、一旦、F5 でビルドをしてみましょう。(エラーなくビルドがおこなわれるはずです。)

第1回 デザイン編

第3回 配置・インストール編
第4回 動作の確認とデバッグ編

※ 次回の掲載は月曜の予定です、、、

 

Published Friday, August 25, 2006 10:33 AM by tsmatsuz
Filed under: ,

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

No Comments

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker