Using the Office Requirements Authoring Starter Kit (Part 2 of 2)

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Microsoft Corporation

May 2006

Applies to: Microsoft Visual Studio 2005 Tools for the Microsoft Office System, Microsoft Visual Studio 2005 Team System, Microsoft Visual Studio 2005 Team Foundation Server, Microsoft SQL Server 2005, Microsoft Windows SharePoint Services, Microsoft Office Word 2003

Summary: See code examples that show how the Requirements Authoring Starter Kit (RASK) can help software development teams collect, interpret, distribute, and synchronize project requirements in a structured Word document using Microsoft Visual Studio 2005 Tools for the Microsoft Office System. (36 printed pages)

Download RASK.msi.

Contents

  • Overview

  • Code Examples for RASK Features

  • Establishing Requirement Dependencies

  • Code Examples for RASK Features Using T-SQL

  • Installing and Setting Up the RASK Solution

  • Detailed Instructions for Installing and Setting Up the RASK Solution

  • Troubleshooting RASK

  • Conclusion

  • Additional Resources

Overview

Using the Office Requirements Authoring Starter Kit (Part 1 of 2) defines the problem that the Requirements Authoring Starter Kit (RASK) solves, and describes the RASK software requirements and architecture. After describing each RASK feature, Part 1 also reviews installation and setup.

This article, Using the Requirements Authoring Starter Kit (Part 2 of 2), introduces the code that enables each RASK feature. You can use this information as a starting place for exploring the code in more detail or for planning extensions to RASK.

The following list shows the contents of the two Solutions that RASK provides:

The RequirementAuthoringStarterKitMaster Solution

  • **RequirementAuthoring   **Implements the task pane user interface (UI) that appears in the Microsoft Office Word 2003 documents. This project was specifically created as a Microsoft Visual Studio 2005 Tools for the Microsoft Office System (Visual Studio 2005 Tools for Office) project type. It references several Microsoft Office namespaces. The UI is defined in the RequirementsAuthoringPane namespace. The event handler code is specific to Word and is stored in the Word document template file RequirementsAuthoring.dot.

  • **RequirementAuthoringBL   **Implements the RASK business layer, which is code that implements the functionality exposed in the UI. The primary class it defines is the RequirementTemplateManager class, which in turn has methods for each feature. Additionally, OutlookManager implements an interface to Microsoft Office Outlook through that application's object model.

  • **RequirementAuthoringSupport   **Implements various helper classes for RASK.

The RequirementAuthoringStarterKitSupport Solution

  • **RequirementAuthoringStarterKitDAL   **Implements a data access layer to interact with the Microsoft SQL Server data store using the Web service exposed by Microsoft SQL Server. RequirementAuthoringStarterKitDAL contains a Requirement class to represent a single requirement and a ProjectRequirement class to represent the entire set of requirements in a project. Saving to and loading from the database is handled by the RMProject, RMRequirement, and RMRequirementDepedency classes, all of which derive from a common RMBase class.

  • **RequirementAuthoringTeamFoundation   **Implements a data access layer to interact with Microsoft Visual Studio Team Foundation Server.

  • **RequirementAuthoringSupport   **Implements various helper classes for RASK.

Code Examples for RASK Features

The following code examples introduce each RASK feature described in Part 1 of this article. From these examples, you can explore the details of the code on your own.

Creating Projects

To create a project in RASK, you must select an established Visual Studio Team Foundation Server project from a list in the task pane. RASK then prepares the document accordingly. In the code example, we examine how the list is populated, and what happens when a users selects an item.

This list is populated by the InitializeProjects method of the RequirementsAuthoringPane class. This instantiates a RequirementsTemplateManager from the RequirementsAuthoringBL project. It also calls its GetTeamFoundationProjects method. This creates an instance of ProjectManager from the RequirementAuthoringTeamFoundation project. It also calls its GetProjects method. The GetProjects method performs the work to interface with Visual Studio Team Foundation Server to get the project list.

When the list is populated, the toolStripMenuItemCreateTemplate_Click event handler implements the Actions button in the UI. This calls OnCreateTemplate, which in turn calls the taskPane_OnCreate template, located in RequirementsAuthoring.dot. This calls DisplayProject, which stores the project name, ID, and other information from the task pane in the document. To do so, DisplayProject uses an XML Schema that is bound to the Word document. The following code example shows how RASK establishes a reference to the appropriate node, and then populates it from the task pane.

Word.XMLNode nodeProjectName =
   rootNode.ChildNodes.Add(
   SchemaNode.ProjectName.ToString(),
   (string)_namespaceURI,
   ref range);

   nodeProjectName.Range.Text = taskPane.ProjectName;

Adding Requirements

To add requirements, you create appropriate nodes in the document's XML structure that map to new areas in the document. Because the process for adding requirements is similar for all requirement types, we develop one example, the Scenario type, for you to follow.

From the UI, toolStripMenuItemAddScenario handles the event and calls OnAddScenario. This leads to the taskPane_OnAddScenario event handler in RequirementsAuthoring.dot. This calls AddTopLevelRequirement, which creates a new, globally unique identifier (GUID) to act as the requirement ID. AddTopLevelRequirement uses Word bookmarks to locate the end of the requirements section in the document. It then calls the AddRequirement method. Because the AddRequirement method is overloaded into several versions, it can add requirements, such as different types and child levels.

The AddRequirement method first determines what level of requirement you are adding by determining the level of the XML node in the document:

if (rootNode.BaseName ==
    SchemaNode.Project.ToString())
{
    style = "Heading 1";
    detailStyle = "Normal 1";
    typeStyle = "Type 1";
}
else if (rootNode.ParentNode.BaseName ==
    SchemaNode.Project.ToString())
{
    style = "Heading 2";
    detailStyle = "Normal 2";
    typeStyle = "Type 2";
    isTop = false;
}
else if (rootNode.ParentNode.ParentNode.BaseName ==
    SchemaNode.Project.ToString())
{
    style = "Heading 3";
    detailStyle = "Normal 3";
    typeStyle = "Type 3";
    isTop = false;
}
else
{
    MessageBox.Show("Unable to create child requirement. " + 
        "Requirements are limited up to 3 levels only.");
    return;
}

Although this code arbitrarily sets a limit of three levels, you can extend that to any number of levels.

To extend the number of levels

  1. Modify the above code to add blocks for additional levels by adding an additional ParentNode reference in the if condition for each new level.

  2. Change the value of the _requirementLevels constant in the file DocumentConstants.cs under the RequirementsAuthoring\DocumentSupport folder.

  3. Add Heading x, Normal x, and Type x styles to the Word document template, where x is the number indicating the new level.

The following code example then adds XML nodes for the new requirement.

