Sitecore on Azure PaaS – AD integration – The multiple providers service is OFF.

Since last few weeks I’ve been trying to get to the bottom of Active Directory integration with Sitecore when hosted on Microsoft Azure as PaaS. While that goal is now successfully achieved – have a read of the blog post if you already haven’t as this blog post forms a part of it.

During the process of integration and configuration of Sitecore Active Directory module, I also came across this particular message:

The multiple providers service is OFF

which resulted because during the process, configuring Activating the Switching Providers (the instructions mentioned in the Active Directory module’s guide page 10) was missed off completely in our excitement of getting this PoC working!

How did we encounter this?

Since this is Active Directory Domain integration with Sitecore CM web app has to be secure we wanted to check if the configuration and integration we have done has been properly done or not.

Moreover we were doing this for the first time and we couldn’t see the Active Directory Domain Groups or Users being exposed in Sitecore’s Role, User or Domain Managers. We did some further reading in Sitecore’s AD module guide and came across The Status Page!

The special Status Page of the AD module is a feature which allows one to troubleshoot for potential security problems and is available on the below url:

http://[yoursite]/sitecore/admin/ProviderStatus.aspx

So in our case, we tried to visit

http://sitecorevanilla.azurewebsites.net/sitecore/admin/ProviderStatus.aspx

Once the page loaded we found the message “The multiple providers service is OFF. In order to enable an option to work with multiple providers, set default Membership and Roles providers to switcher.” as shown below.

The multiple providers service is OFF

The Active Directory module’s guide (page 30) describes some high level status information about each provider:

  • If the status is ON, the provider is functioning and can serve the requests.

  • If the status is OFF, the provider has refused a simple request and the system has marked it as broken.

Coming back to problem on hand, after quick research within the web.config and Sitecore.config alongside Sitecore logs (which are now available in the Kudu console of the web app) and Application & Security logs under Windows Logs in Event Viewer on the VM (on which the Active Directory domain under test was hosted),  we discovered that the simple requests were getting refused.

Going through the configuration steps mentioned in the Active Directory module guide again was the obvious choice – to make sure that everything has been understood, followed and implemented correctly!

The finding was that we had missed out on Activating the Switching Providers:

  • Basically in web.config file, in <system.web> section, search for <membership> element, find the provider called sitecore and set its realProviderName attribute to switcher.
    <membership defaultProvider="switcher" hashAlgorithmType="SHA1">
  • Same way within <system.web> section, search for <roleManager> element, find the provider inside called sitecore and set its realProviderName attribute to switcher.
    <roleManager defaultProvider="switcher" enabled="true">

    Refer page 10 of the Active Directory module’s guide for more details.

Finally, after making these config changes, restarting the Sitecore CM web app we saw the screen that was expected

Verify the status of security providers

Hope this helps my fellow Sitecorians in the world of Azure!

Happy Sitecoring!

Reference Materials:

Advertisements

Sitecore on Azure PaaS – AD integration – Login attempt leads to application crash when SitecoreADMembershipProvider is configured

Since last few weeks I’ve been trying to get to the bottom of Active Directory integration with Sitecore when hosted on Microsoft Azure as PaaS. While that goal is now successfully achieved – have a read of the blog post if you already haven’t as this blog post forms a part of it.

During the process I also came across this particular error and the attempt to login, lead the Sitecore CMS web app to crash!

So one would think that, since we have followed all the instructions mentioned in the Active Directory module’s guide to the dot (during the process of getting Sitecore AD module working with Sitecore 8.2 update 2 on Azure), we will be able to login into Sitecore CMS and check if the Active Directory Domain’s Groups and Users are visible or not in Sitecore’s Role Manager and User Manager. But (there is always a but), we were in for a surprise – Login attempt leads to Sitecore CM web app to crash!

Sitecore CMS Web App crashes

After our friend Google helping me out, we discovered that Sitecore Support Team have already got a fix for it – Sitecore.Support.139945 which describes “Login attempt leads to application crash when SitecoreADMembershipProvider is configured”.

Which made sense in our case as we had configured the Sitecore AD Membership Provider. We followed the instructions (mentioned on SitecoreSupport GitHub):

