Kentico 12 Caching in different environments - caching

MVC C# project with a Kentico 12 back-end (no drag-n-drop web parts just using it as back end CMS, with calls to Kentico APIs for data). Basically, we're having a caching issue that only occurs on one of our environments (PROD). I believe this is more of an IIS or environment issue than a Kentico thing. Let me give you some specifics: Kentico 12 MVC v12.0.34 (upgraded from K11) and as stated before we're not using any web parts/components. Kentico is just the back-end CMS, and we use Kentico APIs to pull data for each page and have rolled our own views and models.
We have 2 environments, STG and PROD, both running Win Server 2016 that have a slightly different OS build version
STG: v1607 OS build 14393.3115, IIS v10.0.14393.0
PROD: v1607 OS build 14393.2999, IIS v10.0.14393.0
Within Kentico when we update a category, an event is wired for the UPDATE and runs the following code:
CacheHelper.TouchKeys(new[] { "cms.category|all" });
This clears ALL category caching (CacheDependency within Kentico) and when the webpage is refreshed the GetAllCategories method that pulls, you guessed it, ALL categories is called again. If you try it another time, you'll get a cached version until there's a change within Categories (or the cache timing runs out, something like a month). Works exactly as you'd think on the STG box.
Just to see what's going on, I added some Kentico informational logging to check what is happening at different places around this Update event firing. From the EventArgs I can get the source of the event (which category triggered it), and I can see when it's using the cached info and when it retrieves it from the db. Awesome.
The issue that I'm running into is when I run on PROD using the exact same code base, along with the same logging, and trigger the same event, the cache does not get released. The event logging says it has, but when the webpage refreshes, the GetAllCategories is not brand new but the last cached value. The only way to get the new version is to recycle the app pool or shutdown/startup the application within IIS.
There is no Output Caching on the class/methods. Same code base across 2 different servers.
Is there some environment variable or IIS setting that could have been set differently on the PROD box?
Any thoughts what could be causing this? Other places to look on the web server? Thanks for your help!

I've had a caching issue similar to this and it turned out that it was down to the Web Farm configuration.
The problem is that when you have the CMS and MVC both hosted on the same server Kentico cannot tell them apart in Web Farms.
Make sure that your CMSApp and MVC projects each have web.config keys to set the CMSInstanceNameSuffix key. This will help differentiate them in Web Farms and allow web farm tasks to be correctly generated for your MVC app.

Related

Kentico Output Caching issue - content couldn't get updated

I am working with a Kentico site and I have a problem with page output caching.
We have a custom webpart which loads the records from a Bizform's record data and displays those data in a page. The problem is that after giving it several tries, we couldn't figure out the problem why the webpart couldn't get the latest data from the bizfrom data and we suspect it was because of output caching.
We tried to:
Disable webpart output caching in webpart configuration
Disable page output caching in CMSDesk > General > Output Caching
Disable site output caching in Settings > System > Performance
Disable IIS cache for both User-mode and Kernel cache
Create cache dependencies for cms.form|byid| touched key (which I found is not supported in current kentico version)
And going to try create event handler to add touched key on bizform insert event
We encounter a similar problem with Shopping Cart Mini Preview Webpart with Ecommerce.CurrentContext.CurrentShoppingCart which returns different result for service handler (.ashx - gets updated) and for webpart (.ascx - does not get updated)
If you ever experienced these problems, please help.
The last place where it could be cached is the content cache. It can be set either in Settings->System->Performance or at the web part level under System settings section.
Only web parts that utilize the content caching have this section available. (E.g. some repeaters and data source web parts.) It might be a little bit confusing because then there are two sections (System settings and Performance) where you can influence caching. However the Performance section is used to set up the Partial output cache.
Anyway, you should definitely try to check Cache debug to see what is actually cached.
Additional resources:
Deep dive – Kentico CMS Caching
New in 5.5: Caching API changes
Deep dive: Cache dependencies
Kentico caching and cache dependencies explained
ASP.NET Caching Dependencies
I have faced issue similar to second one (with Shopping Cart Mini Preview Webpart) recently. Only web service (.asmx) was used instead of HTTP handler. In my case issue was solved by setting the EnableSession property of WebMethod attribute to true for all the CRUD webservice methods.
[System.Web.Services.WebMethod(EnableSession = true)]
So I think the matter is that handler should be able to access current Session.
In case of HTTP handler you could try to add IRequiresSessionState on the handler declaration to attach it with the session.
I am also using Kentico 8, I see that your Kentico version is older. That might also have impact but I am not sure about that.

Portal type application with AngularJS (Multiple Independent apps)