Word.XMLNode nodeRequirement =
rootNode.ChildNodes.Add(
SchemaNode.Requirement.ToString(),
(string)_namespaceURI,
ref range); 

Then this example subsequently inserts a table into the document body for the new requirement.

Word.Table tableRequirement =
Tables.Add(
nodeRequirement.Range,
3, 1,
ref _missingValue,
ref _missingValue);

The requirement is a bookmark in Word:

start = nodeRequirement.Range.Start - 1;
end = nodeRequirement.Range.End + 1;
range = Range(ref start, ref end);
Bookmarks.Add(generatedID, ref range);

Finally, the requirement is added to the tree view in the task pane:

taskPane.AddTreeViewItem(
parentRequirementID,

   (requirementName.Trim()!=String.Empty)?requirementName:"<Unspecified>",
requirementID,
typeID,
Convert.ToBoolean(needsReview.ToString().ToLower()), 
unsavedRequirement, 
teamFoundationWorkItemID);

Saving Requirements to SQL Server

The SaveToSQLServer2005 method in RequirementsAuthoringPane implements saving requirements. RASK relies heavily on RMRequirement and RMProject objects from the RequirementAuthoringStarterKitDAL project to perform the save operation.

To save information to the database, RASK gets information from the Word document's XML Schema and calls the appropriate objects in the data access layer. Although RASK saves the project level, requirement level, and dependency information in separate operations, the operations are similar. Therefore, we develop one example, the project level, for you to follow.

First, iterate through the XML nodes in the document:

