Experience Sitecore ! | More than 200 articles about the best DXP by Martin Miles

Experience Sitecore !

More than 200 articles about the best DXP by Martin Miles

Debugging and inspecting Sitecore libraries

Debugging requires symbol files to present within a bin directory along. You have Sitecore libraries, and they are not obfuscated, so you may decompile and inspect the original code using various tools like Reflector. But you need PDBs to be able to to debug those libraries, for example perform step Into, watch and modify locals, set breakpoints and similar actions.

How to generate PDB files from assembly? There is a great (and free!) tool from JetBrains called dotPeek. As soon as you download and install it, you will be able to generate PDB from any non-obfuscated assembly with it. To do that, first specify the location where PDB are kept:


Also allow to debug "not just my" code -this will allow debugger to step into methods that are stored in other referenced libraries, of course of you have their PDBs in symbols folder, as set on previous step.


Now with dotPeek we'll generate PDB under the same path previously set in Visual Studio where it will seek for symbols. Open library in dotPeek, right click its context menu and select Generate PDB, as on a screenshot below:


Remember path should be the same:


Congratulations! Now you can debug that DLL and get more understanding of how Sitecore works internally especially when sometimes you may need to override its functionally and implement your custom logic based on that.

Important! On the recent versions of Sitecore, especially Sitecore 9 or newer you may experience troubles with stepping in withing Sitecore.Kernel library. That happens due to that with time it has been more and more rewritten to rely on Sitecore.Abstractions so you will need to generate PDBs and de-optimize that one as well.

You are now able to debug the code, step into the functions and investigate the logic as the code runs. But you may not still get the entire experience as if you were debugging your own code - due to optimization. To overcome optimization you need to start Visual Studio as Administrator with setting a specific environment variable:
set COMPLUS_ZapDisable=1
cd /d "C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\Common7\IDE"
start devenv.exe
exit
Next, for each DLL you are about to explicitly disable optimisation, you need to accompany with a *.ini file having the same name and the following instructions (example for Sitecore.Kernel.ini):
[.NET Framework Debugging Control] 
GenerateTrackingInfo=1 
AllowOptimize=0
Finally, as ReSharper is your permanent friend, you'll find the most convenient way to inspect the code by using its Assembly Explorer:

Hope this helps!

How websites are resolved with Sitecore - the essentials

What actually happens when you type website URL in browser and how is your request factually served in sitecore. We are going to use www.site.com as the URL for our example. This is simplified version where only most important steps are covered.

First of all, as you hit this URL in browser's address bar, it retrieves IP address by the host name from DNS server. Then it creates request to IP address resolved with host name (www.site.com) in HTTP header. There may be multiple traffic managers / load balancers on the route to the server, but eventually request gets to that IP address to the specified port (as we use normal HTTP, then the port is default 80).

On the server computer there should be specific software running and listening to that port (80) otherwise request will fail. In our scenario, that is the Microsoft IIS web server. Below are two most important IS configuration screens:


On the first screenshot you see Site Bindings screen that binds exact website within current IIS instance to specific port and hostname (if set). There can be multiple website hosted within same IIS instance, so you we usually vary them by hostname / port combinations. The example above shows that all requests to port 80 with the hostname www.site.com would be served by current website. Second record shows that all requests to port 443 (which is default to HTTP) would be served by the same site as well.


The second screenshot assigns our website www.site.com to a folder on a disk drive which becomes a web root for our site.

Root of the website should have a configuration file called web.config, that may be split and overridden in subfolders and that itself overrides global web.config and machine.config files with default settings. Every sitecore-based website contains <sitecore> node in the configuration file, that is where all sitecore settings are defined, including <sites> node that specifies all the websites per current Sitecore instance.


Important to note that sites are determined by "first match" principle, so order is critical. If you look at our www.site.com record - you'll notice that it specifies hostname - all requests matching that name will be served by this site. Other setting set what database is used for particular site (name should match database name from connection string), what is starting sitecore tree node within that database - factual page item that is being returned. There are also html caching setting, sitecore domain name for the site, etc.

The rest of request to current Sitecore instance, that do no math our host name pattern will be served by site called "website", it does not have hostName specified, so it will serve everything else and return /sitecore/content/home item.

Let's assume the site has been published from master database to web database, as per configuration. Here's below how sitecore tree looks like in Sitecore Content Editor:


Our website's home item (selected) is called SiteCom and it will return the page with "www.site.com"in title. Let's see the browser:


Here we done. That is our www.site.com landing page loaded!


Advanced topic: How to host several sites within the same Sitecore instance without specifying a hostname, just on different ports