We are trying to create a portal type application with multiple / independent "sub-apps". Assuming that all sub-apps are written in Angular what is a good pattern to achieve the following goals.
Each app can be developed and deployed independent of each other.
They share a common authentication service, they can share common libraries (directives, filters etc).
Only one app will be visible and active at any given time. The scope of each sub-app is isolated from each other.
When the users goes between the sub-apps, the state is maintained as long as the user does not refresh the page or visit another static link. (I think this is built into Angular and no special effort maybe needed)
Each sub-app will have more than one views (it will have its own menu). There will be a top menu based on what sub-apps are available. Ideally the top menu is dynamically build based on what sub-apps are deployed. Maybe there is a server side component to this (the server detects the folder structure etc and determines what apps are deployed and injects the necessary js code into the page).
Given the fact that AngularJs does not have multi-level view structure, I was thinking of using multiple ng-app declarations on different divs and then using $window scope to store the key of the active app and hide the ones which are not active.
There is no easy answer to your (rather open) question, but regarding the $route and ngView limitations, I have been having great success employing a technique derived from this: http://www.bennadel.com/blog/2420-Mapping-AngularJS-Routes-Onto-URL-Parameters-And-Client-Side-Events.htm
This is something that I also have been thinking of trying to implement. While I don't have a complete working solution, I believe that this type of portal app would consist of multiple angular apps on the same page.
The portal app would be the traditional ng-app directive on the main page and the "portlets" would be dynamically created and manually bootstrapped angular apps on a sub view div. You can share data, state, authentication, personalization, etc from injecting the portal services (contained in their own module) that provide these features into the manually bootstrapped portlet apps.
The tricky part is how the portal app would discover the portlet apps and serve up their angular modules knowing that these apps would be independently deployed web apps with their own urls.
I still have some questions around if the service data would be common between the apps or if you would need to try and leverage HTML5 local storage via the portal service (like a data manager).

Can I see server logs or something equivalent on AppHarbor?

I just pushed my app to appharbor. I don't need full-on google analytics (and I can't use it since mostly my app is about dynamically creating rss feeds) but would just like to get a general idea how often my site is being hit and the types of urls that people are hitting.
Normally I would just keep an eye on the severlog but that doesn't seem to be available on appharbor. How can I get something equivalent?
I recently turned on the logentries add-on available in Appharbor and it has been a godsend for solving some server-side errors on my asp mvc 3 app. Extending my code to log routing requests would be a simple few lines of code.

Blank page on Azure