For all Sitecore instances in the solution:

  1. Make a backup of the bin/Sitecore.Support.139945.dll if that already exist in Website folder.
  2. Download and extract the Sitecore.Support.139945-1.3.0.0.zip archive to the Website folder, overwrite existing files if there are any and any conflicts occur.
  3. Find the <membership> section in the Web.config file and replace

    <add name=”switcher” type=”Sitecore.Security.SwitchingMembershipProvider, Sitecore.Kernel” applicationName=”sitecore” mappings=”switchingProviders/membership” />

    with

    <add name=”switcher” type=”Sitecore.Support.Security.SwitchingMembershipProvider, Sitecore.Support.139945” applicationName=”sitecore” mappings=”switchingProviders/membership” />

After the Sitecore CM web app restarted, it just worked fine and we could login.

“A big thank you to Sitecore Support Team and request to Sitecore Documentation’s team to update Active Directory 1.3 module guide, Installation package for Active Directory 1.3 rev. 161017 and Active Directory 1.3 module’s Known Issues page with this information if this error is going to occur for anyone configuring the SitecoreADMembershipProvider.”

On successful login, I was now able to verify the Active Directory Domain Groups, Users and Domain that were visible in Sitecore’s Role, User and Domain Managers.

Hope this helps my fellow Sitecorians in the world of Azure!

Happy Sitecoring!

Reference Materials:

Active Directory integration with Sitecore on Azure PaaS

On a recent project we came across the key requirement of Single Sign-On (SSO) for the Sitecore 8.2 Update 2 PaaS implementation on Microsoft’s Azure. The integration of client’s Active Directory (AD) domain with a Sitecore 8.2 Update 2 was a challenge because:

  1. Sitecore XP on Microsoft Azure Compatibility Table explicitly states that Active Directory (Component or Module) is not supported.
  2. Azure VNET Integration with Azure web app does not support Active Directory integration as mentioned in Azure Web Apps documentation

The matter was more interesting because:

  1. Neither Sitecore had a clarification on their website on an Azure web app (Sitecore PaaS CM) integration with Active Directory or Azure Active Directory; well they had that it is not supported but what is the work around.
  2. And neither Microsoft had mentioned on their website in Azure Web Apps documentation that, AD integration is fully not supported or partially not supported and / or what part of AD is incompatible with Azure Web Apps.

Hence the need for a Proof of Concept (PoC) arose, along with checking with our Sitecore and Microsoft counterparts about their official stance on support if our PoC worked.

Creating Microsoft Active Directory domain in Azure

  1. First Sitecore XP 8.2 Update 2 was spun up in Azure.
    Sitecore Azure Resources
  2. We created the following:
    • Virtual network (VNET)
    • Subnets (Gateway, Web management)
    • VNET Gateway in the GatewaySubnet
    • Allocate  point-to-site address pool that is outside of VNET range and
    • Virtual machine (VM)
      in the same Azure Resource Group as Sitecore XP resources.
      VNET VM Azure Resources
      Azure VNET VPN Gateway Configuration for Web App VNET Integration
  3. How is all it wired?
    VN-PAAS-Sitecore is the virtual network (VNET) that connects to the Sitecorevanilla Azure Web App. In the below image under the Networking section of Sitecorevanilla web app, VNET Integration shows Connected to VN-PAAS-Sitecore VNET.
    VNET Web App Connectivity
  4. VN-PAAS-Sitecore VNET has two connected devices in it – a virtual network gateway (VPN- -VN-PAAS-Sitecore) and network interface (nic-M 1-C-SCOD)
    VNET Devices
  5. Network Interface (nic-M 1-C-SCOD) is attached to Virtual Machine (M 1-C-SCOD) that hosts the Active Directory on it.
    NIC 2 VM Connectivity
  6. Active Directory that we configured for this PoC looks something along these lines which shows the virtual machine (M 1-C-SCOD)
    Domain Controller
  7. The Organisational Unit (OU) called sitecore that we created in the AD and the groups that were assigned to that sitecore OU.
    Sitecore OU Related Groups in AD
  8. Last but not the least, Joe Bloggs our AD user we will use to test the successful login into Sitecore.
    Joe Bloggs User in AD
  9. This user belongs to TestDomainLocalGroup AD Group.
    Joe Bloggs AD Group