Sitecore Desktop usability improvements (package)

While playing with core database for some useful stuffies - I came across some improvements that can save little of my time in day-to-day activities. A screenshot below can say better than few paragraphs of text, so here it is:


It works across all the versions of Sitecore, I in fact had opportunity to test that package against 6.6 and 8.0 Update 4.


Enjoyed that and want to get for yourself?

Download the package: Sitecore Desktop Improvements-1.1.zip (47.5KB)

Previous version: Sitecore Desktop Improvements-1.0.zip (30.8KB)


SwitchMasterToWeb.config for Sitecore 8

I have just tested the one on my Sitecore 8.0 Update 4 instance - it works pretty well!

For those who has never met this config before - SwitchMasterToWeb is a configuration patch file, that aims to be placed into App_Config\Include folder on content delivery server (CD) in order to remove references to master database, that should not present there by design.



	
		
			
			
			
			
			
			
			
		
		
			
			
			
				
			
		
		
			
		
		
			
				
			
		
		
			
				
					
						
							
								
							
						
					
				
			
		
		
			
				
					
						
					
				
			
			
				
			
			
				
			
			
				core
				/sitecore/system/tasks/schedules
				true
			
			
				
			
			
				
					
						sitecore_master_index
					
				
			
			
				
			
			
				
			
		
		
			
				
					
						
					
					
						
					
					
					
						
					
					
					
						
					
					
					
						
					
					
					
						
					
					
					
						
					
					
					
						
					
				
			
			
			
				
					
						
					
					
						
					
				
			
		
		
		
			
				
			
		
		
		
			
				
					web
				
			
		
		
		
			
				
					
						
							web
						
					
					
						
							web
						
					
					
						
							web
						
					
				
			
		
		
		
			
				
					
						web
					
				
			
			
				
					
						web
						sitecore_marketing_asset_index_web
					
				
			
			
				
					
						web
					
				
			
			
				
					
						web
					
				
			
		

		
		
			web
		
	

Wildcard items ("*"-pages) with MVC, passing the correct datasources based on requested item URL

As you probably know, there is a feature in Sitecore, called "wildcard items". Let's say you have a folder where multiple subitems suppose to be and should be presented by similar pages. Sitecore allows you create a wildcard item named "*" (asterisk) so that it will serve any request to this folder. Let's take a look on example below:


Here we see clear separation of pages and data. Airports page has the only child - wildcard page item that is highlighted (and you see its details). Below, in /Data folder, there is a corresponding data sources for each of the airport.

In usual scenario, there should be a page item created for each of airports from /data folder, and page's presentation details screen should have that data items set as the datasource for corresponding rendering (yes, we are on MVC here). But how to have this working, if we have only one universal page item? We have a rendering called Airport to display airport info, but how should we specify the datasource to it?


The rendering relies on RenderingContext.Current.Rendering.DataSource as usual. And instead of datasource of specific airport, we get "*" item as the datasource in all cases, regardless of what airport's page we're loading.

I wanted to leave page's datasource and rendering untouched, as normal implementation. Instead, I decided to incline into mvc.getRenderer pipeline and resolve datasources for "*"-wildcard-items dynamically, based on the URL requested, so that rendering get corresponding data item from RenderingContext.Current.Rendering.DataSource. And of course, as "*"-items serves all possible requests to its folder, I must provide datasources only for matching data items, redirecting all the rest to 404 error page (since there's no data for the page - there's no sense in such a page).

So here's my implementation of wildcard datasource resolver:







Airport
        
      
    
  

Code referenced from configuration patch file:

    public class WildcardDatasource : GetRendererProcessor
    {
        public string RenderingName { get; set; }

        public override void Process(GetRendererArgs args)
        {
            if (args.PageContext.Item.Name == "*" && args.Rendering.RenderingItem.Name.IsSameAs(RenderingName))
            {
                string datasourceFolder = args.Rendering.DataSource.IsOK()
                    ? args.Rendering.DataSource
                    : string.Format("{0}/{1}", Paths.DataFolder.TrimEnd('/'), args.PageContext.Item.Parent.Name);

                string dataSourcePath = string.Format("{0}/{1}", datasourceFolder, 
                    args.PageContext.RequestContext.HttpContext.Request.Url.Segments.Last());

                var dataSourceItem = Sitecore.Context.Database.GetItem(dataSourcePath);
                if (dataSourceItem != null)
                {
                    args.Rendering.DataSource = dataSourcePath;
                }
                else
                {
                    // process 404 page not found
                }
            }
        }
    }


