Built-in steps

From Sense/Net Wiki
Jump to: navigation, search
  •  
  •  
  •  
  •  
  • 100%
  • 6.3.1
  • Enterprise
  • Community
  • Planned

Overview

Sense/Net ECMS evolves constantly and we release new versions of the product from time to time. To make the upgrade easier we offer upgrade packages and patches for Enterprise customers. Community customers can take advantage of this packaging framework also to create their own upgrade packages. This article lists all the available built-in steps that are shipped with the product and can be used to build a package. In the examples below we list all available properties but do not show all possible combinations (for default property, element, attribute, mixed models); we try to demonstrate the most optimal approach for the steps.

Basic steps

Assign

  • Full name: SenseNet.Packaging.Steps.Assign
  • Default property: Value
  • Additional properties: Name

Assigns a phase variable with the given string value. Use this step to declare or modify a phase wide variable that can be used in other steps (not every step can use a phase variable). The Name must start with a @. The declared variable can be seen for the consecutive steps in the whole phase. A variable declared this way cannot be deleted or hidden in any way.

This step can be placed in ForEach steps' Block sections.

Example:

...
  <Steps>
	<Assign Name="@path">Admin\Rename4\contents\features1.Content</Assign>
	<Assign Name="@newName">features.Content</Assign>
	<Rename Source="@path" SourceIsRelativeTo="TargetDirectory">@newName</Rename>
  </Steps>
...

Copy

  • Full name: SenseNet.Packaging.Steps.Copy
  • Default property: Source
  • Additional properties: NewName, SourceIsRelativeTo, TargetDirectory

Copies files, usually from the package to the web folder. Use this step to update or add new libraries or other files to the web folder. If the given target parent directory structure does not exist in the file system, this step creates them.

This step can be placed in ForEach steps' Block sections.

The valid values for SourceIsRelativeTo are the following:

  • Package: the source path is relative to the package root folder (default)
  • TargetDirectory: the source path is relative to the web site root folder (this is the mandatory value if the step is put into a ForEach step)

Delete

  • Full name: SenseNet.Packaging.Steps.Delete
  • Default property: Path
  • Additional properties: -

Deletes a file/directory from the file system or the Content Repository, depending on the given path. Path is relative to the package's target directory or an absolute repository path.

This step can be placed in ForEach steps' Block sections.

  <Delete>App_Data\MyFolder</Delete>
  ... or ...
  <Delete>/Root/MyFolder</Delete>

If the given path is a Content Repository path, please make sure that a StartRepository step (see below) is placed into the manifest before this one to make sure that the Content Repository is started and accessible.

ExecuteDatabaseScript

  • Full name: SenseNet.Packaging.Steps.ExecuteDatabaseScript
  • Default property: Query
  • Additional properties: ConnectionName, InitialCatalog

Executes a database script on the Content Repository database. The Query property is two-faced:

  • Can be a path of the file in the package that contains a valid database script.
  <ExecuteDatabaseScript query="dbscripts\longest-tables.sql" />
  • Can contain a valid database script.
  <ExecuteDatabaseScript>
    <![CDATA[
      SELECT TOP 5
        t.NAME AS TableName, SUM(a.total_pages) * 8 AS TotalSpaceKB
      FROM sys.tables t
        INNER JOIN sys.indexes i ON t.OBJECT_ID = i.object_id
        INNER JOIN sys.partitions p ON i.object_id = p.OBJECT_ID AND i.index_id = p.index_id
        INNER JOIN sys.allocation_units a ON p.partition_id = a.container_id
      WHERE
        t.NAME NOT LIKE 'dt%'
          AND t.is_ms_shipped = 0
          AND i.OBJECT_ID > 255
      GROUP BY
        t.Name, p.Rows
      ORDER BY
        TotalSpaceKB desc
    ]]>
  </ExecuteDatabaseScript>

The result of this step depends on the query result. If it contains a table, a very simply formatted table will be displayed. The result of the query above is something like this (five largest tables in the database in descendant order):

================================================== #0/1 ExecuteDatabaseScript
TableName       TotalSpaceKB
LogEntries      36176
Versions        27832
TextPropertiesNText     4328
JournalItems    1488
BinaryProperties        1344
Script is successfully executed.
-------------------------------------------------------------

The scalar result will be displayed too. The step:

  <ExecuteDatabaseScript>
    SELECT COUNT(1) FROM Nodes
  </ExecuteDatabaseScript>

The result:

================================================== #0/1 ExecuteDatabaseScript
 
1689
Script is successfully executed.
-------------------------------------------------------------

In any other cases (e.g. update / delete / mode change) the step does not write back extra information but the "Script is successfully executed." will be shown.

If the script contains XML characters ( '<', '>', '&' etc.), do not escape the individual characters but place the whole query into a CDATA section.

Export

from version 6.5.5

  • Full name: SenseNet.Packaging.Steps.Export
  • Default property: Source
  • Additional properties: Target, Filter

Extracts contents from the given Source repository path, filtered by the given Filter content query into the given Target path.

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