Integrating Microsoft Active Directory domain in Sitecore Content Management (CM) Azure Web App

  1. For integrating the AD domain in Sitecore, the obvious choice was Sitecore’s Active Directory Module 1.3, specially prepared for Sitecore XP 8.2.

    The Sitecore XP Active Directory module provides the integration of a Microsoft Active Directory domain with a Sitecore XP solution. You can integrate domain users and groups available into Sitecore XP as Sitecore users and Sitecore roles immediately after the module installation and configuration. Moreover, user profiles can be easily extended with custom properties from Active Directory.

  2. We downloaded the module from here and the guide on how to install, configure, and use of the Active Directory module.
  3. For the purpose of our PoC we focused on the Chapter 2 (pages 5 to 11) of the guide.
  4. We first installed the Sitecore Active Directory component 1.3 rev. 161017.zip module using the Installation Wizard.
    Sitecore Active Directory Module 1.3 Installation
  5. Once successful installation of the module was done we modified the following files as per the guide:
    • Modified the /App_Config/ConnectionStrings.config file to add a Connection String to the Active Directory Domain.
      We added the following just before the </connectionStrings> tag.

      <add name="ManagersConnString" connectionString="LDAP://1xx.1x.1x.1xx:389/DC=companyADdomain,DC=company,DC=com" />

      One can also specify Organisational Unit (OU), as shown below, within this string but it will restrict user visibility – so be aware!

       <add name="ManagersConnString" connectionString="LDAP://1xx.1x.1x.1xx:389/OU=sitecore,DC=companyADdomain,DC=company,DC=com" />

      Refer page 5 & 6 of the guide it has very interesting details.

    • Modified the /App_Config/Security/Domains.config.xml file for adding a New Domain.
      We added

       <domain name="ad" ensureAnonymousUser="false"/>

      just before

       <domain name="extranet" />
    • Penultimate but important set of changes to the web.config file for Configuring the ASP.NET Security Providers – Membership, Role and Profile (Optional), including the Activating of Switching Providers.

    • Configuring Membership Provider:
      We searched for the <membership> element in the <system.web> section and added the following code (remember the order is not important)

       <add name="ad"
       type="LightLDAP.SitecoreADMembershipProvider"
       connectionStringName="ManagersConnString"
       applicationName="sitecore"
       minRequiredPasswordLength="1"
       minRequiredNonalphanumericCharacters="0"
       requiresQuestionAndAnswer="false"
       requiresUniqueEmail="false"
       connectionUsername="[put the user here]"
       connectionPassword="[put the password here]"
       connectionProtection="Secure"
       attributeMapUsername="sAMAccountName"
       enableSearchMethods="true" />

      Including the connectionProtection attribute set to Secure requires that we add one more element to the <system.web> section – Machine key attributes:

       <!-- Machine key attributes -->
      <machineKey
      validationKey="BDDFE367CD36AAA81E195761BEFB073839549FF7B8E34E42C0DEA4600851B0065856B211719ADEFC76F3F3A556BC61A5FC8C9F28F958CB1D3BD8EF9518143DB6"
      decryptionKey="0DAC68D020B8193DF0FCEE1BAF7A07B4B0D40DCD3E5BA90D" validation="SHA1" />
      

      Refer page 7, 8 & 9 of the guide for more details.

       

    • Configuring Role Provider:
      We searched for the <roleManager> element in the <system.web> section and added the following code (remember the order is not important)

       <add name="ad" type="LightLDAP.SitecoreADRoleProvider"
            connectionStringName="ManagersConnString"
            applicationName="sitecore" 
            username="[put the user here]"
            password="[put the password here]"
            attributeMapUsername="sAMAccountName" 
            cacheSize="12MB" />

      Refer page 9 of the guide for more details.
      Note: We gave a slightly larger cache size than the default 2MB.

    • Configuring the Profile Provider:
      Since it was optional so we left it out.
    • Activating the Switching Providers:
      • Note: This was the step which was missed off completely in our excitement of getting this PoC working! We encountered a road/block due to this for which I have written this blog post which might be useful if you see the below message on the Provider Status Page.
        The multiple providers service is OFF
      • Basically in web.config file, in <system.web> section, search for <membership> element, find the provider called sitecore and set its realProviderName attribute to switcher.
        <membership defaultProvider="switcher" hashAlgorithmType="SHA1">
      • Same way within <system.web> section, search for <roleManager> element, find the provider inside called sitecore and set its realProviderName attribute to switcher.
        <roleManager defaultProvider="switcher" enabled="true">

        Refer page 10 of the guide for more details.

      • Final changes to the /App_Config/Sitecore.config file for Adding the Domain-Provider Mappings.Adding the Domain-Provider Mappings:
        Search for the <switchingProviders> element in Sitecore.config, it contains three groups: <membership>, <roleManager> and <profile>. We added the following line of code to all the three groups  (remember  the order is not important)

        <provider providerName="ad" storeFullNames="false" wildcard="*" domains="ad" />

        So the  section will look as below:

        <!-- SWITCHING PROVIDERS -->
        <switchingProviders>
             <membership>
                  <provider providerName="sql" storeFullNames="true" wildcard="%" domains="*" />
                  <provider providerName="ad" storeFullNames="false" wildcard="*" domains="ad" />
             </membership>
             <roleManager>
                  <provider providerName="sql" storeFullNames="true" wildcard="%" domains="*" ignoredUserDomains="" allowedUserDomains="" />
                  <provider providerName="ad" storeFullNames="false" wildcard="*" domains="ad" />
             </roleManager>
             <profile>
                  <provider providerName="ad" storeFullNames="false" wildcard="*" domains="ad" />
                  <provider providerName="sql" storeFullNames="true" wildcard="%" domains="*" ignoredDomains="" />
             </profile>
        </switchingProviders>

        Refer page 10 of the guide for more details.