Things to improve in future:

  1. Add support for nested wildcards
  2. Find the way wildcard items work with Page Editor

Afterthoughts about Sitecore official training and certification course

I have just taken official Sitecore Developer Training and Certification in their office in London, near Tower Bridge.

In general, I did not expect the course to be so intensive. 4 days going through all aspects of working with Sitecore filled many gaps in my knowledge of platform. There were 5 of us so everyone could receive proper support and explanation while stuck with anything while studying.

Thanks to our tutor, Raul, who has heroically stood out a flurry of questions from me and gave really great insights on quite advanced topic outside of course agenda.

My advice for those who are just about to sign up for it - treat this course not as a final result by itself, but as a starting point for your individual further investigation. You will not become an expert after getting a certification, but you will be aware of most Sitecore features you need to know at that moment and how they function. Thus, do the notes, as much notes as you can. And ask as much question as you feel important to satisfy your understanding of each exact feature.

Another point I would suggest is to postpone your training if you are complete newbie in Sitecore. In that case, there is a risk you may miss something very important, especially if that becomes a prerequisite for further module. Do your own research before attending the course as much as possible - read multiple blogs, Q&A on StackOverflow etc. and ideally form the list of your own questions that you'd find answers for, while taking the course.

I personally found that very useful, so do recommend to you guys. And yes, if you are successful enough, you shortly receive a certificate like the one below but with your name, and also gain access to Sitecore developers' resources such as SDN forums and support.


So, good luck!

Sitecore.Kernel and Sitecore.MVC delivered via a NuGet library

Update (01 Aug 2015):  Here is the alternative approach answer and the solution for blog post:


I was always wondering, why Sitecore yet hasn't hosted Sitecore.Kernel and Sitecore.MVC on the NuGet?