Either Source or Filter are mandatory arguments. If you omit Source it defaults to /Root and the Filter content query will be executed globally. If you omit Filter, the step extracts every content dwells in the repository tree pointed by Source into the target folder. Target is mandatory and its value is a file system path that must be writable for the user running the package. This path can be absolute or relative. If it is relative, the step will replenish it by the path of the App_Data folder. If the final path points to a not existing folder, it will be created.

This step can be placed in ForEach steps' Block sections.

Example 1:

...
<Steps>
    ...
    <StartRepository/>
    <Export Target="export_target" >/Root/Sites/Default_Site/Cars</Export>
...

Example 2:

...
<Steps>
    ...
    <StartRepository/>
    <Assign Name="@filter">+InFolder:/Root/Sites/Default_Site/Cars +Type:Car .REVERSESORT:ContentName</Assign>
    <Export Target="C:\SenseNet\WebSite\App_Data\export_target" Filter="@filter"></Export>
...

Example 3:

...
<Steps>
    ...
    <StartRepository/>
    <Assign Name="@path">/Root/Sites/Default_Site/Cars</Assign>
    <Assign Name="@filter">+Type:Car</Assign>
    <Export Target="export_target" Filter="@filter">@path</Export>
...

ForEach

  • Full name: SenseNet.Packaging.Steps.ForEach
  • Properties: Item, ContentQuery, Files

Implements a loop structure inside the package, that iterates through the collection having collected by the given source. Use this step to define a recurring loop of steps on the resources obtained by the source property.The source can be two kinds: Files or ContentQuery. Exactly one of them must be present at once. Files property is used to give a file system path relative to the web root. ContentQuery on the other hand is used to define a repository query expression. A ForEach step must contain exactly one Block XML tag. The Block tag is not an independent step, it serves only one aim: to contain the steps that are executed subsequently on each and every resource. The Block tag can contain indefinite number of steps (not every step is allowed to be put inside a ForEach step). The Item property contains the identifier of an inner package variable, that holds the value of the current resource, while the loop is executing. The Item's value must contain only English alphabetic characters preceded by a @ character.

This step can be placed in ForEach steps' Block sections.

Example 1:

...
<Steps>
  <StartRepository />
  <ForEach item="@path" files="Tools\*.config">
    <Block>
      <Copy TargetDirectory="App_Data\copytest" SourceIsRelativeTo="TargetDirectory">@path</Copy>
    </Block>
  </ForEach>
</Steps>
...

Example 2:

...
<Steps>
  <StartRepository />
    <ForEach item="@filePath" files="Admin\ForEachAndImport\contents\*.Content">
      <Block>
	<Import source="@filePath" target="/Root/Folder1" SourceIsRelativeTo="TargetDirectory" />
      </Block>
    </ForEach>
</Steps>
...

Example 3:

...
<Steps>
  <StartRepository/>
  <ForEach item="@content" ContentQuery="+InFolder:/Root/MyFolder/MyContent">
    <Block>
	<Delete>@content.Path</Delete>
    </Block>
  </ForEach>
</Steps>
...

StartRepository

  • Full name: SenseNet.Packaging.Steps.StartRepository
  • Default property: -
  • Additional properties: StartLuceneManager, StartWorkflowEngine, PluginsPath, IndexPath, RestoreIndex, BackupIndexAtTheEnd

Starts the Content Repository in the SnAdmin tool. Use this step before accessing content in the Content Repository from any step.

Import

  • Full name: SenseNet.Packaging.Steps.Import
  • Default property: Source
  • Additional properties: AbortOnError, LogLevel, SourceIsRelativeTo, Target

Imports content from the package to the Content Repository.

This step can be placed in ForEach steps' Block sections.

The valid values for SourceIsRelativeTo are the following:

  • Package: the source path is relative to the package root folder (default)
  • TargetDirectory: the source path is relative to the web site root folder (this is the mandatory value if the step is put into a ForEach step)

The valid values for LogLevel are the following:

  • Info: minimal information (default)
  • Progress: displays a status bar of the ongoing import process
  • Verbose: displays everything (one line per every imported content)

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

The source is always a file system structure in the package or in the target web folder. This is similar structure used by the importer tool. For example

...
<Steps>
  <StartRepository />
  <Import target="/Root/YourContents/MyFolder" logLevel="Info" abortOnError="true">./import</Import>
</Steps>
...
...
<Steps>
  <StartRepository />
  <Import target="/Root/YourContents/MyFolder" logLevel="Info" abortOnError="true" SourceIsRelativeTo="TargetDirectory">App_Data\TempImport</Import>
</Steps>
...

If the "import" directory contains a content "MyContent", after the execution the this content could be accessed on the "/Root/YourContents/MyFolder/MyContent" path.

ImportSchema

  • Full name: SenseNet.Packaging.Steps.ImportSchema
  • Default property: Source
  • Additional properties: LogLevel, AbortOnError

Installs content types or aspects to the Content Repository. LogLevel can be "Info", "Progress", "Verbose" (see details above).

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

If the import material contains schema elements (any aspect or CTD) these must be separated in the file system and must import them with this step. Schema elements must be categorized into "Aspects" and "ContentTypes" directories and this containers' parent will be the source of the step. For example here is a part of a manifest that deals a whole import (schema and content too).