Check if Active Directory Groups and Users are visible

So now one would think that, since we have followed all the instructions mentioned in the Active Directory module’s guide to the dot, we will be able to check if the AD Domain’s Groups and Users are visible or not, but (there is always a but), we were faced an error – Login attempt leads to Sitecore CM web app to crash! I have written a blog post about it.

Once we resolved the error and on successful login, we were now able to verify the Active Directory Domain Groups, Users and Domain that were visible in Sitecore’s Role, User and Domain Managers.

Domain Manager
With our custom domain “ad”. Domain Manager

Role Manager
With our test AD Groups as Sitecore Roles – TestGlobalGroup, TestDomainLocalGroup and TestUniversalGroup and including few other groups. Role Manager

User Manager
With our test AD User as Sitecore User – Joe Bloggs and including few other users. User Manager.png The AD Domain, Groups & Users visible and confirmed as Sitecore Domain, Role and Users we moved on to configuring these so that our AD User Joe Bloggs can login to Sitecore.

Configure Active Directory Groups to Sitecore Roles in Sitecore Roles Manager

Now this is slightly complicated but let me try and explain visually first

Sitecore Roles
    sitecore\Sitecore Client Author
      + sitecore\List Manager Editors (Role)
      + ad\TestDomainLocalGroup (AD Group now as a Role)
      + sitecore\Author (Role)

Active Directory Groups
    ad\TestDomainLocalGroup
      + ad\joebloggs
    ad\TestGlobalGroup
    ad\TestUniversalGroup

The Sitecore Role that we are testing is sitecore\Sitecore Client Author which has the necessary content authoring permissions that we want for our AD user Joe Bloggs to have.

AD user, Joe Bloggs is part of the ad\TestDomainLocalGroup group within the AD and Sitecore. This ad\TestDomainLocalGroup group has been added as a member of sitecore\Sitecore Client Author role. AD User ad\joebloggs is a member of ad\TestDomainLocalGroup group within the AD.

AD Group Member of Sitecore Role.png

And now the final piece in the jigsaw, to test if AD User ad\joebloggs can login to Sitecore or not?

Joe Bloggs Sitecore LoginJoe Bloggs Sitecore Launch Pad and Content Editor

Sitecore Logs Diagnostic Console

As you can see from the above images our AD user ad\joebloggs can successfully login to Sitecore CMS and access the areas to which we have given permissions.

Appreciate this is a very long blog post but wanted to share this PoC for Sitecore Azure PaaS implementation with Active Directory. Special thanks to Vijay Thakorlal for being partner in crime.

Hope this helps my fellow Sitecorians in the world of Azure!

Happy Sitecoring!

Reference Materials:

SyntaxError: Unexpected token ) – Gulp Tasks not working for Sitecore Habitat

Sitecore Habitat using Helix principles is the new approach of developing Sitecore based solutions and even though we were a bit sceptical in developing this for a client we took the leap of faith.

