SDK Example 5 - Using the WorkSession
HotDocs templates may allow a user to complete multiple interviews and assemble multiple documents in a single session. In this example, you will use the HotDocs WorkSession to:
- Repeatedly retrieve interviews
- Complete interviews
- Retrieve multiple assembled documents
Full source code for this example is available at the bottom of the page.
Example Source Code on GitHub
The SdkExample5Worksession example project is available on GitHub, in the HotDocs-Samples repository.
What is a WorkSession?
The WorkSession is a state machine that maintains a queue of Work Items waiting to be assembled. A Work Item represents either:
- An Interview; or
- An Assembled Document
Using the Work Session, you can get information about:
- Completed Work Items
- Pending Work Items
- The Answer Collection used in the current Work Item
Using the Work Session, you can perform the following actions:
- Display interviews for Work Items
- Assemble documents for Work Items
For more information, see the WorkSession article in the HotDocs Open SDK help file.
1. Create a Visual Studio Project for Example 5
Before you start, create a new Console Application project for this example, named SdkExample5Worksession. You will gradually add code to this project until you have a working example. Remember to reference the HotDocs SDK DLLs at the beginning of the class.
2. Create a new WorkSession
Create a new method, CreateWorkSession, to return a new Work Session object:
private static WorkSession CreateWorkSession()
{
}
To create the session, you need a Service object and a Template object. You can retrieve these using the CreateHotDocsService and CreateTemplate methods created in previous examples:
var service = CreateHotDocsService();
var
template = CreateTemplate();
Using the newly-created Service and Template, create a new WorkSession:
var session = new WorkSession(service, template);
The WorkSession can now be returned for use elsewhere in the class. The final method looks like this:
private static WorkSession CreateWorkSession()
{
var service = CreateHotDocsService();
var template = CreateTemplate();
var session = new WorkSession(service,
template);
return session;
}
3. Create the AssembleDocuments method
Next, you will add a new method that will create a WorkSession and use it to output assembled documents. First, create a new method, AssembleDocuments. The first line in this method is a call to the HotDocs SDK Utility method SetPersistentEncryptionKey. This sets the key for encrypting WorkSession data.
private static void AssembleDocuments()
{
Util.SetPersistentEncryptionKey("ExampleKey");
}
Add the CreateWorkSession method created in the step above to create the WorkSession:
private static void AssembleDocuments()
{
var session = CreateWorkSession();
}
In the next step, you will expand this method, using the Work Session to access Work Items for processing.
4. Process the Work Items
Next, you will expand AssembleDocuments to process the current work item and output an assembled documents. This takes several steps, outlined below.
4.1 Check for Work Items to Process
First, add a new While loop to AssembleDocuments with a !session.IsCompleted condition:
while(!session.IsCompleted)
{
}
This condition checks to see if all the Work Items in the current session have been processed (i.e. all WorkItems have IsCompleted property set to true and the CurrentWorkItem is null). Only while there are still Work Items in the session should you attempt to process them.
4.2 Retrieve the Current Work Item from the Session
After creating the Work Session, you must select a Work Item to process. As the Work Session is effectively a queue of Work Items, you need to select the Work Item next in line to be assembled. To retrieve this, access the CurrentWorkItem property of the Work Session object:
var currentWorkItem =
session.CurrentWorkItem;
The currentWorkItem can then be used to retrieve an interview and assemble documents.
4.3 Process the Interviews for the Work Item
Inside the while loop, you now handle the interviews for the Work Item. A Work Item may contain multiple interviews. In HotDocs a single template can be used to assemble multiple other templates, each with their own interview. To handle this, the application must be able to process multiple interviews.
First, check that the current work item is the correct type of Work Item to process. As mention above, a Work Item can either be a Interview Work Item or an Assembled Document Work Item. At this stage, you are only interested in Interview Work Items. To check that browser interviews are processed only, you add the following check for the InterviewWorkItem type:
if (currentWorkItem is InterviewWorkItem)
{
}
Within this condition, you can retrieve the interview HTML fragment from the session using the GetCurrentInterview method:
var interviewHtmlFragment
= session.GetCurrentInterview();
At this stage, the interviewHtmlFragment should be passed to a View and displayed to the user.
Usually, when using a Work Session, answers would come from users filling out an interview, then posting back the answers when the interview is complete. For simplicity, retrieve the answers using the GetAnswers method from previous examples:
var answers = GetAnswers();
Now, use the Session FinishInterview method with the answers to mark the current interview as completed and update the AnswerCollection available in the WorkSession:
session.FinishInterview(answers);
4.4 Assemble the Documents for the Work Item
Once the Interview is complete the documents can assembled, using the WorkSession AssembleDocuments method:
var docs = session.AssembleDocuments("logref");
AssembleDocuments produces a collection of completed documents. Once the documents have been assembled, you can iterate through them and perform any additional processing required. In Example 1, this additional processing was saving the file to disk. Alternatively, it could be saving the file to a database.
foreach(var doc in docs)
{
//Perform
additional processing for each assembled document
}
4.5 Completed AssembleDocuments Method
Once all the steps above are complete, the final AssembleDocuments method looks like this:
private static void AssembleDocuments()
{
var
session = CreateWorkSession();
while(!session.IsCompleted)
{
var
currentWorkItem = session.CurrentWorkItem;
if(currentWorkItem
is InterviewWorkItem)
{
var
interviewHtmlFragment = session.GetCurrentInterview();
//Show
interview to user, receive postback containing answers
var
answers = GetAnswers(); session.FinishInterview(answers);
}
var
docs = session.AssembleDocuments("logref");
foreach(var
doc in docs)
{
//Perform
additional processing for each assembled document
}
}
}
Test
To test the WorkSession:
- Set the current project as the Startup Project (Right-click the SdkExample5Worksession project, select Startup Project from the drop-down menu).
- Set three breakpoints in Visual Studio:
- On var currentWorkItem = session.CurrentWorkItem in the AssembleDocuments method.
- On foreach(var docs in docs) in the AssembleDocuments method.
- Press F5 to run the project. The var currentWorkItem breakpoint is hit.
- Hover the mouse over the var session variable. This appears several lines above the current breakpoint. Not that the WorkSession contains two WorkItems. One is the InterviewWorkItem and one is the DocumentWorkItem.
- Hover the mouse over the session.CurrentWorkItem. The current work item is an InterviewWorkItem.
- Click Continue. The foreach breakpoint is hit.
- Hover the mouse over the docs collection in the foreach condition. One DOCX document has been assembled. At this stage, the session is completed, as there are no more interviews to process, and the document can be processed (for example, saved to disk).
Example Source Code (C#)
using System;
using
System.Collections.Generic;
using
System.IO;
using
HotDocs.Sdk;
using
HotDocs.Sdk.Server;
using
HotDocs.Sdk.Server.Local;
namespace SdkExample5Worksession
{
///
<summary>
///
This shows how to use a worksession to repeatedly retrieve interviews,
complete them, and then retrieve the assembled documents
///
</summary>
internal
class SdkExample5Worksession
{
private
static void Main(string[] args)
{
AssembleDocuments();
}
private
static void AssembleDocuments()
{
Util.SetPersistentEncryptionKey("ExampleKey");
var
session = CreateWorkSession();
while
(!session.IsCompleted)
{
var
currentWorkItem = session.CurrentWorkItem;
if
(currentWorkItem is InterviewWorkItem)
{
var
interviewHtmlFragment = session.GetCurrentInterview();
//Show
interview to user, receive postback containing answers
var
answers = GetAnswers();
session.FinishInterview(answers);
}
var
docs = session.AssembleDocuments("logref");
foreach
(var doc in docs)
{
//Process
each document as needed. For example, save document to disk, as in Example
2.
}
}
}
private
static WorkSession CreateWorkSession()
{
var
service = CreateHotDocsService();
var
template = CreateTemplate();
var
session = new WorkSession(service, template);
return
session;
}
private
static Services CreateHotDocsService()
{
const
string tempDirectoryPath = @"C:\temp\";
var
service = new Services(tempDirectoryPath);
return
service;
}
private
static StringReader GetAnswers()
{
var
answerCollection = CreateAnswerCollection();
var
answerCollectionXml = answerCollection.XmlAnswers;
return
new StringReader(answerCollectionXml);
}
private
static AnswerCollection CreateAnswerCollection()
{
var
answerCollection = new AnswerCollection();
//Text
answers
var
answer = answerCollection.CreateAnswer<TextValue>("TextExample-t");
answer.SetValue<TextValue>("World");
//Number
answers
var
numberAnswer = answerCollection.CreateAnswer<NumberValue>("NumberExample-n");
numberAnswer.SetValue<NumberValue>(123);
//Date
answers
var
dateAnswer = answerCollection.CreateAnswer<DateValue>("DateExample-d");
dateAnswer.SetValue<DateValue>(DateTime.Now);
//True/False
answers
var
trueFalseAnswer = answerCollection.CreateAnswer<TrueFalseValue>("TrueFalseExample-tf");
trueFalseAnswer.SetValue<TrueFalseValue>(true);
//Multiple
choice answers
var
mcAnswer = answerCollection.CreateAnswer<MultipleChoiceValue>("MultipleChoiceExample-mc");
var
multipleChoices = new List<string> { "Apple", "Orange"
};
mcAnswer.SetValue(new
MultipleChoiceValue(multipleChoices.ToArray()));
//Repeat
answers
var
repeatAnswer = answerCollection.CreateAnswer<TextValue>("NameRepeatExample-t");
repeatAnswer.SetValue<TextValue>("Steve",
0);
repeatAnswer.SetValue<TextValue>("Carol",
1);
repeatAnswer.SetValue<TextValue>("John",
2);
return
answerCollection;
}
private
static Template CreateTemplate()
{
const
string packagePath = "HelloWorld.hdpkg";
string
packageId = Guid.NewGuid().ToString();
var
templateLocation = new PackagePathTemplateLocation(packageId, packagePath);
var
template = new Template(templateLocation);
return
template;
}
}
}