Include File Patching Facilities

Total Page:16

File Type:pdf, Size:1020Kb

Include File Patching Facilities

Include file patching facilities Table of contents 1 Introduction The main purpose of the include mechanism is extending of configuration facilities. Include files allow you to introduce new settings or properties or modify the values of the existing ones. There is special XML syntax that allows you to perform common operations: insert a node into a defined place, modify an attribute value, remove a node etc. The below article describes this in more detail.

2 General concepts

2.1 XML namespaces and node names One of the advantages of using XML is namespaces. Each node and attribute is defined inside a certain namespace, which is empty by default. You can find more information about XML namespaces in Wikipedia (http://en.wikipedia.org/wiki/XML_namespace). All the attributes and elements that are related to patching (later: p-controlling nodes) are located inside the following namespaces:  patch – http://www.sitecore.net/xmlconfig/

 set – http://www.sitecore.net/xmlconfig/set/ In order to use them in our include file, we must declare namespaces before we start using them. Normally, they are declared at the beginning of a file:

......

In such a scenario, the p-controlling nodes may be accessed by using the patch: and set: prefixes. Since we will frequently refer to particular node names later in this document, let me remind you of some of the related terms according to the established naming convention. Node – a primary data type for the entire tree. A node can be an element node, an attribute node, a text node etc. Element – a logical document component which either begins with a start-tag and ends with a matching end-tag or only contains an empty-element tag (i.e. ). Attribute – a markup construct consisting of a name/value pair that exists within a start-tag or empty- element tag (i.e. ).

2.2 Include directory and *.config files When Sitecore reads the configuration, first of all it gets the content of the web.config file. After this it gets all of the *.config files from the /App_config/Include (later Include) folder and uses them to extend/modify the content of the section, which is defined in the web.config file. The files from the Include folder (include files later) are applied sequentially. The list of the *.config files is obtained using the System.IO.Directory.GetFiles() method. According to the MSDN, there is no strict order, in which file names are ordered, but normally they are sorted by name. This means that Sitecore applies the ZName.config file after AName.config file. Basically, it doesn’t matter. But if the same setting (or node) is modified in more than one include file, only the last modification will be accepted. In this case the file order does matter.

Sitecore takes only *.config files into account. So if we need to disable a particular *.config file, we only have to change its extension. The include mechanism traverses the file system recursively. Sitecore enumerates all non-hidden files and then recursively enumerates all non-hidden folders. We should take this order into account when introducing folders in the Include folder.

2.3 Path to target node As a rule, each file of the Include folder changes the content of the element. We must specify in a unique way which node must be modified. This may be the parent node of a custom processor or an existing node, whose attribute will be altered. CMS configuration is represented as an XML document. As the include files are applied, CMS recursively traverses all elements starting from the root. When Sitecore processes a particular element, two options are possible:  This element already exists, and Sitecore modifies its content.

 This element doesn’t exist, so Sitecore introduces this element as a new one. In order to match the element in the original configuration document, Sitecore takes the element’s name and all its attributes into account. The only attributes that Sitecore ignores are p-controlling nodes (i.e. nodes from the set and patch namespaces) and namespace declarations (e.g. ). The comparison algorithm follows: 1.1.1.1.i.1. Sitecore takes an element from an include file and extracts all its attributes with their values. All the p-controlling nodes and namespace declarations are ignored. 1.1.1.1.i.2. Sitecore checks whether an element of the same level with the same name and attribute set exists in the original document. 1.1.1.1.i.3. If a few nodes with such constraints exist, Sitecore selects the first of these nodes. For instance, if we specify the element in the include file, only the first processor will be matched. Note that we use attributes and their values as constraints to clarify which specific node we mean. If we don’t specify enough attributes, a wrong element may be matched (e.g. the first event handler with the same type attribute value). On the other hand, if we specify redundant attributes values, Sitecore might not match any node if its value was changed in the original document (e.g. in the web.config file or the previous include file). So each time we construct the include file, we must analyze which attribute to include and which to omit. Consider the following example to better understand the rules. Suppose, we have the following configuration defined in the web.config file:

Currently our task is to remove the OnItemChanged event handler and set the AllowLogoutOfAllUsers setting to true. The content of the include file may be following:

Let us ignore for a moment the patch specific nodes; we will talk about them and their usage later. Note how the event handler and setting are specified. Now let me perform analysis of the XML document.  The sitecore element doesn’t require any constrains because there is only one sitecore element is available.  The original events element contains the timingLevel attribute. We ignored this attribute because there is only one events node, and ambiguity is impossible. Moreover, it is unsafe to specify it because if we change the timingLevel value in the web.config file, CMS will not be able to match it from that time onwards.  There are several event nodes; this is why, we used the name attribute to identify the exact one.

 For handler, we used both type and OnItemChanged attributes. The usage of the type attribute only is not enough because the OnItemRemoved handler will be matched in this case. We only may use the method attribute because there are no other handlers with this method name. However, it goes against logic (only the whole type-method pair represents a handler) and may cause issues if we introduce one more handler with the same method attribute value.  For the settings node, we didn’t use any attributes, because only one such node exists.

 For the setting element, we used the name attribute value only. If we add the value attribute, it will work fine only until we change the value in web.config or any preceding include files. The resulting configuration is as follows:

2.4 Resulting configuration (showconfig.aspx) As Sitecore is started, it reads and merges the configuration files producing the resulting XML document. This document is stored in the process memory, and the CMS works with it each time it needs configuration values. In order to view the resulting XML file, we may use the showconfig.aspx page. The URL is as follows: http://hostName/sitecore/admin/showconfig.aspx. We recommend that you work with the showconfig.aspx page output to check the actual configuration rather than look at web.config at stand-alone include files. In this case, we don’t have to worry that a node was overridden in any other file.

3 Patch namespace (http://www.sitecore.net/xmlconfig/)

3.1 Overview The patch namespace contains two type of nodes. There are the attributes () and elements (), whose functionality differs. We should define the http://www.sitecore.net/xmlconfig/ namespace to access these nodes. Although we may specify any alias for namespace, usually the patch is assigned:

3.2 Attribute nodes Normally when we introduce a new element, it is appended at the end of the parent element. The attribute nodes from the patch namespace are used to determine the relative position of the inserted element. Usually such attributes are used only when we introduce new elements. These attributes aren’t designed to move the existing elements. There are only 3 attributes in this namespace, which are described below. The attribute value is an xpath of the sibling the attribute is related to. The xpath is applied to the parent element, and we usually specify a sibling element. Each attribute has a short alias, which may be used instead of its long name. 3.2.1 patch:before This attribute allows to specify the sibling element before which the current element should be inserted. Short alias: b. Syntax

Example of usage Original configuration:

Include file content:

Resulting configuration:

3.2.2 patch:after This attribute allows to specify the sibling element after which the current element should be inserted. Short alias: a. Syntax

Example of usage Original configuration:

Include file content:

Resulting configuration:

3.2.3 patch:instead This attribute allows us to specify the sibling element instead of which the current element should be inserted. Unlike patch:before and patch:after, this attribute allows us to entirely replace the original node. Short alias: i. Syntax

Example of usage Original configuration:

Include file content:

Resulting configuration:

3.3 Elements nodes The element nodes (i.e. the tags from the patch namespace) are applied to their parents. This means that the element affects only the parent element which surrounds it. Such nodes cannot contain the child elements. If they exist, they will be ignored. The patch namespace contains only two-element nodes, any other are ignored, such as attribute nodes. These nodes have also aliases, which may be used instead of their full names. 3.3.1 patch:delete This element doesn’t contain a value and attributes. It is just a marker that the parent node should be removed. Short alias: d. Syntax

Example of usage Original configuration:

Include file content:

Resulting configuration:

Note that we specified the name attribute for the element node in our include file to identify which exactly element should be removed. If we omitted the attribute, the first element would be removed (with the name “a”). 3.3.2 patch:attribute This element is used to modify the attribute value of the parent element. Usually it is used to change a value of some setting or type of some pipeline processor/event handler. The last change normally takes place when we override the default Sitecore functionality. Short alias: d. Syntax

newAttributeValue

The purpose of the nodes is the following:  name attribute is used to specify the name of the parent’s attribute, whose value should be changed.

 value attribute is used to specify the new value of the specified attribute.

 Optionally, we may specify a new attribute value as the value of the attribute tag. If both the value attribute and element value are available, the last is taken into account. Example of usage Original configuration:

Include file content:

Resulting configuration:

Usually the patch:attribute element is used to change the setting value, type of objects (by modifying the type attribute value) or some other parameters (e.g. defaultProvider value for manager).

4 Set namespace (http://www.sitecore.net/xmlconfig/set/)

4.1 Overview The only purpose of the Set namespace is overriding of the attribute values. This namespace doesn’t contain any predefined elements or attributes and may be applied only to attribute nodes. In the previous chapter the patch:attribute element has been introduced. The Set namespace duplicates the functionality of this element, but allows to do this in a more convenient way. Similar to the patch namespace, we must also define the http://www.sitecore.net/xmlconfig/set/ namespace before we start using it. The Set namespace prefix is a marker that we want to override the present attribute value of the current element with (i.e. we say “set value of this attribute to the specified value, no matter which it was before. If it is not available, introduce it. We want to have this attribute with a specified value.”). All the attributes which start with the Set namespace prefix, will not be used during node matching (functionality, covered in the 2.3 Path to target node chapter). We must be aware when dealing with this namespace because a single element may contain attributes with the same name more than once: without the namespace prefix to help identify a node and with a namespace prefix to alter the attribute value (e.g. ).

4.2 Syntax The Set namespace doesn’t contain any predefined attributes and elements, so there are no special syntaxes. If we want an attribute to belong to the Set namespace to alter its value, we should declare the namespace and add the appropriate prefix to the attribute name:

If the original element node contains the attr3 attribute, the value will be overridden with “newValue”. If such attribute isn’t present, it will be introduced.

4.3 Examples The namespace itself doesn’t contain any nodes and its usage is direct, but confusion may arise when the attribute is mentioned twice (one without a namespace prefix and one with the Set namespace prefix). Suppose we have the following configuration:

Suppose we would like to change the color attribute for the “b” element. In this case our include file should identify the node itself and contain the color attribute with a new value. The color attribute should be coupled with the Set attribute prefix. Include file content:

Resulting configuration:

The {name="b"} attribute was used to identify the proper element (because there are a few ones). The {set:color="yellow"} attribute, coupled with the set namespace prefix, was used to alter the value of the existing color attribute. Let’s perform a trickier change. Suppose we need to change the blue color to violet for the following element: In this case we can’t use only the name or color attribute because this will lead to ambiguity (logically ambiguous, because CMS will pick up the first node that matches specified attribute values). So in order to identify the node, we have to use both the name and color attributes. At the same time, our element should contain the color attribute in the set namespace with a new value. Include file content:

Resulting configuration:

In our include file, we used the {name="c"} and {color=”blue”} attributes to identify the node and decorated {“set:color="violet"} attribute to alter the attribute value.

5 Example of multiple approaches to solve the same task In the last section devoted to the Set namespace, we noted that all the functionality of the patch:attribute may be replaced by usage of the Set namespace. But as we discussed the patch namespace, we discovered that the same task may be done in different ways. Let’s demonstrate this.

5.1 Case Suppose we have the following configuration (a part from ECM):

It’s quite simple. Currently our goal is overriding the default type resolver. More specifically we should set our custom type value to the type attribute.

5.2 Possible approaches 5.2.1 patch:delete & insert new The first and most direct way is to remove the whole TypeResolver node and specify our custom one. This may be done by the following include file content:

5.2.2 patch:instead We may use the patch:instead attribute to insert our custom TypeResolver element instead of the default one:

5.2.3 patch:attribute The patch:attribute node allows us to modify the type attribute only and doesn’t affect other attributes (e.g. singleInstance). So we may use it as well:

CustomTypeResolver, Custom

5.2.4 Set namespace If we were able to achieve the result using the patch:attribute node, we can do the same using the Set namespace. The content may be following:

5.3 Final result No matter which way we chose, the final configuration is the following:

5.4 Approach analysis We can achieve the goal using any of the approaches described above, so it may appear that it is fine to choose any of them. Although they all bring the same result, not all of them are recommended. Let’s review this more thoroughly. First two methods totally override the TypeResolver element. This means that we are overriding the singleInstance attribute value as well ignoring its old value. If we change the original attribute value in the web.config file or any preceding include file, the actual value will not be affected. The probability of this particular change is relatively low, so in this case it is a matter of taste. But there are places when it will be a mistake to follow this approach. For instance, if we want to override the database type:

......

In this particular case we need to bring the whole node to the include file. It may happen that some preceding include files affect the database settings (e.g. tune caches sizes, specify custom engines) and these changes will be ignored. So we should be careful when we a make a decision regarding the approach. The last two approaches are more elegant because they affect only the type attribute. The approach with Set namespace requires less text and seems simpler. So any of the last two approaches is recommended. Every time we select an approach, we should keep in mind other approaches as well. In ideal world, the selected approach should affect only the attributes/elements we are interested in and rely on minimal number of other values.

6 Sitecore 7 changes By and large, there have been no major changes in functionality. All features from Sitecore 6 are still actual and can be used. So in terms of backward compatibility everything is fine.

6.1 One more “Include” folder Sitecore started to take into account one more folder during the initialization. The folder path in the following: /App_Config/Sitecore/Components. This folder is applied before applying the /App_config/Include folder. It does matter if we override settings, which are overridden by other include files.

6.2 patch:source attribute The patch:source attribute have been introduced in Sitecore 7. The purpose of this attribute is to indicate the source of the actual value in the merged XML document. The value of this attribute is a name of file that modified the element (e.g. altered the attributes) last. This value is assigned automatically to the resulting XML document and we shouldn’t specify it by ourselves. It doesn’t affect anything and was introduced to help quickly identify value source. The resulting XML document may be obtained using the showconfig.aspx page.

Recommended publications