foreach (Word.XMLNode node in Globals.ThisDocument.XMLNodes)
{

Find the one containing project information:

if (node.BaseName == SchemaNode.Project.ToString())
{

Instantiate an RMProject object, and then call its Insert method to save to the database:

try
{
RMProject project = new RMProject();
project.Insert(
_projectID,
_projectName,
Environment.UserName,
ref created,
_teamFoundationProjectID);

The Insert method relies on the native XML Web services feature of Microsoft SQL Server to communicate with the database. Most of the code to communicate with the database is automatically generated by Microsoft Visual Studio, within the RequirementAuthoringStarterKitDAL project, when the Web reference is added to the project. For more information about how this feature works, see the documentation for Visual Studio or Microsoft SQL Server.

The loop continues to identify nodes containing requirements and performs similar tasks to save them.

Synchronizing Requirements with Visual Studio Team Foundation Server

The SyncRequirementstoTeamFoundation method in RequirementsAuthoringPane implements synchronizing requirements. RASK relies on a RequirementTemplateManager object from the RequirementAuthoringBL project to synchronize requirements.

As the SyncRequirementstoTeamFoundation method iterates through the XML nodes in the document looking for requirements, it does so recursively to get to all nodes and child nodes in the tree. The following code performs the synchronization for each requirement.

RequirementTemplateManager bll = new RequirementTemplateManager(
   Config.GetTeamFoundationConnectionString());

if (teamFoundationWorkID > 0)
{
   bll.UpdateTeamFoundationRequirement(teamFoundationWorkID,
      _projectName,
      requirementName,
      String.Empty);

Generating a Consolidated Requirements Document

This feature works exactly like creating a new project: It uses DisplayProject to populate the document with project-level information. In addition, it calls DisplayRequirements to fill the document with requirements from the data store. Because the path from the UI to this code is straight-forward, we focus on DisplayRequirements, which is in RequirementsAuthoring.dot.

First, it calls on the GetRequirements method of the task pane:

string content = taskPane.GetRequirements(taskPane.ProjectID);

This method uses a RMRequirement object from the RequirementAuthoringStarterKitDAL project to get the requirement from the database:

RMRequirement requirement = new RMRequirement();
retVal = requirement.SelectXMLByProjectID(projectID);

Next, the code interprets the results as an XML stream and iterates on a node-by-node basis:

TextReader tr = new StringReader(content);
if (content != "<Requirements />" &&
    content != String.Empty)
{
   taskPane.IsTreeNodeClick = true;
   XPathDocument xpathDoc = new XPathDocument(tr);
   XPathNavigator xpathNav = xpathDoc.CreateNavigator();
   XPathNodeIterator nodes =
      xpathNav.Select(
      "/*[local-name()='Requirements']/*[local-name()='Requirement']");
   if (nodes != null)
   {
      while (nodes.MoveNext())
      {

Code (not shown) reads the information from the nodes, and then calls AddRequirement to insert the requirement text into the document:

AddRequirement(
range,
Convert.ToInt32(nodeRequirementTypeID),
new Guid(nodeRequirementID),
requirementName,
requirementDetail,
needsReview,
Guid.Empty,
false,
Convert.ToInt32(nodeTeamFoundationWorkItemID));

For more information about AddRequirement, see Adding Requirements in this article.

Reusing Requirement Content

To allow you to reuse requirement content, RASK implements search. Search occurs at the database level, rather than in the text of the document. The Search method of the RequirementsAuthoringPane instantiates a RequirementTemplateManager from the RequirementAuthoringStartKitDAL project. The Search method then calls its SearchRequirement method to perform the search and return the results as a DataSet object, as shown in this example:

RequirementTemplateManager bll = new RequirementTemplateManager(
   Config.GetTeamFoundationConnectionString());
DataSet ds = bll.SearchRequirement(textBoxKeyword.Text, nameOnly);

The full-text indexing of XML data feature of Microsoft SQL Server makes the search possible.

SearchRequirement calls either SelectByRequirementName or SelectByRequirementNameRequirementDetail, depending on which option the user selected. The DataSet is then rendered into a list box in the UI, with the help of a Requirement List Item object from the RequirementAuthoringSupport project.

foreach (DataRow row in ds.Tables[0].Rows)
{
item = new RequirementListItem(
   row["RequirementName"].ToString(),
   row["RequirementID"].ToString(),
   WorkItemType)Convert.ToInt32(row["RequirementTypeID"]));
listBoxRequirements.Items.Add(item);
}

Establishing Requirement Dependencies

RASK implements dependencies with the help of the RequirementDependency class in the RequirementAuthoringSupport project. A dependency consists of a pair of RequirementID GUIDS.

The AddDependency method of the RequirementAuthoringPane controls the process that the user initiates. The AddDependency method gets the requirement IDs from the two tree views in the UI, and then instantiates a pair of RequirementDependency objects to define both directions of the relationship:

RequirementDependency newDependency = new RequirementDependency(
   requirementTagItem.RequirementID,
   dependencyTagItem.RequirementID);

RequirementDependency newOppositDependency = new RequirementDependency(
   dependencyTagItem.RequirementID,
   requirementTagItem.RequirementID);

After error checking to ensure that no requirement is linked to itself, RASK adds the dependencies to a collection that each requirement maintains using its Dependencies property.

requirementTagItem.Dependencies.Add(newDependency);
dependencyNode.StateImageIndex = (int)NodeIcon.Dependency;
requirementNode.Tag = requirementTagItem;

if (nodes.Length > 0)
{
   RequirementNodeItem tempItem =
      (RequirementNodeItem)nodes[0].Tag;
   tempItem.Dependencies.Add(newOppositDependency);
   nodes[0].Tag = tempItem;
}

Flagging Requirements Needing Review

With requirement dependencies established, RASK can automatically notify users of requirements that need review when a related requirement changes. To do this, RASK looks for changes to requirements since the last time you generated a consolidated requirements document. If RASK finds changes, it flags related requirements in the Project Summary tree view with an icon (see Figure 13 in Using the Office Requirements Authoring Starter Kit (Part 1 of 2)).

Sending Outlook Task Requests

The OutlookManager class in the RequirementAuthoringBL project implements sending Microsoft Office Outlook task requests. Specifically, the CreateTaskRequest method uses the Outlook object model to create a task and assign it accordingly.

TaskItem taskItem = (TaskItem)_outlook.CreateItem(
      OlItemType.olTaskItem);
   try
   {
      taskItem.Assign();
      Recipient recipient = taskItem.Recipients.Add(
         toEmail);
      recipient.Resolve();

Using the Resolve method is necessary to validate the e-mail address.

The code continues by filling out the properties of the task, then calls the Save method, to save the request into the user's task list, and the Send method, to send the request to the recipient:

taskItem.Save();
if (displayForm)
      {
         taskItem.Display(true);
      }
         else
      {
         taskItem.Send();
      }

Code Examples for RASK Features Using T-SQL

Transaction-SQL (T-SQL) is an extended form of SQL that adds declared variables, transaction control, error and exception handling, and row processing to SQL's existing functions. The following sections provide code examples for RASK that use T-SQL.

Retrieving Projects from the RASK Data Store Using T-SQL

When you use T-SQL to retrieve a project from the RASK data store, it passes it from Microsoft SQL Server to RASK assemblies as XML. Although the XML format is self-documenting, in brief, it consists of a root-level <Project> element, which can contain up to three levels of nested <Requirement> elements. The following code example shows the XML retrieved from Microsoft SQL Server:

<Project ProjectID="" TeamFoundationProjectID=""> 
   <ProjectName> 
   </ProjectName> 
   <Requirements> 
      <Requirement RequirementID="" TeamFoundationWorkItemID=
         "" RequirementTypeID="" NeedsReview="" Ordinal=""> 
      <RequirementName> 
      </RequirementName> 
      <RequirementDetail> 
      </RequirementDetail> 
      <Requirement RequirementID="" TeamFoundationWorkItemID=
         "" RequirementTypeID="" NeedsReview="" Ordinal=""> 
      <RequirementName> 
      </RequirementName> 
      <RequirementDetail> 
      </RequirementDetail> 
      <Requirement RequirementID="" TeamFoundationWorkItemID=
         "" RequirementTypeID="" NeedsReview="" Ordinal=""> 
      <RequirementName> 
      </RequirementName> 
      <RequirementDetail> 
      </RequirementDetail> 
      </Requirement> 
      </Requirement> 
   </Requirement> 
   </Requirements> 
</Project> 

The following code example shows the prototype for the stored procedure that RASK uses to retrieve a specific RASK project. RASK creates a GUID named @ProjectID to uniquely identify a project within the database.

CREATE PROC [ProjectSelectXMLByProjectID]
   @ProjectID UNIQUEIDENTIFIER

RASK uses T-SQL's FOR XML PATH to retrieve the XML for a project and format it according to the previously specified XML representation. The following pseudo code shows the general layout of the T-SQL code. RASK uses each FOR XML PATH to specify a level of XML element nesting.

SELECT 
   SELECT 
      SELECT 
         SELECT 
            FROM [RequirementMaster] AS RL3
            WHERE 
         FROM [RequirementMaster] AS RL2
      AS XML)
   FROM [RequirementMaster] AS RL1
   FOR XML PATH('Requirement')
FROM [ProjectMaster] AS P
FOR XML PATH ('Project')

The following example shows the entire T-SQL code for the ProjectSelectXMLByProjectID stored procedure call.

CREATE PROC [ProjectSelectXMLByProjectID]
   @ProjectID UNIQUEIDENTIFIER

AS

SELECT 
   [ProjectID] AS "@ProjectID",
   [TeamFoundationProjectID] AS "@TeamFoundationProjectID",
   [ProjectName],
   CAST(
   (
   SELECT 
      [RequirementID] AS "@RequirementID",
      [TeamFoundationWorkItemID] AS "@TeamFoundationWorkItemID",
      [RequirementTypeID] AS "@RequirementTypeID",
      [NeedsReview] AS "@NeedsReview",
      [Ordinal] AS "@Ordinal",
      [RequirementName],
      CAST(RequirementDetail AS XML),
      CAST(
      (
         SELECT 
         [RequirementID] AS "@RequirementID",
         [TeamFoundationWorkItemID] AS "@TeamFoundationWorkItemID",
         [RequirementTypeID] AS "@RequirementTypeID",
         [NeedsReview] AS "@NeedsReview",
         [Ordinal] AS "@Ordinal",
         [RequirementName],
         CAST(RequirementDetail AS XML),
         CAST(
         (
            SELECT 
            [RequirementID] AS "@RequirementID",
            [TeamFoundationWorkItemID] AS "@TeamFoundationWorkItemID",
            [RequirementTypeID] AS "@RequirementTypeID",
            [NeedsReview] AS "@NeedsReview",
            [Ordinal] AS "@Ordinal",
            [RequirementName],
            CAST(RequirementDetail AS XML)
            FROM [RequirementMaster] AS RL3
            WHERE 
               (RL3.[ProjectID] = P.[ProjectID]) AND
               (RL3.[ParentRequirementID] = RL2.[RequirementID])
            FOR XML PATH('Requirement')
            )
         AS XML)
         FROM [RequirementMaster] AS RL2
         WHERE 
            (RL2.[ProjectID] = P.[ProjectID]) AND
            (RL2.ParentRequirementID = RL1.[RequirementID])
         FOR XML PATH('Requirement')
         )
      AS XML)
   FROM [RequirementMaster] AS RL1
   WHERE 
      (RL1.[ProjectID] = P.[ProjectID]) AND
      (RL1.ParentRequirementID = dbo.RequirementRootParentID())
   FOR XML PATH('Requirement')
   )
AS XML)
FROM [ProjectMaster] AS P
WHERE
   ([ProjectID] = @ProjectID)
ORDER BY [ProjectName]
FOR XML PATH ('Project')

Retrieving Dependencies for a Requirement Using T-SQL

The following code example shows the stored procedure that RASK uses to retrieve dependencies for a requirement. The procedure uses FOR XML PATH. In a dependency, one requirement is linked to another. RASK uses RequirementSelectXMLByRequirementIDDependency to retrieve the dependent requirements for a specific requirement. The following example shows the self-documenting XML format used to retrieve dependencies for a specific requirement.

<Requirements> 
   <Requirement RequirementID="" TeamFoundationWorkItemID=
      "" RequirementTypeID="" 
   NeedsReview="" Ordinal=""> 
   <RequirementName> 
   </RequirementName> 
   <RequirementDetail> 
   </RequirementDetail> 
   </Requirement> 
</Requirements> 

The RequirementSelectXMLByRequirementIDDependency stored procedure is an inner and an outer FOR XML PATH. The following code shows the entire stored procedure.

CREATE PROC [RequirementSelectXMLByRequirementIDDependency]
   @RequirementID UNIQUEIDENTIFIER

AS 

SELECT CAST(
(
   SELECT 
   [RequirementID] AS "@RequirementID",
   [TeamFoundationWorkItemID] AS "@TeamFoundationWorkItemID",
   [RequirementTypeID] AS "@RequirementTypeID",
   [NeedsReview] AS "@NeedsReview",
   [Ordinal] AS "@Ordinal",
   [RequirementName],
   CAST([RequirementDetail] AS XML)
   FROM [RequirementMaster]
   WHERE 
   ([RequirementID] IN (
      SELECT RequirementIDDestination
      FROM RequirementDependency
      WHERE (RequirementIDSource = @RequirementID))
   )
   ORDER BY [ProjectID], [ParentRequirementID], [Ordinal]
   FOR XML PATH('Requirement')
)
AS XML)
FOR XML PATH('Requirements')

Updating Requirements to Be Reviewed Using T-SQL

When requirements must be reviewed, RASK updates the XML and an OPENXML. The following code shows the XML used to update requirements in conjunction with the RequirementModifiedUpdate stored procedure.

<ModifiedRequirements> 
   <Items> 
   <ModifiedRequirement RequirementID="" /> 
   </Items> 
</ModifiedRequirements> 

The RequirementModifiedUpdate stored procedure uses OPENXML, as shown in the following process and examples:

  1. RequirementModifiedUpdate passes in XML using a stored procedure parameter of type XML:

    CREATE PROCEDURE [dbo].[RequirementModifiedUpdate]
       @XmlDocument XML
    
  2. RequirementModifiedUpdate uses the OPENXML statement, in conjunction with a document handle of type integer that is associated with an XML document, using the sp_xml_preparedocument stored procedure:

    DECLARE @docHandle INT
    
    EXEC sp_xml_preparedocument @docHandle OUTPUT, @XmlDocument
    
  3. OPENXML uses the previously set up document handle.

    RASK uses the OPENXML statement for the RequirementModifiedUpdate stored procedure to populate a temporary table with the requirements to update:

    CREATE TABLE #TempRequirementDependency
    (
       RequirementID UNIQUEIDENTIFIER
    )
    
    INSERT #TempRequirementDependency
    SELECT * 
    FROM OPENXML(@docHandle, N'//ModifiedRequirement')
    WITH #TempRequirementDependency
    
  4. When OPENXML processes the document, it closes the handle using the sp_xml_removedocument stored procedure:

    EXEC sp_xml_removedocument @docHandle 
    
  5. Finally, the RequirementModifiedUpdate stored procedure updates the requirements using an UPDATE statement, and then cleans up the temporary table:

    UPDATE [Requirement]
    SET [NeedsReview] = 1
    WHERE 
       [RequirementID] IN
       (
          SELECT [RequirementIDDestination]
          FROM [RequirementDependency] AS RD
          INNER JOIN #TempRequirementDependency AS TD
          ON (RD.[RequirementIDSource] = TD.[RequirementID])
       )
    
    DROP TABLE #TempRequirementDependency
    

The following code shows the entire RequirementModifiedUpdate stored procedure.

CREATE PROCEDURE [dbo].[RequirementModifiedUpdate]
   @XmlDocument XML

DECLARE @docHandle INT

CREATE TABLE #TempRequirementDependency
(
   RequirementID UNIQUEIDENTIFIER
)

EXEC sp_xml_preparedocument @docHandle OUTPUT, @XmlDocument

INSERT #TempRequirementDependency
SELECT * 
FROM OPENXML(@docHandle, N'//ModifiedRequirement')
WITH #TempRequirementDependency

EXEC sp_xml_removedocument @docHandle 

UPDATE [Requirement]
SET [NeedsReview] = 1
WHERE 
   [RequirementID] IN
   (
   SELECT [RequirementIDDestination]
   FROM [RequirementDependency] AS RD
   INNER JOIN #TempRequirementDependency AS TD
      ON (RD.[RequirementIDSource] = TD.[RequirementID])
   )

DROP TABLE #TempRequirementDependency

Updating and Deleting Requirements Using T-SQL

You update and delete requirements using OPENXML in conjunction with the RequirementModifiedDelete stored procedure. The following code shows the XML used by this stored procedure.

<ModifiedRequirements> 
   <Items> 
   <ModifiedRequirement RequirementID="" /> 
   </Items> 
</ModifiedRequirements> 

The RequirementModifiedDelete stored procedure uses OPENXML, as shown in the following process and examples:

  1. RequirementModifiedUpdate passes in XML using a stored procedure parameter of type XML:

    CREATE PROCEDURE [dbo].[RequirementModifiedDelete]
       @XmlDocument XML
    
  2. RequirementModifiedUpdate uses the OPENXML statement, in conjunction with a document handle of type integer that is associated with an XML document, using the sp_xml_preparedocument stored procedure:

    DECLARE @docHandle INT
    
    EXEC sp_xml_preparedocument @docHandle OUTPUT, @XmlDocument
    
  3. OPENXML uses the previously set up document handle.

    RASK uses the OPENXML statement for the RequirementModifiedDelete stored procedure to populate a temporary table with the requirements to update and delete:

    CREATE TABLE #TempRequirement
    (
       RequirementID UNIQUEIDENTIFIER
    )
    
    INSERT #TempRequirement
    SELECT * 
    FROM OPENXML(@docHandle, N'//ModifiedRequirement')
    WITH #TempRequirementDependency
    
    EXEC sp_xml_removedocument @docHandle 
    
  4. When OPENXML processes the document, it closes the handle using the sp_xml_removedocument stored procedure:

    EXEC sp_xml_removedocument @docHandle 
    
  5. After RASK stores the data in the **@TempRequirement** temporary table, it can place the data into its hierarchical form using another temporary table, #ParentChildRequirement, and a series of SELECT statements that are integrated with UNION statements:

    CREATE TABLE #ParentChildRequirement
    (
       RequirementID UNIQUEIDENTIFIER,
       ParentRequirementID UNIQUEIDENTIFIER,
       Level INT
    )
    
    INSERT #ParentChildRequirement
    SELECT 
       RL3.[RequirementID], 
       RL3.[ParentRequirementID],
       3 AS Level
    FROM [Requirement] AS RL1
       INNER JOIN #TempRequirement AS TR
          ON
          (RL1.[RequirementID] = TR.[RequirementID])
          INNER JOIN RequirementDependency AS RD
          ON 
          (RL1.[RequirementID] = RD.[RequirementIDDestination])
       INNER JOIN [Requirement] AS RL2
          ON 
          RL2.[ParentRequirementID] = RL1.[RequirementID])
       INNER JOIN [Requirement] AS RL3
          ON 
          (RL3.[ParentRequirementID] = RL2.[RequirementID])
    
    UNION
    
    SELECT 
       RL2.[RequirementID],
       RL2.[ParentRequirementID],
       2 AS Level
    FROM [Requirement] AS RL1
       INNER JOIN #TempRequirement AS TR
          ON 
          (RL1.[RequirementID] = TR.[RequirementID])
       INNER JOIN RequirementDependency AS RD
          ON 
          (RL1.[RequirementID] = RD.[RequirementIDDestination])
       INNER JOIN [Requirement] AS RL2
          ON 
          (RL2.[ParentRequirementID] = RL1.[RequirementID])
    
    UNION ALL
    
    SELECT 
       RL1.[RequirementID],
       RL1.[ParentRequirementID],
       1 AS Level
    FROM [Requirement] AS RL1
       INNER JOIN #TempRequirement AS TR
          ON 
           (RL1.[RequirementID] = TR.[RequirementID])
       INNER JOIN RequirementDependency AS RD
          ON 
          (RL1.[RequirementID] = RD.[RequirementIDDestination])
    
  6. The stored procedure is ready to handle update and delete operations.

    Because UPDATE and DELETE are separate statements, we create a transaction and use the new SQL Server 2005 TRY/CATCH block:

    BEGIN TRY
       BEGIN TRANSACTION
    
  7. Updating requirements is simply an update generated from the temporary table created to contain the hierarchy of requirements:

    UPDATE [Requirement]
    SET [NeedsReview] = 1
    FROM [Requirement] AS R
       INNER JOIN #ParentChildRequirement AS PR
          ON
          (R.[RequirementID] = PR.[RequirementID])
    
  8. RASK performs delete operations at the lowest level of requirements, followed by the middle layer of requirements, and then the top level of requirements; this sequencing avoids issues with dependencies between levels:

    DELETE [Requirement]
    FROM [Requirement] AS R
       INNER JOIN #ParentChildRequirement AS PR
          ON
          (R.[RequirementID] = PR.[RequirementID])
       WHERE PR.[Level] = 3
    
    DELETE [Requirement]
    FROM [Requirement] AS R
       INNER JOIN #ParentChildRequirement AS PR
       ON
       (R.[RequirementID] = PR.[RequirementID])
       WHERE PR.[Level] = 2
    
    DELETE [Requirement]
    FROM [Requirement] AS R
       INNER JOIN #ParentChildRequirement AS PR
       ON
          (R.[RequirementID] = PR.[RequirementID])
       WHERE PR.[Level] = 1
    
  9. Once RASK processes the UPDATE and DELETE statements, it drops the temporary tables:

    DROP TABLE #TempRequirement
    DROP TABLE #ParentChildRequirement
    
  10. The CATCH clause of the TRY/CATCH statement is used to detect an error and rollback the transaction used to wrap the update and delete statements:

    END TRY
    
    BEGIN CATCH
       DECLARE @ErrorMessage NVARCHAR(400)
       DECLARE @ErrorSeverity INT
       DECLARE @ErrorState INT
    
       SELECT @ErrorMessage = ERROR_MESSAGE()
       SELECT @ErrorSeverity = ERROR_SEVERITY()
       SELECT   @ErrorState = ERROR_STATE()
       IF @ErrorState = 0
          BEGIN
             SET @ErrorState = 1
          END
    
       IF (XACT_STATE()) != 0
          BEGIN
             ROLLBACK TRANSACTION
          END
    
       RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState )
    
       RETURN
    END CATCH
    
  11. After the CATCH clause is processed, the stored procedure can commit the update and delete actions:

    COMMIT TRANSACTION
    

Each level of the document requires new nesting of SELECT calls. With some restructuring of the data, you can use Common Table Expressions (CTE) or an APPLY statement in Microsoft SQL Server. Although you can make the code generic, this adds a layer of complexity to the logic. A CTE makes handling hierarchies elegant, but it applies only to a single statement. Using temporary tables allows RASK to use T-SQL to handle and apply hierarchies to four T-SQL statements: one UPDATE statement and three DELETE statements.

The following code shows the entire RequirementModifiedDelete stored procedure:

CREATE PROCEDURE [dbo].[RequirementModifiedDelete]
   @XmlDocument XML

AS

DECLARE @docHandle INT

EXEC sp_xml_preparedocument @docHandle OUTPUT, @XmlDocument

CREATE TABLE #TempRequirement
(
   RequirementID UNIQUEIDENTIFIER
)

CREATE TABLE #ParentChildRequirement
(
   RequirementID UNIQUEIDENTIFIER,
   ParentRequirementID UNIQUEIDENTIFIER,
   Level INT
)

INSERT #TempRequirement
SELECT * 
FROM OPENXML(@docHandle, N'//ModifiedRequirement')
WITH #TempRequirementDependency

EXEC sp_xml_removedocument @docHandle 

INSERT #ParentChildRequirement
SELECT 
   RL3.[RequirementID], 
   RL3.[ParentRequirementID],
   3 AS Level
FROM [Requirement] AS RL1
   INNER JOIN #TempRequirement AS TR
      ON 
      (RL1.[RequirementID] = TR.[RequirementID])
   INNER JOIN RequirementDependency AS RD
      ON 
      (RL1.[RequirementID] = RD.[RequirementIDDestination])
   INNER JOIN [Requirement] AS RL2
      ON 
      (RL2.[ParentRequirementID] = RL1.[RequirementID])
   INNER JOIN [Requirement] AS RL3
      ON 
      (RL3.[ParentRequirementID] = RL2.[RequirementID])

UNION

SELECT 
   RL2.[RequirementID],
   RL2.[ParentRequirementID],
   2 AS Level
FROM [Requirement] AS RL1
   INNER JOIN #TempRequirement AS TR
      ON 
      (RL1.[RequirementID] = TR.[RequirementID])
   INNER JOIN RequirementDependency AS RD
      ON 
      (RL1.[RequirementID] = RD.[RequirementIDDestination])
   INNER JOIN [Requirement] AS RL2
      ON 
      (RL2.[ParentRequirementID] = RL1.[RequirementID])

UNION ALL

SELECT 
   RL1.[RequirementID],
   RL1.[ParentRequirementID],
   1 AS Level
FROM [Requirement] AS RL1
   INNER JOIN #TempRequirement AS TR
      ON 
      (RL1.[RequirementID] = TR.[RequirementID])
   INNER JOIN RequirementDependency AS RD
      ON 
      (RL1.[RequirementID] = RD.[RequirementIDDestination])

BEGIN TRY
   BEGIN TRANSACTION

   UPDATE [Requirement]
   SET [NeedsReview] = 1
   FROM [Requirement] AS R
      INNER JOIN #ParentChildRequirement AS PR
      ON
      (R.[RequirementID] = PR.[RequirementID])

DELETE [Requirement]
FROM [Requirement] AS R
   INNER JOIN #ParentChildRequirement AS PR
      ON
      (R.[RequirementID] = PR.[RequirementID])
   WHERE PR.[Level] = 3

   DELETE [Requirement]
   FROM [Requirement] AS R
      INNER JOIN #ParentChildRequirement AS PR
      ON
      (R.[RequirementID] = PR.[RequirementID])
   WHERE PR.[Level] = 2

   DELETE [Requirement]
   FROM [Requirement] AS R
    INNER JOIN #ParentChildRequirement AS PR
      ON
      (R.[RequirementID] = PR.[RequirementID])
   WHERE PR.[Level] = 1

   DROP TABLE #TempRequirement
   DROP TABLE #ParentChildRequirement
END TRY

BEGIN CATCH
   DECLARE @ErrorMessage NVARCHAR(400)
   DECLARE @ErrorSeverity INT
   DECLARE @ErrorState INT

   SELECT @ErrorMessage = ERROR_MESSAGE()
   SELECT @ErrorSeverity = ERROR_SEVERITY()
   SELECT @ErrorState = ERROR_STATE()
   IF @ErrorState = 0
   BEGIN
      SET @ErrorState = 1
   END

   IF (XACT_STATE()) != 0
   BEGIN
      ROLLBACK TRANSACTION
   END

   RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState )

   RETURN
END CATCH

COMMIT TRANSACTION

GO

IF EXISTS( 
   SELECT * 
   FROM DBO.SYSOBJECTS 
   WHERE ID = OBJECT_ID(N'[DBO].[RequirementDependencyDelete]') AND  
      OBJECTPROPERTY(ID, N'IsProcedure') = 1) 
DROP PROCEDURE [DBO].[RequirementDependencyDelete]

GO

CREATE PROC [RequirementDependencyDelete]
   @RequirementIDSource UNIQUEIDENTIFIER,
   @RequirementIDDestination UNIQUEIDENTIFIER

AS

DELETE FROM [RequirementDependency]
WHERE
   (([RequirementIDSource] = @RequirementIDSource) AND
   ([RequirementIDDestination] = @RequirementIDDestination)) OR
   (([RequirementIDSource] = @RequirementIDDestination) AND
   ([RequirementIDDestination] = @RequirementIDSource))

Exposing Stored Procedures as Web Services Using T-SQL

RASK uses the new CREATE ENDPOINT statement in SQL Server 2005 to expose stored procedures as Web services. RASK uses the WEBMETHOD argument to specify each stored procedure exposed as a Web method. The following code shows a portion of the T-SQL code used to define the Web service:

CREATE ENDPOINT RequirementsAuthoring
STATE = STARTED
AS HTTP (
   SITE = '*', 
   PATH = '/sql/RequirementsAuthoring', 
   AUTHENTICATION = (INTEGRATED),
   PORTS=(CLEAR)   
)   
FOR SOAP (
   WEBMETHOD 'ProjectSelectAll' 
   (
   name='RequirementsAuthoring.dbo.ProjectSelectAll', 
   schema=STANDARD
   ),

-- Remainder of Web service exposed stored procedures list here

   WSDL = DEFAULT,
   DATABASE = 'RequirementsAuthoring',
   BATCHES=ENABLED,
   NAMESPACE = 'http://tempui.org/'
)

Installing and Setting Up the RASK Solution

The following sections provide details about how to install and set up the RASK solution.

Software Requirements (Prerequisites)

  • Microsoft Office 2003 with Service Pack (SP) 2. Note that, at a minimum, you must install Microsoft Office Word 2003 and Microsoft Office Outlook 2003.

  • Microsoft SQL Server 2005. Note that this solution has not been tested with Microsoft SQL Server 2005 SP 1.

  • Microsoft Windows SharePoint Services 2.0 SP 2.

  • Microsoft Visual Studio Team Foundation Server. Follow instructions in Visual Studio Team Foundation Server installation guide available on MSDN.

  • Microsoft Visual Studio Team Edition. Note that Microsoft Visual Studio Tools for the Microsoft Office System is included with Visual Studio Team Edition.

  • Microsoft Visual Studio Team Explorer. Note that this must be installed from the Visual Studio Team Foundation Server media in addition to Visual Studio Team Edition.

Quick Start: Installing and Setting Up the RASK Solution

You can follow these brief instructions to get started quickly, or see Detailed Instructions for Installing RASK Source Code for more information.

To install the source code for the RASK Solution

  1. Install all code to a folder.

    For example, by default, this solution is installed to \User Data Folder\Visual Studio 2005\Projects\VST02005RASK.

  2. Optional step: Run TFSrefs.bat (This adds the Team Foundation DLLs to the Visual Studio list of References on the .NET tab, when you add References to projects.)

  3. At the Visual Studio command prompt, run Createdb.bat to create the database.

    Note

    You may need to modify the paths in Createdb.bat and register.bat to reflect your installation paths.

  4. Open the RequirementAuthoringStarterKitSupport solution.

  5. Open the Web Reference in the DAL project, and then refresh it.

    Be sure the subfolder is not read-only.

  6. Set the solution to Release mode.

  7. Build the solution.

  8. At the Visual Studio command prompt, run Register.bat to register the DAL and TFS assemblies.

    Note

    You may need to modify the paths in Createdb.bat and register.bat to reflect your installation paths.

  9. Close the solution.

  10. Open the RequirementAuthoringStarterKitMaster solution.

To set up Team Explorer in Visual Studio Team Foundation Server

  1. If necessary, connect to Visual Studio Team Foundation Server from the Tools menu.

  2. Create a Team Project.

  3. Edit Workitem.bat to use the name of the Team Project that you just created, and then run it at the Visual Studio command prompt.

  4. Set the solution to Debug mode.

  5. Run the solution.

    OR

    Publish the RequirementAuthoring project.

    For example, publish the project to \User Data Folder\Visual Studio 2005\Projects\VST02005RASK\PUBLISH.

  6. In the RequirementAuthoring_1.0.0.X subfolder of the Publish folder, create a shortcut to the RequirementAuthoring.dot file.

Detailed Instructions for Installing and Setting Up the RASK Solution

For instructions without installation details, see Quick Start: Installing and Setting Up RASK Solutions.

To install the RequirementAuthoringStarterKitSupport Solution

  1. Setup the RequirementsAuthoring database. For more information, see Database Setup.

  2. In the RequirementAuthoringStarterKitDAL project, refresh the Web Reference.

  3. Build and register the RequirementAuthoringStarterKitDAL assembly.

  4. Build and register the RequirementAuthoringTeamFoundation assembly.

  5. On the Build menu, click Build Solution to build the RequirementAuthoringStarterKitSupport solution.

You must recompile and reregister the RequirementAuthoringStarterKitDAL and RequirementAuthoringTeamFoundation projects for your changes to take effect in RASK.

Database Setup

  1. Open SQL Management Studio and log on.

  2. Drop/Delete RequirementsManager Database

  3. Open the following files in order and execute.

    1. RequirementsAuthoringDB.sql: this creates the RequirementsAuthoring database including its user defined data types, tables, indexes and constraints.

    2. RequirementsAuthoringCode.sql: this creates the stored procedures, triggers and user define functions.

    3. RequirementsAuthoringSeed.sql: creates the data used in the database (requirement types, root level projects and root level requirements)

Using SQL Command Line Utility, SqlCmd

  1. On the Start menu, click Run.

  2. Type "cmd" and click OK. This brings up a console window.

  3. Type the following command syntax in the console window:

    Syntax

    sqlcmd -E -S "Server" -I -i "InputSQLScriptFile"
    

    Example

    sqlcmd -E -S "SOFTAGON-VPC001" -I -i "RequirementsAuthoringDB.sql"
    
  4. Execute the following scripts in order.

    1. RequirementsAuthoringDB.sql

    2. RequirementsAuthoringCode.sql

    3. RequirementsAuthoringSeed.sql

To install the RequirementAuthoringStarterKitMaster Solution

  1. Open the RequirementAuthoringStarterKitMaster solution

    If Visual Studio prompts you to enable Microsoft Visual Basic for Applications (VBA), click OK.

  2. In Solution Explorer, select RequirementAuthoring, and then open the App.config file for editing:

    1. Set the TeamFoundataionConnectionString key to the connection string used to access the Visual Studio Team Foundation Server:

      <add key="TeamFoundationConnectionString" value="http://localhost:8080/"/>
      
    2. Set the WordXSDPath key to the full path of the .xsd file:

      RequirementAuthoringStarterKit\RequirementAuthoring\Requirements.xsd

      For example:

      <add key="WordXSDPath"
         value=
         "C:\RequirementAuthoringStarterKit\RequirementAuthoring\Requirements.xsd"/>
      
  3. Build the RequirementAuthoringStarterKitMaster solution.

  4. Verify that you have access to the Visual Studio Team Foundation Server and that Visual Studio Team Foundation Server has at least one project.

  5. To set the RequirementAuthoring project as the startup project, right-click the RequirementAuthoring project in Solution Explorer, and then, on the Contact menu, click Set as Startup Project .

  6. Create a project to use with RASK, and then import a custom work item into the project.

  7. In Visual Studio, press F5 to run RASK.

  8. Install the custom Requirement work item.

    For more information, see To import a custom work item into a Visual Studio Team Foundation Server project, in this article.

  9. To run RASK without running Visual Studio, click the Publish command for the RequirementAuthoring project, and then run the .dot file from the subfolder in the Publish folder.

  10. To set up Management Studio in Microsoft SQL Server, open Management Studio, and then log in.

  11. Drop/Delete the RequirementsManager database.

  12. Open these files, in the order shown:

    1. RequirementsAuthoringDB.sql

      This file creates the RequirementsAuthoring database including its user-defined data types, tables, indexes, and constraints.

    2. RequirementsAuthoringCode.sql

      This file creates the stored procedures, triggers, and user-defined functions.

    3. RequirementsAuthoringSeed.sql

      This file creates the data used in the database: requirement types, root-level projects, and root-level requirements.

  13. Click Execute.

To use the Microsoft SQL Server command-line utility (SqlCmd)

  1. On the taskbar, click Start, and then click Run.

  2. Type cmd, and then click OK.

  3. In the Command Prompt window, type the following syntax:

    Syntax

    sqlcmd -E -S "Server" -I -i "InputSQLScriptFile"
    

    Example

    sqlcmd -E -S "SOFTAGON-VPC001" -I -i "RequirementsAuthoringDB.sql"
    
  4. Execute the following scripts, in the order shown:

    1. RequirementsAuthoringDB.sql

    2. RequirementsAuthoringCode.sql

    3. RequirementsAuthoringSeed.sql

To compile and register RequirementAuthoringStarterKitDAL

  1. Open the RequirementAuthoringStarterKitSupport solution.

  2. Set the compilation mode to Release mode.

  3. In Solution Explorer, expand the RequirementAuthoringStarterKitDAL project folder and the Web References folder.

  4. Right-click RequirementsAuthoringWebservice, and then click Update Web Reference to refresh the RequirementsAuthoringWebservice Web reference.

  5. At the Visual Studio command prompt, run Register.bat.

    Note

    To locate the command prompt, click Start, and then click All Programs. In the list of programs, click Microsoft Visual Studio 2005, click Visual Studio Tools, and then click Visual Studio 2005 Command Prompt.

    Running the batch file Register.bat, which is in the Release folder, registers the RequirementAuthoringStarterKitDAL.dll assembly, which places the assembly in the global assembly cache (GAC), as shown in this example:

    RequirementAuthoringStarterKit\
       dev\
          RequirementAuthoringStarterKit\
          RequirementAuthoringStarterKitDAL\
             bin\
             Release
    

    For information about manually registering or unregistering the assembly in GAC, see To register and unregister assemblies in the Global Assembly Cache, in this article.

    Note

    Although RASK does not place the unregister task in the project's pre-build event or the register task in the post-build event, we encourage you to do so. To provide adequate code access security when Word interacts with Web Services, specifically T-SQL stored procedures and Team Foundation Services, these assemblies were placed in the GAC in RASK. For best practices and other approaches to VSTO deployment, see the following: Deploying Visual Studio 2005 Tools for Office Solutions Using Windows Installer (Part 1 of 2) Deploying Visual Studio 2005 Tools for Office Solutions Using Windows Installer: Walkthroughs (Part 2 of 2) VSTO Blogger: Misha Shneerson

To compile and register the RequirementAuthoringTeamFoundation project

  1. Open the RequirementAuthoringStarterKitSupport solution.

  2. Set the compilation mode to Release mode.

  3. Compile the RequirementAuthoringTeamFoundation project.

  4. At the Visual Studio command prompt, run Register.bat.

    Register.bat is in the Release folder. Running this batch file registers the RequirementAuthoringTeamFoundation.dll assembly, which places the assembly in the GAC, as shown in this example:

    RequirementAuthoringStarterKit\
       dev\
       RequirementAuthoringStarterKit\
          RequirementAuthoringTeamFoundation\
             bin\
    Release
    
  5. Compile RequirementAuthoringTeamFoundation Solution.

  6. Reregister the RequirementAuthoringTeamFoundation assembly to update the GAC version of the assembly.

    To register it, you can use Register.bat.

    For information about manually registering or unregistering the assembly in the GAC, see To register and unregister assemblies in the Global Assembly Cache, in this article.

    Note

    Developers are encouraged to place the unregister task in a project's pre-build event and the register task in the post-build event. This step was not performed in this authoring toolkit because build events tend to go unnoticed and developers need to recognize that in order to get around security issues related to Word talking to Web services (stored procedures and Team Foundation Services) certain assemblies must be placed in the GAC.

#To create a Visual Studio Team Foundation Server project

  1. Display Team Explorer in Visual Studio (on the View menu, click Team Explorer).

  2. If the Team Explorer window does not display a tree of Server/Servers (root nodes) and team services projects (child nodes) then, on the Tools menu, click Connect to Team Foundation Server and connect to the Visual Studio Team Foundation Server to be used with RASK.

  3. Right-click the Visual Studio Team Foundation Server in the Team Explorer window, and then select New Team Project.

  4. Create a project named Testing123, and then click Next. Click Next. Click Next. Click Finish.

#To import a custom work item into a Visual Studio Team Foundation Server project

  1. At the Visual Studio command prompt, locate the directory containing the Requirement.xml file, as shown in this example:

    RequirementAuthoringStarterKit\WorkItem
    
  2. Type the following command syntax:

    witimport /f "template filename" /t "Team Foundation Server" /p "project name"
    

    Example

    witimport /f "Requirement.xml" /t "http://localhost:8080" /p "Testing123" 
    

    Note

    RASK uses the custom work item. Each time a project is created, the custom work item must be imported.

To register and unregister assemblies in the Global Assembly Cache

The Global Assembly Cache (GAC) tool, Gacutil.exe, allows you to view and manipulate the contents of the GAC and download cache. Although Shfusion.dll provides similar functionality in the Microsoft .NET Framework, you can use Gacutil.exe from build scripts, makefile files, and batch files. Gacutil.exe is located here: C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin.

To register or unregister an assembly in GAC

  1. On the taskbar in the Visual Studio command prompt, click Start, click All Programs, and then click Microsoft Visual Studio 2005.

  2. Click Visual Studio Tools, and then click Visual Studio 2005 Command Prompt.

  3. From the folder where the assembly to be registered or unregistered is located:

    • To unregister an assembly, type the following syntax, and then press ENTER:

      gacutil /u Assembly name
      

      For example:

      gacutil /u RequirementAuthoringTeamFoundation
      
    • To register an assembly, type the following syntax, and then press ENTER:

      gacutil /i Assembly name
      

      For example:

      gacutil /i RequirementAuthoringTeamFoundation.dll
      

      Note

      The path to Gacutil.exe is C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin.

To register assemblies in the .NET Project Reference List

If you cannot find an assembly that you successfully registered in GAC on the .NET Reference tab of the Add Reference window, follow the steps below to locate the assembly:

  1. On the taskbar, click Start, and then click Run.

  2. Type regedit, and then click OK.

  3. Navigate to this path in the registry:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\AssemblyFolders
    
  4. Right-click AssemblyFolders, click New, and then click Key.

  5. Give the key the same name as the assembly, for example, RequirementAuthoringStarterKitDAL.

  6. In the dialog box, double click the (Default) name, and then type the path to the assembly, for example:

    C:\installdirectory\RASK\GAC\DAL.
    
  7. Close the Registry Editor.

To publish the Requirement Authoring Document Template

Before publishing the template, be sure that the RequirementAuthoring project builds successfully.

  1. Right-click the RequirementAuthoring project, and then click Properties.

  2. In the Properties dialog box, click Publish.

  3. Type the path where you want to publish the project, and then click Publish.

  4. After you publish the document template, configure RequirementAuthoring.dll.config for the appropriate Team Foundation connection string and XSD path.

Troubleshooting RASK

The following list describes common problems using RASK and suggests ways to solve them:

  • Parameter not optional

    Exception from HRESULT: 0x8002000F (DISP_E_PARAMNOTOPTIONAL)

    1. On the Word Tools menu, click Templates and Add-ins, then select the XML Schema tab.

    2. Remove the entire XML schema, except ActionsPane.

    3. Run RASK.

  • Operation Timed Out

    This error occurs with CTP of Microsoft SQL Server before September 2005.

    1. Start, and then stop, the SQL Server Service.

    2. Double-click the SQL Server icon on the taskbar.

    3. From the Services drop-down list box, select SQL Server.

    4. Click Stop.

    5. After the SQL Server Service stops, click Start.

    6. Attempt to start and stop SQL Server Service again.

  • Configuring Code Access Security

    1. Go to Admin Tools, and then run Microsoft .NET Framework 2.0 Configuration.

    2. InWindows Explorer,click My Computer , Runtime Security Policy, User, Code Groups, All Codes, and then click RASK.

    3. Right-click RASK, and then select the properties that you want.

    4. On the Membership tab, verify that URL Condition Type is selected and that the path leads to the RASK folder where you extracted the file, for example:

      C:\Office Samples\VSTO2005RASK\*).
      
    5. Select the Permission Set tab, and then select full trust.

  • Code Access Security in Windows SharePoint Services

    "The customization does not have the required permissions to execute. . ."

    1. Go to Admin Tools and run the .NET Framework Configuration.

    2. In Windows Explorer, click My Computer, Runtime Security Policy, Machine, Code Groups, and then click All Codes.

    3. Right-click All Codes, and then click New.

    4. Type the name and description

    5. Go to the Membership tab, be sure that URL Condition Type is selected, and that the URL points to the document on the SharePoint site, for example, http://myserver/*.

    6. Select the Permission Set tab, and then select full trust.

    7. Click OK.

      You might need to wait a few minutes for Windows to refresh the security settings.

  • Error in sending a task request

    Verify that Outlook is running and configured correctly.

Conclusion

The RASK solution illustrates one way that you can integrate Microsoft products to create a custom solution.

Using the Office Requirements Authoring Starter Kit (Part 1 of 2) defines the problem that the Requirements Authoring Starter Kit (RASK) solves, and describes the RASK software requirements and architecture.

Additional Resources