13

Sitecore's .config files will sometimes use the ref attribute for inheriting the current node from an existing configuration node.

Here's an example from Sitecore.ContentSearch.Solr.Index.Analytics.config:

<configuration ref="contentSearch/indexConfigurations/defaultSolrIndexConfiguration">
  <fieldMap ref="contentSearch/indexConfigurations/defaultSolrIndexConfiguration/fieldMap">
    <fieldNames hint="raw:AddFieldByFieldName">
    ...
  • How does this feature work, exactly? It's clear that you can use XPath to refer to another node, but what does this do under the hood? Will the whole content of the referenced node, along with all attribute values, be (logically) copied into the referrer?
  • Are there any caveats about extending referenced configuration? Like in the example above, <fieldMap> both refers to an existing node and adds its own children. Will they be merged with the original node's children?

2 Answers 2

16

The Sitecore XML configuration has some fairly handy things in it, and ref is one of them. I spent a bit of time playing around with it some time ago; I think that I can provide an answer, but it's quite a long one so buckle in.

With 'how it works'... For fine detail, you can investigate the Factory.CreateObject(XmlNode, string[], bool, IFactoryHelper) and the Factory.CreateFromReference(XmlNode, string[], bool) methods, but in a nutshell Sitecore will attempt to construct the object in a few different ways. One of which is using a given ref or path attribute. Sitecore does not, at any point, actually fiddle with the underlying XML (e.g. by merging or copying it).

As you'll likely be aware, Sitecore assigns the properties of the object based on the child nodes present in the XML that identifies the type name. There are some exceptions to this case, but by and large this holds so long as the hint attribute is not used. To provide an example, the following XML (when requested through Factory) will create an object of type MyType and then proceed to set the value of the MyProperty property on that object to "foo":

<someNode type="MyType, MyAssembly">
  <myProperty>foo</myProperty>
</someNode>

The population process described above occurs on two separate occasions: first with properties matching the child nodes present in the "referred" XML, and second with the properties matching child nodes present in the "original" XML. This is what allows for configuration such as with the Content Search indexes where index configuration can override a "default".

The interesting caveat here, is that because the XML is never merged, the "original" property values take precedence over the "referred" property values when used normally (i.e. set property X to value Y). This is why you often have to duplicate swathes of the default index configuration if you just want to add a value.

A further caveat to the above is: if you're using hint attributes to call methods then my understanding is that the method will be called for the "referred" XML and then the "original" XML. I haven't looked too deeply into this - but it makes sense given that it would be tricky to somehow "undo" the unknown effect of a method call. This is your best bet if you want to "merge" your values, and is probably why it only "sometimes" works if you just add in your changes rather than the full set of default values.

In terms of where it can be used, you can only use ref for XML that governs the instantiation of an object. Typically this means when you're creating an object for an object's property, or if you're making some top-level XML that you yourself intend to use the Factory class to instantiate.

To clarify the above: you - unfortunately - cannot use it if you're simply constructing an XML-only configuration node and want to reduce repetition, or to copy in commonly used values for properties (e.g. cache sizes for databases). You must be creating an object. I spent quite a bit of time attempting to do this and scratching my head when it didn't work, before digging a bit deeper.

A rather trivial point is that the ref will only be followed once per object. You cannot use a ref attribute to point to an element which is in turn another ref. Although you can obviously use ref on properties inside of those objects.

Hopefully that wasn't a whole lot of TL;DR and it answers your questions enough; if there's something I've missed or any mistakes please let me know.

4
  • Thanks a lot! This was very interesting and useful. How about the children of the referred node? Will the factory use them when creating the object? Oct 23, 2016 at 19:53
  • Yep, as I say in my answer, it will set the properties first from the "referred" XML and after that it will set the properties contained in the "original" (referring) XML
    – Matt
    Oct 24, 2016 at 7:32
  • I've added some clarification on how child nodes in the XML map to properties on the created objects, and included a simple example. While the answer isn't quite so straight-forward, I believe that it holds for the majority of cases people will encounter. Does that clear things up a bit?
    – Matt
    Oct 24, 2016 at 13:31
  • Yes, thank you! I was first confused by what you meant by "property". For some reason, I was thinking about node attributes the whole time! With your expanded explanation, it is now much more clear you meant object properties. Oct 24, 2016 at 13:33
2

The ref attribute is used to refer to other parts of the configuration using an XPath. If there is a piece on config which is already in place with information needed, instead of repeating it you can refer to it.

The ref object has to map to a property.

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.