This would have simplified our (developers') life in some way, as for today, we have to keep an additional /Libs folder and reference those 2 DLLs out of it (but couple others will serve good as well, for instance Lucene DLLs etc.). That could also simplify versioning and dependencies issues for us as soon as we still are using NuGet package management, so we now have 2 folders for references, highlighted below:


If they avoid doing that for licensing purposes - that seems quite strange as mentioned libraries are very little part of what Sitecore is, plus they may just supply obfuscated DLLs via NuGet and normal reflection-friendly via standard platform installation.

Here is what I have in my Libs folder and that I use and reference in small proof-of-concept project:


Dear Sitecore, if you read me, please consider using NuGET - today's industry standard for packaging and resolving dependencies .

Sitecore tips

1. Load Sitecore Desktop automatically and pre-select an item

I was wondering, if there is any opportunity to preload Sitecore Desktop automatically on Sitecore enter.

So annoyed of moving mouse across whole big monitor to the very top bottom, then select Content Editor from the menu, then wait till it loads an eventually as content tree loads - navigate to specific item! Even if it does not seem quite complex for a first glance - the number of times I do that per day makes me sadly thinking of wasted efforts for nothing...

Good news, everyone! There a convenient way of creating a shortcut that not only loads Content Editor, but also select any item you would like and loads its data right hand side. Here is the format of url:

http://your.host.name/sitecore/shell/Applications/Content%20Editor.aspx?fo={9CFF486B-9829-416E-8A39-408D3909B4FE}

where fo parameter stands for the item you want to pre-load.


2. If you use Google Chrome - install Chrome extensions for Sitecore


More details in my blog post by this link: Sitecore extensions for Google Chrome

Attach to IIS - debugging Sitecore with just one hotkey!

Debugging Sitecore in most cases requires you to open attach to a process menu in Visual Studio, then enable display for processes of all users, find appropriate IIS process and фееср to it. To much hassle, isn't it, especially taking into account that you may need to repeat that again and again hundreds / thousands times as a part of your work?

Ok, here's the solution to take your debugging pain off: Attach To IIS extension for Visual Studio. At the moment there are extensions for 2012 and 2013 version, as I haven't tried it in 2015 preview.





Download extensions for your Visual Studio version:

Attach_To_IIS_2012.vsix (58.6KB)

API - Useful IDisposable context switchers

Sitecore API provide several IDisposable context switchers, so I thought it's worth to review them in one place. Here they are:
  1. EditContext
  2. EventDisabler
  3. SecurityDisabler
  4. UserSwitcher
  5. LanguageSwitcher
  6. DatabaseSwitcher
  7. SiteContextSwitcher
  8. DatabaseCacheDisabler
  9. LockingDisabler
  10. LinkDisabler
1. EditContext
This is a very elegant way of editing an item in sitecore. What it does is automatically does item.Editing.BeginEdit(), item.Editing.EndEdit() as well as wraps that into try / catch block with item.Editing.CancelEdit() on Exception. You may map additional parameters into constructor to skip updating statistics (ie. last modified item's system field), suppress raising events (like item:save event) and also you may SecurityDisabler as a constructor parameter. 
// default usage
using (new EditContext(item))
{
    item.Fields["fieldname"] = "Some value to set";
}
// example of using with supressing events and avoiding statistics update
bool updateStatistics = false;  
bool silent = true;  
using (new EditContext(item, updateStatistics, silent))  
{  
    item.Fields["fieldname"] = "Some value to set";
}
// using EditContext and disable SecurityCheck together
using (new EditContext(iem, SecurityCheck.Disable))  
{  
    item.Fields["fieldname"] = "Some value to set";
}

2. EventDisabler
It gives exactly the same effect as if you were using Item.Editing.EndEdit(bool silent), passing true within silent. No events will be raised.
using (new EventDisabler())
{
    item.Editing.BeginEdit();
    // do edits
    item.Editing.EndEdit();
}

3. SecurityDisabler
Turns of permission check for operations performed within using block, regardless of if the user from the context can or cannot create / modify / move / rename /delete items. Beware as it may be insecure especially on CD instances. There is an alternative for this method - UserSwitcher (see below at 4). Here is an example of  SecurityDisabler usage:
using (new SecurityDisabler())
{
    subNode = homeItem.Add("SubNode", templateId);
    using (new EditContext(subNode))
    {
        subNode[fieldIdA] = "test";
        subNode[fieldIdB] = "testBBB";
    }
}

4. UserSwitcher
That is recommended practice (by Sitecore) to be used instead of SecurityDisabler. Everything you do is done in the context of a specific user. The user can be an Administrator and can do everything. Maybe you want to create a "service user" with only specific permissions or whatever, you can use this user to do what you want.
If you use the SecurityDisabler - Sitecore will not do any permission checks at all. In fact, the result will be the same as if you use the UserSwitcher() with an administrator, but you have no control over the context.
//User which is already created in Sitecore User Manager
 string testUser = @"sitecore\testuser"; 
if (Sitecore.Security.Accounts.User.Exists(testUser))
{
    //Getting Sitecore User Object with UserName
    Sitecore.Security.Accounts.User scUser = Sitecore.Security.Accounts.User.FromName(testUser, false); 
    //Switching Context User
     using (new Sitecore.Security.Accounts.UserSwitcher(scUser))
    {
        //Using EditContext to edit an Item
        using (new Sitecore.Data.Items.EditContext(home))
        {
            home["Text"] = "Modified Text from Code";
        }
    }
}

5. LanguageSwitcher
When working on multi-lingual website, you may have a need in retrieving the values in the language different than one you're having currently in the Context. Please consider the following code to achieve that:
var item = Sitecore.Context.Item;
using (new Sitecore.Globalization.LanguageSwitcher("fr"))
{
    item = myItem.Database.GetItem(item.ID);
}


6. DatabaseSwitcher
Sometimes you may need to do some database operations from the database
another than you currently have in Context, for instance you may have a specific task to look-up master database, or read some setting from core. Of course, such type of activities is fairly an exclusion from normal practice, so think well ahead. In any case, the following using switcher will be handy for that type of situations:
var master = Sitecore.Configuration.Factory.GetDatabase("master"))
using (new DatabaseSwitcher(master))
{
// now within this scope Sitecore.Context.Database is returning master database
}

7. SiteContextSwitcher
That one is use to substitute current site context. Usage is pretty easy:
var item = Sitecore.Context.Item;
using (new SiteContextSwitcher(SiteContextFactory.GetSiteContext("site_name_as_in_config")))
{
    // all the code here would run in the context of "site_name_as_in_config" site
}

8. DatabaseCacheDisabler
This one has become one of my favorites. When working with many items in background tasks etc., it will use the regular Items cache for fetching items, but on cache misses, it won’t put items loaded from the database into the items cache. This avoids the items cache from being polluted by for example a background task traversing multiple items. As the number of items grows in a solution, it’s important that the items being accessed by users are in the cache and aren’t outcompeted by one-time operations etc.
var item = Sitecore.Context.Item;
using(new DatabaseCacheDisabler())
{
  // your code here...
}
9. LockingDisabler
The __lock field isn’t updated also the locking events aren’t fired, so that switch effectively d
isables the item locking mechanism.

10. LinkDisabler
This is one is handy but use it with care as it disables updates of the Links Database. This may speed up item saves when doing changes to items from code that you know won’t change any links.

Hope you find this article helpful.