I want to disable the html cache for 1 item so it is always rendered.
Background:
I need to show information for companies stored in a separate database. In sitecore I have 1 item which has the user control that shows the required information and depending on a Context parameter I figure out which company to show.
The sitecore tree look like this:
/sitecore
/content
/home
/company-information
The url is: /show-company-information/[company-name]-[company-id]. I have a pipeline module that parses the url and sets the company information as the current item and adds the company id to HttpContext.Current.Items. That's how my user control figures out which company information to render.
It all works fine in development but once you deploy it to a Content Delivery server it stops working correctly. The first time the page is accessed it gets cached and every consecutive request returns the company information that was cached the first time.
My current workaround is to clear the HTML cache for the company-info item in the same pipeline step that parses the company-information but it seems a really dirty solution.
Is there a better way to achieve the same result?
EDIT
Here is how the site is setup in web.config and also the web database configuration:
<site name="website" virtualFolder="/" physicalFolder="/" rootPath="/sitecore/content/Home/" startItem="/home" language="en-GB" database="web" domain="extranet" loginPage="/user-login.aspx" allowDebug="true" cacheHtml="true" htmlCacheSize="400MB" registryCacheSize="500KB" viewStateCacheSize="500KB" xslCacheSize="20MB" filteredItemsCacheSize="20MB" enablePreview="true" enableWebEdit="true" enableDebugger="true" disableClientData="false" />
<!-- CACHE SIZES -->
<cacheSizes>
<sites>
<website>
<html>500MB</html>
<registry>500KB</registry>
<viewState>500KB</viewState>
<xsl>200MB</xsl>
</website>
</sites>
</cacheSizes>
<database id="web" singleInstance="true" type="Sitecore.Data.Database, Sitecore.Kernel">
<param desc="name">$(id)</param>
<icon>Network/16x16/earth.png</icon>
<securityEnabled>true</securityEnabled>
<dataProviders hint="list:AddDataProvider">
<dataProvider ref="dataProviders/main" param1="$(id)">
<disableGroup>publishing</disableGroup>
<prefetch hint="raw:AddPrefetch">
<sc.include file="/App_Config/Prefetch/Common.config" />
<sc.include file="/App_Config/Prefetch/Web.config" />
</prefetch>
</dataProvider>
</dataProviders>
<indexes hint="list:AddIndex">
<index path="indexes/index[#id='articleIndex']" />
</indexes>
<proxiesEnabled>false</proxiesEnabled>
<proxyDataProvider ref="proxyDataProviders/main" param1="$(id)" />
<archives hint="raw:AddArchive">
<archive name="archive" />
<archive name="recyclebin" />
</archives>
<Engines.HistoryEngine.Storage>
<obj type="Sitecore.Data.$(database).$(database)HistoryStorage, Sitecore.Kernel">
<param connectionStringName="$(id)" />
<EntryLifeTime>30.00:00:00</EntryLifeTime>
</obj>
</Engines.HistoryEngine.Storage>
<cacheSizes hint="setting">
<data>400MB</data>
<items>400MB</items>
<paths>10MB</paths>
<standardValues>1MB</standardValues>
</cacheSizes>
</database>
</databases>
Page layouts structure:
layout - no output caching
- sublayout - no caching options ticked
- offending sublayout - no caching options ticked
Are we doing anything wrong for this to be cached so aggressively?
You can use the CacheManager to turn off caching during the Page Load event then turn it back on in PreRender. This will ensure that the page's html / xslt controls are not cached.
The CacheManager Class has the following method used by all controls when retrieving HTML caches
/// <summary>
/// Gets the HTML cache.
/// </summary>
/// <param name="site">The site.</param>
/// <returns>The HTML cache.</returns>
public static HtmlCache GetHtmlCache(SiteContext site)
{
if (_enabled && (site != null))
{
return site.Caches.HtmlCache;
}
return null;
}
So setting the Enabled Property to false will stop the controls being rendered from the cache:
CacheManager.Enabled = false;
Its brutal but it works.
If your HTML is being cached, its from a specific rendering, e.g. a specific sublayout. If you have a sublayout set to cache and vary by anything in Layout Details, undo that. Or, you may be doing it in code, in which case you can change your C# to not cache it.
Here's a sublayout in code that is set to cache, you may have something like this that you'd want to not cache:
<sc:Sublayout Path="~/layouts/sublayouts/mycontrol.ascx" Cacheable="true" runat="server" />
If this cache problem is cleared by just publishing any sitecore item, then its safe to assume its the sitecore HTML cache.
Any layout or sublayout with caching enabled will also cache the output any control added within it. So if any parent sublayout of this control or rendering has caching enabled you'll need to disable it.
An easy way to view the cache settings for your page is via the debugger [Start] > [Debug]
Hovering over the controls will allow you to view their resultant cache settings.
If your item is a sublayout, you can disable its rendering cache in the page editor component properties or through the definition of the sublayout item in the Cache section.
For example, I have a search results sublayout with cache disabled.
Related
I have built a sitecore site in my dev PC and published it. (From master to web database).
How can I browse the site as an anonymous user.
Say, if i browse the url mysite/pages/about, it loads the page but within the sitecore shell. (and also, I need to be logged in)
I would like to see it, as if it went live. Is this possible.
Since you are still logged into Sitecore by default it will use those credentials to load the page in "Edit Mode".
Use a different browser or open a tab in incognito/private browsing mode.
Alternatively, in Experience Explorer from the Home Ribbon section select "Close" or append ?sc_mode=normal to the URL of the page.
There is a cookie named website#sc_mode which will also be set to Edit when you are in Experience Editor, which remembers your last selection. You could also try removing this as well as the other Sitecore cookies.
There has to be a SiteDefinion.config file in the App_Config/Include folder, which is not avilable by default.
Lets say, the sitecore instance name is democore and you have to develop a website - mysite.
And your content tree may be structured as :
Sitecore > Content > MySite > (home, about, contact etc)
This config file will have the following configuration
<configuration xmlns:patch="www.sitecore.net/.../">
<sitecore>
<sites>
<site patch:before="*[#name='website']"
name="/"
hostname="democore"
virtualfolder="/"
physicalfolder="/"
rootpath="/sitecore/content/"
mediapath="/sitecore/media library/mysite/"
startitem="/home"
loginpage="/login"
database="web"
domain="extranet"
allowdebug="false"
cachehtml="false"
htmlcachesize="10MB"
registrycachesize="0"
viewstatecachesize="0"
xslcachesize="5MB"
filtereditemscachesize="2MB"
enablepreview="true"
enablewebedit="true"
enabledebugger="false"
disableclientdata="false"
language="en"
usedisplayname="true"
embedlanguage="false"
embedlanguageinmedia="true"
routesitename="mysite" />
</sites>
</sitecore>
</configuration>
You can now browse the site as democore/mysite/home
I have Sitecore 6.6 installed. I wanted to add a new domain to Sitecore; Since my Sitecore instance is deployed in two servers with two Sitecore sites in each pointing to different web databases but same core, master and analytics databases, I couldn't do it using Sitecore Domain manager.So I thought of doing it manually by editting the App_Config\Security\domains.config in the server. The following was the domains.config that I had.
<?xml version="1.0" encoding="utf-8"?>
<domains xmlns:sc="Sitecore">
<domain name="sitecore" ensureAnonymousUser="false" />
<domain name="extranet" defaultProfileItemId="{AE4C4969-5B7E-4B4E-9042-B2D8701CE214}" />
<domain name="default" isDefault="true" />
<sc:templates>
<domain type="Sitecore.Security.Domains.Domain, Sitecore.Kernel">
<ensureAnonymousUser>true</ensureAnonymousUser>
<locallyManaged>false</locallyManaged>
</domain>
</sc:templates>
<domain name="Station" defaultProfileItemId="{F181ED3D-F342-46E6-B6F6-2A6A6173B513}" />
<domain name="Emailcampaign" />
</domains>
I added one more domain(MyDomain) at the end like below.
<?xml version="1.0" encoding="utf-8"?>
<domains xmlns:sc="Sitecore">
<domain name="sitecore" ensureAnonymousUser="false" />
<domain name="extranet" defaultProfileItemId="{AE4C4969-5B7E-4B4E-9042-B2D8701CE214}" />
<domain name="default" isDefault="true" />
<sc:templates>
<domain type="Sitecore.Security.Domains.Domain, Sitecore.Kernel">
<ensureAnonymousUser>true</ensureAnonymousUser>
<locallyManaged>false</locallyManaged>
</domain>
</sc:templates>
<domain name="Station" defaultProfileItemId="{F181ED3D-F342-46E6-B6F6-2A6A6173B513}" />
<domain name="Emailcampaign" />
<domain name="MyDomain" />
</domains>
As soon as I did that, Sitecore.Context.User.IsAuthenticated started returning true for extranet\Anonymous user(Non-logged in user) in the code.
Has anyone faced this issue before?
Please let me know where am I going wrong.
I also encounted this issue back when I was working with Sitecore 6.6, I'm not certain if its an issue in later versions. Essentially when you modified your domains.config with the param ensureAnonymousUser set to true the Anonymous User for that domain, in this case Extranet, was created in the database - it may not have been until you changed that setting.
In Sitecore all non-logged in users view the site as the user *domain*/anonymous. As Sitecore's membership is based on .NET Membership it determines that the User is logged in as its using that account.
Therefore I recommend completing an additional check with your Sitecore.Context.User.IsAuthenticated to check if the username of User's account is *domain of site*/anonymous, Sitecore.Context.User.Name, if it is return false.
EDIT
I have confirmed Sitecore.Context.User.IsAuthenticated returning true for *domain*\Anonymous user has been fixed in Sitecore 8. Therefore you can use it to determine if the User is logged in and not using the *domain*\anonymous account.
We finally resolved this issue! This was caused by a fix we added to solve an issue we had with Sitecore ECM. The issue was that Sitecore used to log out as soon as we clicked on the message preview. So we followed the steps given in the below thread to fix the issue.
https://stackoverflow.com/a/30836600/4165670
But we were not testing for Anonymous user like it is done in the thread. We never pushed this code into Content Delivery site and when
we created the new domain, This code got pushed into the Content Delivery site with some other code.
Since we are setting the current user as the Active user in the code, it started showing that extranet\Anonymous user as the current user.
I need to get a specific item based on it's displayname, how do I do that?
For example I want to get this item /sitecore/content/mysite/about
But on the site is translated to multiple languages and could be something like www.site.com/om (in Sitecore it would be /sitecore/content/mysite/om)
There are a couple approaches you can take. The most efficent is to leverage the Content Search API, but the challenge is that Display Name is excluded from the index by default. A simple patch file can fix this:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<indexConfigurations>
<defaultLuceneIndexConfiguration>
<exclude>
<__display_name>
<patch:delete />
</__display_name>
</exclude>
</defaultLuceneIndexConfiguration>
</indexConfigurations>
</contentSearch>
</sitecore>
</configuration>
Then your code would be something like:
public Item GetItemByDisplayName(string displayName)
{
var searchIndex = ContentSearchManager.GetIndex("sitecore_master_index"); // sub your index name
using (var context = searchIndex.CreateSearchContext())
{
var searchResultItems =
context.GetQueryable<SearchResultItem>().Where(i => i["Display Name"].Equals(displayName)).FirstOrDefault();
return searchResultItems == null ? null : searchResultItems.GetItem();
}
}
This all is assuming you are on Sitecore 7. If you're on Sitecore 6, your option are limited and are probably not going to perform well if you content tree is large. Nonetheless, your function might look like:
public Item GetItemByDisplayName(string displayName)
{
var query = string.Format("fast:/sitecore/content//*[#__Display Name='{0}']", displayName);
var item = Sitecore.Context.Database.SelectSingleItem(query);
return item;
}
Please note that this will be horribly inefficent since under the covers this is basically walking the content tree.
Often, you wouldn't need to. LinkManager (responsible for generating all your item URLs) has an option to base the URLs on Display Name instead of Item.Name.
var d = LinkManager.GetDefaultUrlOptions();
d.UseDisplayName = true;
This can also be configured in configuration. Find and amend this section in your Web.config (or patch it via include files):
<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel"
addAspxExtension="false" alwaysIncludeServerUrl="false" encodeNames="true"
languageEmbedding="never" languageLocation="filePath" lowercaseUrls="true"
shortenUrls="true" useDisplayName="false" />
</providers>
</linkManager>
To truly do exactly what you ask is a quite involved process. If you point DotPeek to Sitecore.Pipelines.HttpRequest.ItemResolver, you can step through the ResolveUsingDisplayName() method. It essentially loops through child items, comparing the URL Part to the "__Display Name" field. You would have to cook up something similar.
I'm currently setting up a search for a Sitecore 6.6 web site using SitecoreSearchContrib.
I've got two indexes.
One index looking at my web site content:
/sitecore/content/home
and another index looking in a documents folder in the media library (which contains PDF etc).
/sitecore/media library/documents
The search on my web site can return web pages or Word/PDF documents.
Is there a way (beside using one super-index for content & media library) that I can combine the results from both indexes and still order them by their relevance / hit count?
Ended up solving this by getting rid of the second index and instead, simply included an additional <locations>...</locations> block in the scSearchContrib.Crawler.config to point to the folder in the media library where my documents live.
E.g.
Inside of App_Config/Include/scSearchContrib.Crawler.config
......
<index id="web" type="Sitecore.Search.Index, Sitecore.Kernel">
<param desc="name">$(id)</param>
<param desc="folder">web</param>
<Analyzer ref="search/analyzer" />
<locations hint="list:AddCrawler">
<my-site-content type="scSearchContrib.Crawler.Crawlers.AdvancedDatabaseCrawler,scSearchContrib.Crawler">
<Database>web</Database>
<Root>/sitecore/content/MySite/Home</Root>
<tags>Web Content</tags>
<IndexAllFields>true</IndexAllFields>
<!-- Include/Exclude templates, crawlers etc here -->
</locations>
<locations hint="list:AddCrawler">
<my-site-media-library type="scSearchContrib.Crawler.Crawlers.AdvancedDatabaseCrawler,scSearchContrib.Crawler">
<Database>web</Database>
<Root>/sitecore/media library/SomeFolder/Documents</Root>
<tags>Documents</tags>
<IndexAllFields>true</IndexAllFields>
<!-- Include/Exclude templates, crawlers etc here -->
</locations>
</index>
......
I have a site in sitecore at domain1.com
<site rootPath="/sitecore/content" startItem="/home" .. />
I want to create a second site at domain2.com that uses same items
<site rootPath="/sitecore/content" startItem="/home" ... />
Both sites refer to same items in content tree. Clear?
The links generated by sc:path(.) (makes absolute links) on the domain2.com refer to domain1.com.
As far as I understand links refer to the first site in web.config that refered to the items in content tree.
How can I get valid links for both sites?
Just Rendering.SiteResolving to false.
The the sitecore will determine the urls' hostname from http request.