...
<Steps>
  <StartRepository />
  <ImportSchema logLevel="Progress" abortOnError="true">./schema</ImportSchema >
  <Import target="/Root/YourContents/MyFolder" logLevel="Info" abortOnError="true">./import</Import>
</Steps>
...

The file system structure in the example above:

  schema
    Aspects
      Aspect1.xml
    ContentTypes
      MycontentTypeCtd.xml
  import
    MyContent.Content
  manifest.xml

Rename

  • Full name: SenseNet.Packaging.Steps.Rename
  • Default property: NewName
  • Additional properties: Source, SourceIsRelativeTo

Renames a repository content or a file. NewName property holds the value of the object's new name. Source can be either a repository path or a file system path.

The valid values for SourceIsRelativeTo are the following:

  • Package: the source path is relative to the package root folder (default)
  • TargetDirectory: the source path is relative to the web site root folder

This step can use a phase variable in Source and in NewName properties

Example1:

...
<Steps>
   <Rename Source="WebRoot\Insertable\Contents\some.Content" SourceIsRelativeTo="TargetDirectory">another.Content</Rename>
</Steps>
...

Example2:

...
<Steps>
   <Rename Source="Contents\feature1.Content" SourceIsRelativeTo="Package" NewName="feature.Content"></Rename>
</Steps>
...

Example3:

...
<Steps>
   <Assign Name="@path">WebRoot\Insertable\Contents\some.Content</Assign>
   <Assign Name="@newName">another.Content</Assign>
   <Rename Source="@path" SourceIsRelativeTo="TargetDirectory">@newName</Rename>
</Steps>
...

ReplaceText

  • Full name: SenseNet.Packaging.Steps.ReplaceText
  • Default property: Value
  • Additional properties: Path, Template, Regex

Loads a text file or a content defined by the Path property and replaces a pattern defined by the Template or the Regex property with the Value (on all configured web servers). This step can be a simple text replace, or a regular expression replace with complex pattern matching, according to the given parameters. If the task is a simple text replace you can use the Template parameter or if the task involves a pattern matching you can use the Regex parameter. If both provided, the Template is omitted.

Example1:

...
<Steps>
   <ReplaceText path="/Root/Skins/sensenet/scripts/init.js" template="$(function () {">
	<![CDATA[
		$(function () {
			var $state = getState();
	]]>
   </ReplaceText>
</Steps>
...

Example2:

...
<Steps>
   <ReplaceText path="/Root/Global/pagetemplates/user-dialog.html" template="&lt;/head&gt;">
	<![CDATA[
                <script src="//code.jquery.com/jquery-1.11.3.min.js"></script>
            </head>
	]]>
   </ReplaceText>
</Steps>
...

JSON text

EditJson

  • Full name: SenseNet.Packaging.Steps.EditJson
  • Default property: Value
  • Additional properties: Path, Field

From version 6.5.4.9851

This step allows you to modify an existing file or content that contains JSON-formatted data (for example Settings files). The Value default property is a JSON fragment that may contain simple properties or a whole json object tree. It will be merged into the target JSON defined by the usual Path and (the optional) Field properties.

<EditJson Path="/Root/System/Settings/Logging.settings">
{ 
	Trace: {
		TaskManagement: false
	}
}
</EditJson>

Xml manipulation

The following steps help you create, remove or edit xml fragments either in the file system (e.g. config files) or in the Content Repository.

Handling namespaces

From version 6.5.4.9851

It is important to take care of namespaces when editing xml files. You can provide namespace definitions for the xml steps below by defining an attribute that has the following form: 'namespace-[prefixname]'. You can use this prefix in your XPath expressions defined for the step. For example:

<DeleteXmlNodes	Content="/Root/MyFolder/MyCustom.xml"
   xpath="/x:rootelement/x:subelemenet/x:field[@name = 'Test']"
   namespace-x="http://schemas.example.com/a/b/c" />

AppendXmlFragment

  • Full name: SenseNet.Packaging.Steps.AppendXmlFragment
  • Default property: -
  • Additional properties: Source, Xpath, File, Content, Field

Appends the given xml fragment (from the Source property) as a child (or children) under the xml elements determined by the Xpath property. The target xml can be in the file system (usually a .config file) or in the Content Repository (a field value of a content).

The default property model does not work in this step by design (because the source is an xml fragment itself), so you will need to provide the Source tag explicitely as shown below. The Source value cannot appear as an xml attribute either.

If the target is a content, please make sure that a StartRepository step precedes this one to make sure that the repository is started.

For example we extend the "test.xml" in the App_Data directory. First here is the package step:

<AppendXmlFragment file="App_Data\test.xml" xpath="/testxml/element[2]">
  <Source>
    <testElement attr="any"/>
    <testElement attr="42">
      <nestedElement>42</nestedElement>
    </testElement>
  </Sourc e>
</AppendXmlFragment>

The target XML before execution:

<?xml version="1.0" encoding="utf-8"?>
<testxml>
  <element>one</element>
  <element>
    <nestedElement />
    <nestedElement />
  </element>
  <element />
</testxml>

Target XML after execution:

<?xml version="1.0" encoding="utf-8"?>
<testxml>
  <element>one</element>
  <element>
    <nestedElement />
    <nestedElement />
    <testElement attr="any" />
    <testElement attr="42">
      <nestedElement>42</nestedElement>
    </testElement>
  </element>
  <element />
</testxml>

AppendXmlAttributes

  • Full name: SenseNet.Packaging.Steps.AppendXmlAttributes
  • Default property: Source
  • Additional properties: Xpath, File, Content, Field

Appends or overwrites the given attributes (from the Source property) to the xml elements determined by the Xpath property. The target xml can be in the file system (usually a .config file) or in the Content Repository (a field value of a content).

The source property describes the appended or edited attributes. The valid format is a JSON object.

If the target is a content, please make sure that a StartRepository step precedes this one to make sure that the repository is started.

For example we extend the "test.xml" in the App_Data directory. First here is the package step:

<AppendXmlAttributes file="App_Data\test.xml" xpath="//element">
  { attr: "value", attr1: "value1" }
</AppendXmlAttributes>

The target XML before execution:

<testxml>
  <element />
  <element attr="oldValue"/>
</testxml>

Target XML after execution:

<testxml>
  <element attr="value" attr1="value1" />
  <element attr="value" attr1="value1" />
</testxml>

EditXmlNodes

  • Full name: SenseNet.Packaging.Steps.EditXmlNodes
  • Default property: -
  • Additional properties: Source, Xpath, File, Content, Field

Overwrites the content of the selected element or value of the selected attributes. The selector is the Xpath property. If the selection is attributes, their value will be overwritten. In case of elements the full inner xml will be overwritten. The Source property contains the new value or fragment. This step does not have default property similarly for AppendXmlFragment step.

The target xml can be in the file system (usually a .config file) or in the Content Repository (a field value of a content).

If the target is a content, please make sure that a StartRepository step precedes this one to make sure that the repository is started.

For example we change the value of the "attr" on the "element" when the value is "42":

<EditXmlNodes file="App_Data\test.xml" xpath="//element[@attr='42']/@attr">
  <Source>Forty two</Sour ce>
</EditXmlNodes>

The target XML before execution:

<testxml>
  <element attr="42"/>
  <element attr="43"/>
</testxml>

Target XML after execution:

<testxml>
  <element attr="Forty two"/>
  <element attr="43"/>
</testxml>

DeleteXmlNodes

  • Full name: SenseNet.Packaging.Steps.DeleteXmlNodes
  • Default property: -
  • Additional properties: Xpath, File, Content, Field

Deletes the xml nodes determined by the Xpath property.

The target xml can be in the file system (usually a .config file) or in the Content Repository (a field value of a content).

If the target is a content, please make sure that a StartRepository step precedes this one to make sure that the repository is started.

For example we delete all of the "nestedElement" in any level of the document. The step:

<DeleteXmlNodes file="App_Data\test.xml" xpath="//nestedElement" />

The target XML before execution:

<testxml>
  <element>one</element>
  <element>
    <nestedElement />
    <nestedElement />
    <testElement attr="any" />
    <testElement attr="42">
      <nestedElement>42</nestedElement>
    </testElement>
  </element>
  <element />
</testxml>

Target XML after execution:

<testxml>
  <element>one</element>
  <element>
    <testElement attr="any" />
    <testElement attr="42"></testElement>
  </element>
  <element />
</testxml>

Content type manipulation

The following steps are designed specifically to modify content types. From version 6.5.4.9851 you can choose to use the generic xml manipulation steps instead (see above), if you do not find the particular CTD step that you need here.

AddField

  • Full name: SenseNet.Packaging.Steps.AddField
  • Default property: FieldXml
  • Additional properties: ContentType

Adds a non-existing field to a content type. The ContentType property must refer to an existing content type name. FieldXml is the xml fragment that will be inserted. One step is able to add only one field. Because of the manifest parsing and XML processing specialities there are two ways to use this step:

  • The default-property model requires a CDATA section.
  <AddField contentType="MyCustomizedContent">
    <![CDATA[
      <Field name="OurNewField" type="LongText">
        <DisplayName>Our new field</DisplayName>
        <Description>For test purposes only.</Description>
        <Configuration>
          <MaxLength>1000</MaxLength>
        </Configuration>
      </Field>
    ]]>
  </AddField>
  • In case of explicit property the field must be written in raw XML format. To keep it simple we ignore the ContentType's xml namespace so the field node must be written as if it is in the null namespace. After inserting the field it gets the correct namespace.
  <AddField contentType="MyCustomizedContent">
    <FieldXml>
      <Field name="OurNewField" type="LongText">
        <DisplayName>Our new field</DisplayName>
        <Description>For test purposes only.</Description>
        <Configuration>
          <MaxLength>1000</MaxLength>
        </Configuration>
      </Field>
    </FieldXml>
  </AddField>

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

EditField

  • Full name: SenseNet.Packaging.Steps.EditField
  • Default property: FieldXml
  • Additional properties: ContentType, InsertBefore, InsertAfter, FieldName, PropertyName

Adds or modifies a field property in a CTD. This step is able to add new xml fragments to the root of the field only. For changes in the Configuration section please use the EditFieldConfiguration step below.

As the CTD schema is very strict, sometimes it is necessary to provide the previous (or next) xml node to insert the new one after (or before).

There are two ways to provide the new field xml: as a named xml node or as a default property in a CDATA section. See AddField step above for details.

The following sample will add or override an existing display name value for the Field1 field in the File CTD.

<EditField contentType="File" fieldName="Field1" propertyName="DisplayName" InsertBefore="Description">New displayname</EditField>

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

EditFieldConfiguration

  • Full name: SenseNet.Packaging.Steps.EditFieldConfiguration
  • Default property: FieldXml
  • Additional properties: ContentType, InsertBefore, InsertAfter, FieldName, PropertyName

Adds or modifies a field configuration value in a CTD. This step is able to add new xml fragments to the Configuration xml node of the field. For main field property changes please use the EditField step above.

As the CTD schema is very strict, sometimes it is necessary to provide the previous (or next) xml node to insert the new one after (or before).

There are two ways to provide the new xml: as a named xml node or as a default property in a CDATA section. See AddField step above for details.

The following sample will add or override an existing configuration value for the Field1 field in the File CTD.

<EditFieldConfiguration contentType="File" fieldName="Field1" propertyName="Conf1" InsertBefore="Conf2">new value</EditFieldConfiguration>

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

ChangeFieldType

  • Full name: SenseNet.Packaging.Steps.ChangeFieldType
  • Default property: FieldXml
  • Additional properties: ContentType, FieldName, FieldType, ArchiveFieldName

This step is able to change the type of a metadata field defined on a content type. The old field will be removed first than the new one will be added. Old field values will be migrated only if it is possible (e.g. from a Number Field to a Currency Field or from a ShortText Field to a LongText Field). If the conversion does not make sense (e.g. changing a short text field to a reference field), you may provide an archive field for storing old values (that archive field must be created first of course, with the add field step above).

The step also makes possible migrating field values to a field with a different name, if you provide both the FieldName property and a FieldXml that contains a different name for the new field.

  • ContentType: must refer to an existing content type.
  • FieldXml: the xml fragment for the new field. Can be omitted if both FieldName and FieldType are provided. In that case the original xml fragment will be used.
  • FieldName: name of the field to be changed (original name).
  • FieldType: new field type. If you provide FieldName and FieldType, you do not have to provide the full FieldXml.
  • ArchiveFieldName: name of the archive field that has the same type that the original field. Provide this if you need to preserve old field values in an archive field instead of the new one.

Because of the nature of the manifest XML parsing there are two ways to provide the new field xml: as a named xml node and as a default property in a CDATA section. See AddField step above for details.

Changing a number field to a currency field:

<ChangeFieldType contentType="File" fieldName="Field1" fieldType="Currency" />

Changing a field type and providing new settings for the new field:

<ChangeFieldType contentType="File">
	<FieldXml>
	  <Field name="Field1" type="Currency">
		  <DisplayName>My field</DisplayName>
		  <Configuration>
			<MinValue>0</MinValue>
			<Format>en-US</Format>
			<Digits>0</Digits>
		  </Configuration>
		</Field>
	</FieldXml>
</ChangeFieldType>

Migrating a field to a new one with an incompatible type and preserving the old values in an archive field:

<AddField contentType="File">
	<FieldXml>
		<Field name="Field1Archive" type="ShortText">
		  <DisplayName>My field Archive</DisplayName>
		</Field>
	</FieldXml>
</AddField>
<ChangeFieldType contentType="File" fieldName="Field1" fieldType="Reference" archiveFieldName="Field1Archive" />

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

EditContentTypeHeader

from version 6.5.4

  • Full name: SenseNet.Packaging.Steps.EditContentTypeHeader
  • Default property: InnerXml
  • Additional properties: PropertyName

Adds or modifies a property in the header of a CTD, For example Allowed child types, Icon, etc.

As the CTD schema is very strict, sometimes it is necessary to provide the previous (or next) xml node to insert the new one after (or before).

The following sample will add or override the allowed child types list in the Survey list CTD.

<EditContentTypeHeader contentType="SurveyList" propertyName="AllowedChildTypes" InsertAfter="AllowIncrementalNaming">SurveyListItem,Folder</EditContentTypeHeader>

If you want to modify the content handler of the content type, use this step with the property name 'handler'.

<EditContentTypeHeader contentType="SurveyList" propertyName="handler">MyNamespace.MySurveyHandler</EditContentTypeHeader>

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

Permissions and security

Although it is possible to modify content permissions by importing .Content files containing security entries, sometimes it is easier to define permission changes using these specialized steps.

SetPermissions

  • Full name: SenseNet.Packaging.Steps.SetPermissions
  • Default property: Path
  • Additional properties: Identity, Allow, Deny, LocalOnly

Sets permissions on a content, defined by the Path property for the user, group or org unit defined by the Identity property. Permission type names are provided as a comma separated list. Not enumerated permissions will be cleared.

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

For example the following step adds the read permission to the user but clears any other existing permissions:

<SetPermissions
    path="/Root/Sites/MySite/MyPage"
    identity="/Root/IMS/MyDomain/Users/readerRobert"
    allow="Open"
    />

EditPermissions

  • Full name: SenseNet.Packaging.Steps.EditPermissions
  • Default property: Path
  • Additional properties: Identity, Allow, Deny, Clear, LocalOnly

Sets or clears permissions on a content, defined by the Path property for the user, group or org unit defined by the Identity property. Permission type names are provided as a comma separated list. Only the enumerated permissions will be changed.

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

For example the following step extends the user permissions with Publish and Approve and removes AddNew:

<EditPermissions
    path="/Root/Sites/MySite/MyPage"
    identity="/Root/IMS/MyDomain/Users/intranetMike"
    allow="Publish,Approve"
    clear="AddNew"
    />

RemovePermissionEntries

  • Full name: SenseNet.Packaging.Steps.RemovePermissionEntries
  • Default property: Path
  • Additional properties: Identity

Removes all permissions from a content defined by the Path property, for the user, group or org unit defined by the Identity property. If the Identity property is missing, all explicit entries will be removed.

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

For example the first step removes all explicit permissions from the content, while the second only deletes the defined user's permissions:

<RemovePermissionEntries>/Root/Sites/MySite/workspaces<RemovePermissionEntries>
 
<RemovePermissionEntries
  path="/Root/Sites/MySite/samples"
  identity="/Root/IMS/MyDomain/Users/internetJohn"
  />

BreakPermissionInheritance

  • Full name: SenseNet.Packaging.Steps.BreakPermissionInheritance
  • Default property: Path
  • Additional properties: -

Breaks permission inheritance on a content. If the content does not inherit permissions, this step does nothing.

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

RemoveBreakPermissionInheritance

  • Full name: SenseNet.Packaging.Steps.RemoveBreakPermissionInheritance
  • Default property: Path
  • Additional properties: -

Removes break permission inheritance from a content. If the content already inherits permissions, this step does nothing.

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

AddMembers

  • Full name: SenseNet.Packaging.Steps.AddMembers
  • Default property: Members
  • Additional properties: Group

Adds one or more members to the selected Group. The group can be selected by a path or a content query. In case of query only the first content will be used. If the selected group does not exist, the step execution terminates silently, without throwing an error. The Members property is a comma or semicolon separated list of selectors. Every selector can be one of the following:

  • path
  • content query
  • user name (only the domain\username format is allowed e.g.: BuiltIn\Admin)

The result of selectors are aggregated into a single distinct list. Every element of the result list will become a member of the selected group if the element is a group or user (and is not already a member). Any other elements are skipped and logged.

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

<AddMembers group="/Root/IMS/BuiltIn/Portal/VIP">
  /Root/IMS/BuiltIn/Demo/Developers;
  BuiltIn\mike;
  /Root/IMS/BuiltIn/Demo/Managers/robspace;
  +InFolder:"/Root/IMS/BuiltIn/Demo/ProjectManagers";
</AddMembers>

Resources

AddResource

  • Full name: SenseNet.Packaging.Steps.AddResource
  • Default property: -
  • Additional properties: ContentName, ClassName, Resources

Adds or edits string resources. It is able to create the necessary string resource content if it does not exist.

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

<AddResource contentName='MyResourceFile.xml' className='Action'>
  <Resources>
    <add key="res1" lang="en">Resume upload</add>
    <add key="res1" lang="hu">Feltöltés folytatása</add>
    <add key="res2" lang="en">sample</add>
    <add key="res2" lang="hu">példa</add>
  </Resources>
</AddResource>

Conditional steps

One of the most powerful features of the packaging framework is the ability to execute steps based on a condition. These are the built-in conditional steps, but developers may create their own conditional steps if necessary (see details on the previous link).

IfFileExists

  • Full name: SenseNet.Packaging.Steps.IfFileExists
  • Default property: -
  • Additional properties: Path

Checks if the file on the provided path exists in the file system. The path is relative to the target directory.

  <IfFileExists path="App_Data\MyFolder\MyFile.txt">
    <Then>
      ...steps if the file exists...
    </Then>
    <Else>
      ...steps if the file does not exist...
    <Else>
  </IfFileExists>

Please note that in the current version this step checks only the local file system, where the package is executed; it does not check other web folders (if configured). We assume that all the web folders are synchronized.

IfDirectoryExists

  • Full name: SenseNet.Packaging.Steps.IfDirectoryExists
  • Default property: -
  • Additional properties: Path

Checks if the directory on the provided path exists in the file system. The path is relative to the target directory.

  <IfDirectoryExists path="App_Data\MyFolder">
    <Then>
      ...steps if the directory exists...
    </Then>
    <Else>
      ...steps if the directory does not exist...
    <Else>
  </IfDirectoryExists>

Please note that in the current version this step checks only the local file system, where the package is executed; it does not check other web folders (if configured). We assume that all the web folders are synchronized.

IfContentExists

  • Full name: SenseNet.Packaging.Steps.IfContentExists
  • Default property: -
  • Additional properties: Path

Checks if the content with the provided path exists in the Content Repository. Path is an absolute repository path.

  <IfContentExists path="/Root/MyFolder/MyContent">
    <Then>
      ...steps if the content exists...
    </Then>
    <Else>
      ...steps if the content does not exist...
    <Else>
  </IfContentExists>

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

IfFieldExists

  • Full name: SenseNet.Packaging.Steps.IfFieldExists
  • Default property: -
  • Additional properties: ContentType, Field, LocalOnly

Checks if the given field already exists on the provided content type in the Content Repository. If the LocalOnly boolean property is set to True (the default is False), we check only the given CTD xml and do not care about a field defined in a parent type.

  <IfFieldExists contentType="Folder" field="Annotation">
    <Then>
      ...steps if the Folder has an Annotation field...
    </Then>
    <Else>
      ...steps if the Folder does not have an Annotation field...
    </Else>
  </IfFieldExists>

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

IfXmlNodeExists

  • Full name: SenseNet.Packaging.Steps.IfXmlNodeExists
  • Default property: -
  • Additional properties: File, Content, Field, Xpath

Checks if the given xpath already exists in the provided xml file in the files system or in a content in the Content Repository.

  <IfXmlNodeExists file="./web.config" xpath="/configuration/appSettings/add[@key='ClusterChannelProvider']">
    <Then>
      ...steps if the given xpath exists...
    </Then>
    <Else>
      ...steps if the given xpath does not exist...
    </Else>
  </IfXmlNodeExists>

If the target is a content, please make sure that a StartRepository step precedes this one to make sure that the repository is started.

IfDatabaseValue

(from version 6.5.1)

  • Full name: SenseNet.Packaging.Steps.IfDatabaseValue
  • Default property: -
  • Additional properties: Query

Executes the given SQL script (with ExecuteScalar) and checks the result. If it is null, 0 or empty string, the conditional result will be FALSE and the steps defined in the Else branch will be executed. If the result is 'positive' (a number greater than 0 or a non-empty string), the Then branch will get executed.

  <IfDatabaseValue query="SELECT COUNT(0) FROM MyTable WHERE RelatedId IN (3, 4, 5)">
    <Then>
      ...steps if the result is positive...
    </Then>
    <Else>
      ...steps if the result is 0 or negative...
    </Else>
  </IfDatabaseValue>

The query argument can also point to a SQL script file in the package (e.g. scripts\MyPatchScript.sql).

Advanced steps

DisableIndexing

  • Full name: SenseNet.Packaging.Steps.DisableIndexing
  • Default property: -
  • Additional properties: -

Switches off the indexing. This step is experimental, we use it only in internal scenarios.

EnableIndexing

  • Full name: SenseNet.Packaging.Steps.EnableIndexing
  • Default property: -
  • Additional properties: -

Switches on the indexing. This step is experimental, we use it only in internal scenarios.

PopulateIndex

  • Full name: SenseNet.Packaging.Steps.PopulateIndex
  • Default property: Path
  • Additional properties: -

Populates the index of the whole content tree.

Populating a subtree is not implemented in the current version.

CheckIndexIntegrity

  • Full name: SenseNet.Packaging.Steps.CheckIndexIntegrity
  • Default property: Path
  • Additional properties: Recursive, OutputLimit

Checks the index integrity by comparation the index and database. This step needs running repository. All parameters are optional and their meanings are the following:

  • Path: Defines the integrity check's scope if there is. If empty, the whole repository tree will be checked.
  • Recursive: Defines whether check only one content or the whole tree or subtree. Default: true.
  • OutputLimit: Limits the output line count. 0 means all lines. Default: 1000. If this limit is reached the "...truncated..." will be displayed.

Usage on a subtree and show all difference:

<CheckIndexIntegrity outputLimit="0">
    /Root/Sites/Default_Site
</CheckIndexIntegrity>

Fore example here is a possible output if there is some inconsistence:

================================================== #1/2 CheckIndexIntegrity
Recursive integrity check. Scope: /Root
Integrity check finished. Count of differences: 5
  MoreDocument: DocId: 3576, VersionId: 3979, NodeId: 4967, Version: v1.0.a, DbNodeTimestamp: 3713243, IxNodeTimestamp: 3713243, DbVersionTimestamp: 3713247, IxVersionTimestamp: 3713247, Path: /root/sites/default_site/workspaces/project/pragueprojectworkspace/document_library/aenean semper.doc
  NotInIndex: VersionId: 3980, NodeId: 4968, Version: V1.0.A, DbNodeTimestamp: 3713251, DbVersionTimestamp: 3713255, Path: /Root/Sites/Default_Site/workspaces/Project/pragueprojectworkspace/Document_Library/Aliquam porta suscipit ante.doc
  MoreDocument: DocId: 3578, VersionId: 3981, NodeId: 4969, Version: v1.0.a, DbNodeTimestamp: 3713259, IxNodeTimestamp: 3713259, DbVersionTimestamp: 3713263, IxVersionTimestamp: 3713263, Path: /root/sites/default_site/workspaces/project/pragueprojectworkspace/document_library/duis et lorem.doc
  NotInDatabase: DocId: 3577, VersionId: 3979, NodeId: 4967, Version: v1.0.a, IxNodeTimestamp: 3713243, IxVersionTimestamp: 3713247, Path: /root/sites/default_site/workspaces/project/pragueprojectworkspace/document_library/aenean semper.doc
  NotInDatabase: DocId: 3579, VersionId: 3981, NodeId: 4969, Version: v1.0.a, IxNodeTimestamp: 3713259, IxVersionTimestamp: 3713263, Path: /root/sites/default_site/workspaces/project/pragueprojectworkspace/document_library/duis et lorem.doc
-------------------------------------------------------------
Time: 00:00:00.2456550

ChangeContentType

  • Full name: SenseNet.Packaging.Steps.ChangeContentType
  • Default property: -
  • Additional properties: ContentQuery, ContentTypeName

Changes the content type of one or more content, collected by the ContentQuery property. The new type is defined by the ContentTypeName property. Limitations:

  • only leaf content (that have no children) can be changed (this is because the step actually creates a new content based on the source content)
  • only child types are allowed, meaning the new type must be inherited from the original type of the content

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

EditAllowedChildTypes

  • Full name: SenseNet.Packaging.Steps.EditAllowedChildTypes
  • Default property: Add
  • Additional properties: Remove, Path, ContentType

Changes the AllowedContentTypes list of the defined content type or content by the provided new and retirement list. Step parameters:

  • Add: Comma separated content type names that extend the original AllowedChildTypes list.
  • Remove: Comma separated content type names that narrow the original AllowedChildTypes list.
  • Path: Full path of the existing content to edit. If provided, the ContentType parameter is prohibited.
  • ContentType: Name of the existing content type to edit. If provided, the Path parameter is prohibited.

Examples:

...
  <EditAllowedChildTypes path="/Root/IMS" add="SystemFolder" />
  <EditAllowedChildTypes path="/Root/Sites/MySite/Test1">ImageLibrary,Image,Page</EditAllowedChildTypes>
  <EditAllowedChildTypes path="/Root/Sites/MySite/Test2" add="ImageLibrary,Image" remove="Page"/>
  <EditAllowedChildTypes contentType="Domain" add="RegisteredUser" remove="SystemFolder"/>
...

Please make sure that a StartRepository step precedes this one to make sure that the repository is started.

Trace

  • Full name: SenseNet.Packaging.Steps.Trace
  • Default property: Text
  • Additional properties: -

Writes the given text to the console and to the package log. You can annotate the execution with this step. For example:

  <Trace>The main structure is installed.</Trace>

StopSite - from version 6.4.1

  • Full name: SenseNet.Packaging.Steps.StopSite
  • Default property: Site
  • Additional properties: MachineName

Stops an IIS site on a local or a remote machine. Useful in automatic build scenarios, when you need to update files in a web folder (e.g. NLB test sites).

<StopSite machineName="\\MYVPC01">test.example.com</StopSite>

This step uses the PsExec tool to execute appcmd.exe on remote machines. Please download PsTools and copy PsExec.exe to one of the well-known Windows folders (System32 or SysWOW64, depending on the environment) to let the system access the tool.

StartSite - from version 6.4.1

  • Full name: SenseNet.Packaging.Steps.StartSite
  • Default property: Site
  • Additional properties: MachineName

Starts an IIS site on a local or a remote machine. Useful in automatic build scenarios, when you need to update files in a web folder (e.g. NLB test sites).

<StartSite machineName="\\MYVPC01">test.example.com</StartSite>

This step uses the PsExec tool to execute appcmd.exe on remote machines. Please download PsTools and copy PsExec.exe to one of the well-known Windows folders (System32 or SysWOW64, depending on the environment) to let the system access the tool.

Terminate

  • Full name: SenseNet.Packaging.Steps.Terminate
  • Default property: Message
  • Additional properties: Reason. The type is SenseNet.Packaging.TerminationReason enumeration that has two options:
    • Successful: the package will terminate with success
    • Warning: the package execution result will be Faulty

Writes the given message to the console and to the package log. If the Reason is Warning, the package result will be faulty.

Examples

In case of all conditions are fulfilled and there are no actions left, the execution can be interrupted.

  <IfDirectoryExists path="App_Data\MyFolder">
    <Then>
      <Terminate reason="Successful">No need to execute other steps.</Terminate>
    </Then>
  </IfDirectoryExists>
  ... other relevant steps ...

In the opposite case, when an error is detected in the environment and any further action can be harmful use the Terminate step with Warning and enter compensation-strategy instructions into the element (or into the Message property).

  <IfDirectoryExists path="App_Data\MyFolder">
    <Then>
      <Terminate reason="Warning">
        Cannot continue the execution because MyFolder exists in the App_Data.
        Please delete it and rerun this package.
      </Terminate>
    </Then>
  </IfDirectoryExists>
  ... other relevant steps ...

Related links