I have an application running in Azure (trial account). So far so good, everything has been nice, except for a long deploy times (10-15 minutes).
I've done a deploy recently and got a lot of weird bugs I cannot trace. For example, if I log in and thus a cookie is created (I use FormsAuthentication) all I get from the application is a blank page, as in, absolutely nothing is sent to the browser. The application works fine in the ASP.NET Web Dev Server, IIS Express, even the Azure Emulator!
What could be the issue? Searching the web hasn't been much help, with only a couple of unrelated issues.
I tried logging into the site (if I correctly understood from one if the comments, the url is versulo.com) and I didn't get any blank page with 404 status code.
However, there is another problem I spotted. Your site seems to be implementing caching inappropriately. The main page, the one from which you trigger the login and which is dynamic in nature contains an Expires header set at 5 minutes after the pages first load. That means that each call or redirect to that page within 5 minutes since it was first loaded, will be served from the browser's cache.
Because of that, after I login into your application I am redirected back to the home page which looks like I am not logged in. If I force a F5 refresh on the browser, then the page will indeed show me as logged in.
If instead of a refresh I try to login again (which is what I did in my first trials, since it looked like the login didn't work in the first time), I am getting an error page with the following message:
Sorry, there has been an error on the server.
500
The page looks like an application error page and even if it displays the 500 number, it is actually served with an HTTP 200.
So, while I am not 100% sure if this is also the cause of the problem described by you, you should remove the Expires headers from the dynamic pages your application is serving.
This can be because you're combining Forms Authentication with multiple instances. Are you using multiple instances? If that's the case, could you:
Try to change it to 1 instance. Does this fix the issue?
Try to make the following change to the web.config (configure machineKey): http://msdn.microsoft.com/en-us/library/ff649308.aspx
some partial views are not rendered at all;
Do you mean some pages are working fine, but others are not? It would be better if you can point out a pattern on what’s working and what’s not? For now, please make sure all referenced assemblies (except for default .NET assemblies and Windows Azure runtime) have Copy Local set to true. For example, MVC assemblies are considered as extensions to .NET, so please set Copy Local to true. In addition, you can also try to use Fiddler to monitor the requests to see what’s returned from the server.
Best Regards,
Ming Xu.
Could you provide a link to the application, or perhaps some source code?
When you say 'blank page', what is actually returned, a 404 / 500?
Have you inspected the IIS logs, or added some trace information to your code?
Have you tried accessing the service using it's ip address rather than domain name?

Clearing IIS Cache from MVC3 App

I need to clear the IIS cache on my server. The exact reason is detailed below; but the reason doesn't matter. I'm 100% sure that this is the solution I need; as detailed below, I have used the process of elimination to determine that this is, indeed, the problem I'm facing, and the solution I need.
I have an MVC3 app that's themeable (skinnable architecture). Think of it as Wordpress; users can develop a theme, download it, and activate it on their site. The theme controls exactly the final HTML output. This is an over-simplification, since I provide an API with useful functions to be consumed by themes.
Anyway, users can change the theme of the site. The theme is currently stored in a static variable. When a view page is rendered, the name of the theme determines the location of the layout file (which contains references to the CSS files, etc.) and the view files. The theme is a setting that persists in the DB.
For example, if I have a theme called "Foo", then when requesting the /Admin page, I might use /Themes/Foo/Admin.cshtml. If I have another theme called "Bar" which does not have that file, then for /Admin it might request /Themes/Bar/Generic.cshtml as the layout.
The problem is that changing a theme means that every single page on the site is outdated. This means that any sites cached on IIS7 will show the old theme; this is incorrect. I need them to show the new theme.
Anyway, IIS7 uses caching by default. I need essentially a way to clear the cache when a user changes the theme. Currently, this is not happening, and users continue to see the old theme until the cache (somehow) expires itself.
I am not using output caching, or any other form of explicit caching; this is a "vanilla" ASP.NET MVC3 application from a caching perspective (i.e. I didn't add/configure any caching). IIS7 has its own default caching. I know this, because if I disable output caching in IIS7 for my Site, I will always see the correct theme after a change.
How can I flush the cache? Other SO questions point to using Cache.blah, and I tried using HttpContext.Current but that is null during tests (using VS test tool) -- because the ASP.NET pipeline is not used in full.
To explain, in an integration test, I basically:
Go to localhost/Test/
Log in (submit values into the forms)
Change the theme by browsing to the right page and clicking the right link
Request another page
See if the theme changed (based on the layout/css file name).
This is all done by code; I use a C# port of HtmlUnit, and along with deploying my app to /Test in IIS, I can essentially browse it like an end user.
Currently, this test passes around 50% of the time. The problem is that IIS is caching the results, and I can't cleanly reliably reset the cache on the server-side.
Again, I'm not talking about clearing the session or the user-side cache; IIS itself is the culprit guilty of caching my application. Nor do I want to completely disable the cache via the IIS settings, a) because I can't force people who install my application to do that, and b) because caching is good.
So how can I force flushing the cache on the server?
For example, I tried programatically touching web.config; this works, but recycles my application pool, and so, kills my static variables; every request means reloading all the static vars from the DB, which kills my performance.
As you requested I have amended this post:
You can use output cache, you say that the selected theme is stored in the database ( like settings for the site ) Well I would add another column with say a GUID and then use this as the varybycustom value.
Your global.asax file will be able to run code:
void Page_Init() {
///code here to get the GUIDforthissitestheme
var outputCacheSettings = new OutputCacheParameters() {
Duration = Int32.MaxValue, //think its maxvalue
VaryByCustom = GUIDforthissitestheme
};
InitOutputCache(outputCacheSettings);
}
At least here you will have output cache, but also every change of theme, changes the GUID so therefore changes the cache and then your page should be new.
I did something like this on a site that listed products, and when the products database was updated the key would be changed, however I can't find what site I implemented it and I work on a hell of a lot of sites.
hope this helps
Set up 'Cache Rule' in 'Output caching' feature with 'File Cache Monitoring' set to 'Using file change notification'. Then 'touch' the files theme change affects, from .net code you could do:
System.IO.File.SetLastWriteTimeUtc(fileName, DateTime.UtcNow);
The issues you are describing sound a lot like a client side caching issue. Have you checked this with a HTTP Proxy like Fiddler to verify if this is getting cached on the client?
If you are seeing HTTP 304's after a template change you may want to try configuring IIS (or your site template) to disable client side caching.
I dont think the approach mentioned for themes is correct.
If we are using STATIC variables , then it will affect all the users and all the pages.(Which is certainly not required.)
We can think of two approaches,
Use theme name in url and make it as a prat if RouteData. So the url "http://myHost/BLUE/.." will return in BLUE theme and "http://myHost/RED/.." will return in RED theme. If user will change theme then url will be updated.
The problem with above approach is next time user browse, it will load default theme.
So better approach will be save theme as a part of user preference. Once user logged in read the theme from DB and set the RouteData value.
Just touch web.config. That's the easiest and most reliable way. Flushing the application pool programmatically is overkill.
If you have a problem finding out where web.config is in a test environment (since System.Web.HttpRequest.Current is null, and similar for Server), you can always use an app.config file to point out the location.
Again, there's no other easy way to do it; even disabling output caching, as mentioned in the question, is hard to do through web.config alone.

Resources