After exploring & understanding the concept and watching a few videos (listed below), the team felt confident, found Habitat to be a logical and easy approach to develop a Sitecore solution.

Team started making good progress and I joined the team around sprint 5. Even though we were a bit optimistic on setting up our Habitat solution on my new development machine, we failed in the first go!

  • Sitecore code repository was pulled fine and configured locally.
  • Sitecore 8.2 Update 2 vanilla instance was setup and running!
  • Visual Studio Solution file opened up fine with building a solution working.

Issue was the Gulpfile.js failed to load in the Task Runner Explorer

Gulp Task Runner Sitecore Habitat I

The obvious, we started troubleshooting to resolve this issue; we tried:

  • Comparing the repository folders and paths
  • The content of files like gulp-config.js, gulpfile-ci.js and gulpfile.js files just to make sure we haven’t changed things.
  • Have I followed the Sitecore Habitat prerequisites and have the necessary resources on the development machine ?
  • Made sure that Visual Studio is running As Administrator. (I know it sounds like an obvious one but can get you!)
  • Asked our friend Google for solution and came across various blog posts to resolve but no joy!
  • Finally I decided to scrap what I had installed and make a fresh start. My colleague D who was helping me agreed and we configured the setup same as on his machine.

We had success – the list of Gulp Tasks was nicely visible in the Task Runner Explorer window!

Gulp Task Runner Sitecore Habitat II

By the way don’t feel that there wasn’t a ReadMe.md for the project setup, there was but still didn’t help.

On a side note, if you don’t know what is Gulp, this should help and here is how you get started on it.

The solution set, I was eager to run the gulp tasks to deploy the assets and the code to my local Sitecore setup. And as one would go, selected the default task -> right click -> Run. To my dismay we encountered another issue !!!!!

SyntaxError: Unexpected token )

Gulp Task Runner Sitecore Habitat III

Colleague S from the team came to rescue when I and colleague D had given up for the afternoon after investing so much time to resolve this. His investigation approach was similar, checking the same things that we did earlier, but with a slight twist.

  • We went on the Node command prompt and tried to execute commands from there. Still found that the same error was being encountered
  • We re-installed Node.js v6.10.0 LTS for Windows (x64)
  • Made sure that the environment variables and/or any other settings are not the cause of this issue – but still no joy!

Finally colleague S had an epiphany!

He goes let’s check what Node version is Visual Studio set to use. Well for those who don’t know Visual Studio ships with node.js Tools for Visual Studio (NTVS) which runs inside Visual Studio.

In VS2015’s Menu – Tools -> Options -> Projects and Solutions -> External Web Tools one would find .\node_modules\.bin as default settings

Gulp Task Runner Sitecore Habitat IV.png

We added a new location; the location where I had install the latest version of Node.js and moved it to the top of the order as shown below.

Gulp Task Runner Sitecore Habitat V.png

Saved it ran the “default“task from the list of Gulp tasks and Voilà!

The code and the assets got published and I was able to browse our Sitecore solution locally on my development machine. Thanks to my colleague S and D for helping me out.

Even though this is a little setting and but it is a gotcha which caused a blocker for a few hours. Hope this post comes as a solution to my fellow Sitecorians who are embarking on the Sitecore Habitat journey!

Happy Sitecoring !

Sitecore Unit Testing is not a Success or is IT ?

On November 28, 2013 I came across this question on StackOverflow – Sitecore Unit Testing is not a success? Luckily I could answer it and provide information to the user dpwulp94 but on the first read I was astonished that we as developers do give up unless there is some motivation or solution for the problems we face. My effort for this blog post is to encourage people to break through the barriers of limitations provided by the initial version of any application. Make the effective changes not only in frameworks but also in the attitude and approach of the common problems faced by Sitecore community developers.


Sitecore Unit Testing is not a success or is it ? dilbert-quality “Unit Testing is always useful for anything that is written in C# (or should I say in OO Language)” is what I said on the post but now the front end frameworks are also rapidly changing for the ability to write tests around it. dpwulp94 was implying that after a good amount of research he was planning to give up (“Should we give up or can we get it working and in what way?”), but giving up for the time being and revisiting it with a fresh approach is the key with testing. All I could suggest again is watching

  1. Another interesting video by codeflood.
  2. Automated Testing with Sitecore V2 video by Alistair Deneys from Hedgehog

and read Alistair Deneys’ blog post Unit Testing in Sitecore is not Scary There are also more Unit Testing videos mentioned in Unit Testing Sitecore using NUnit, serializing content blog post if you want more information on how to do Unit Testing in Sitecore.  Coming back to the StackOverflow answer, I also mentioned that “I can gauge the blockage that you are facing. But have a read of Testing Strategies – Opinionated Advice by Kevin Obee.” Sometimes while doing Unit Testing we loose the focus of being pragmatic and just follow the Unit Testing Principles. Confessing in the answer that “I faced that and establishing the balance would be the key. In no way I am suggesting that you might have gone in this direction, but just suggesting that sometimes taking a step back, reflecting on what we ACTUALLY want to TEST and restarting helps a lot.” After reading through the answer a positive comment by dpwulp94 was “The article of Unit Testing in Sitecore is not scary seems great. But it would be nice if there are some people on StackOverFlow who encountered the same problem, writen above. And (of course) how that was being solved” To this I would completely agree and would like open source isolation testing framework for Sitecore like Sitecore.FakeDb gain more light. If this interests you check out this video by Pavel Veller from BrainJocks Keep open source projects coming and let’s make Sitecore Testing better by the day. Happy Sitecoring !

Use Name Value List field type, it’s there for a reason

Couple of months ago, I came across a solution that was put in place in Sitecore to have Name – Value pairs or Key – Value pairs for calculation purpose. But the data template’s field names were used as Key and the content editor would enter in the Value. This seemed wrong at that time but I could not think of an apt change to make that solution better and simpler. Recently, while learning about Sitecore fields and field types on my SND course I came across the field type – Name Value List, Straight away I thought, the solution that I had seen a couple of months back could benefit from this field type and could be done a lot better.

The solution that was put into place was just seemed bit odd and have shown it below.

1. A template with a list of fields was created which were the Names, like if one is trying to create a Name – Value or a Key – Value Paired list.

2. The image shows the template created.

Sitecore Data Template

Sitecore Data Template

3. The final template was then inherited from the above template. Showing the inheritance in the below image.

Sitecore Data Template Inheritance

Sitecore Data Template Inheritance

4. The item created from this template was filled out my the content editor. Filled values shown below.

Item created using Template

Item created using Template

By now we get the picture of what is going on and how much maintenance overhead this can be.

Applying the knowledge that I learnt at the SND course, seemed the right way to correct this odd solution. The data template should be modified by changing the field type to Name Value List.

Correct Template

An Item based on this template should be created. Below image shows how the content data should be stored in a Name Value List field type.

Name Value List in Sitecore

Correct way to implement Name Value List in Sitecore

The raw value of Name Value List is stored in a url string format – value_1=20.5&value_2=21.5&value_3=22.5&value_4=23.5&value_5=24.5.

There is no Sitecore web control for this field type.

Lastly the use of Sitecore.Web.WebUtil class comes in handy.

private void FetchNameValueList(Item item)
        { 
            string _urlParamsToParse = item["NameValueListFieldName"];
            NameValueCollection nameValueCollection = Sitecore.Web.WebUtil.ParseUrlParameters(_urlParamsToParse);

            foreach(var nv in nameValueCollection)  
            {
                // Do Stuff
            }
        }

Enumerate through the keys to retrieve the values from the field.

Hope this post gives a better understanding of Name Value List field type and helps implement better and simple solutions.

Thanks to Jason who taught me the recent SND course at Sitecore that inspired me.

Finding specific renderings using sitecore query

Recently I was helping a content editor by moving items in the content tree. We successfully move almost all items apart from a couple. These were advert items which referenced on various pages within the renderings using data source. Hence referenced as path and not the Sitecore Item Guid. Some moving them would break the links and we didn’t know on which pages these were referenced.

We did a search using Sitecore Rocks but the way these were referenced and the current version of Rocks didn’t support path searching. We were bit clueless. One of my fellow developers suggested writing a bit of Sitecore Query to get what we were after.

We wrote something like

select @@id, @@name, @__Renderings from /sitecore/content/home//*[contains(@__Renderings,’ds=”/sitecore/content/home/caring/apply for job”‘)];

This helped us find a specific type of renderings which referenced using data-source and they were placed within specific sublayouts.