Umbraco get all cache items - caching

I am using Umbraco caching using Umbraco.Core.Cache;
I have no problem getting cache item using this line of code
ApplicationContext.Current.ApplicationCache.RuntimeCache.GetCacheItem(
given the correct cache key item.
Now my question is:
What if I forgot the cache key item? is there any way I can peek for all cache item? Or for debugging purpose I just want to see all of them?
I traced all possible intellisense suggestion but seems no "GetAllCacheItem" available
Anyone please enlighten me is it possible?

When writing the code you could only get intellisense on the cache keys if you used constants (like below) but the drawback is having to maintain the constant values when adding new cache items.
ApplicationContext.ApplicationCache.RuntimeCache.GetCacheItem(CacheKeys.SAMPLE_KEY)
public class CacheKeys
{
public const string SAMPLE_KEY = "some-example-key";
}
Whilst debugging you are able to view the cache keys as follows; under the hood IRuntimeCacheProvider (ApplicationContext.ApplicationCache.RuntimeCache) uses the HttpRuntime cache so although you cannot iterate over cache items in the RuntimeCache property directly you can use HttpRuntime.Cache like:
var keys = new StringBuilder();
foreach (DictionaryEntry cacheItem in HttpRuntime.Cache)
{
keys.AppendLine(cacheItem.Key.ToString());
}
Items added to the runtime cache via the Umbraco provider contain the prefix "umbrtmche-" so you may wish to filter the results:
HttpRuntime.Cache.Cast<DictionaryEntry>()
.Where(x => x.Key.ToString().StartsWith("umbrtmche"))
.Select(x => x.Key.ToString().Replace("umbrtmche-", ""))
.ToList();
And the final thing to note is that Umbraco uses the cache itself so you will not only see cache keys you have added, if you wish to filter these I suggest adding a prefix of your own so that you can filter your own cache keys from Umbraco's.

Related

MenuItemDefinition Order

I'm getting started with ASP.NET Boilerplate where I am using the free start-up template of ASP.NET Core Multi Page Web Application.
My question is regarding the left hand navigation bar. I have the NavigationProvider in my project where the abstract class is implemented. I have been testing out some of the properties available in the MenuItemDefinition, specifically the order and isVisible. My expectation was that I could set both the order and isVisible properties and that this would show in the application when running. I don't however see any of these properties actually being used to either set the order of the menu items or control their visibility.
For the order property I updated the Default.cshtml of the SideBarNav component to implement an OrderBy so I can get the correct order. This works but I'm not sure if this is the recommended approach.
Is it correct that setting the order when adding a MenuItemDefinition doesn't actually have any consequence to the running application and that this property is here with the expectation that I implement the behavior as I've done in the Default.cshtml?
My reason for wanting to control the order this way rather than by just the order the items are added is related to creating different modules that each have their own NavigationProviders.
Is it correct that setting the order when adding a MenuItemDefinition doesn't actually have any consequence to the running application and that this property is here with the expectation that I implement the behavior as I've done in the Default.cshtml?
Yes, the templates (as of v5.2.0) do not use nor implement ordering of user menu items.
I suggest implementing an extension method to easily change the ordering across the project.
public static IOrderedEnumerable<UserMenuItem> OrderByCustom(this IEnumerable<UserMenuItem> menuItems)
{
return menuItems
.OrderBy(menuItem => menuItem.Order)
.ThenBy(menuItem => menuItem.DisplayName);
}
Regarding versions: You are using v5.1.x and below. As of v5.2.0, the template has been migrated to use AdminLTE 3 instead of AdminBSB for the MVC UI, so the following changes are incompatible.
v5.2+
I have submitted a PR to implement the ordering: aspnetboilerplate/module-zero-core-template#510
var orderedMenuItems = Model.MainMenu.Items.Where(x => x.IsVisible).OrderByCustom().ToList();
var subMenus = Model.Items.Where(x => x.IsVisible).OrderByCustom().ToList();
Files changed:
Web.Mvc/Views/Shared/Components/SideBarMenu/Default.cshtml
Web.Mvc/Views/Shared/Components/SideBarMenu/_MenuItem.cshtml
v5.1.x and below
Note that you should change in 3 places (corresponding to 3 nesting levels) in Default.cshtml.
#foreach (var menuItem in Model.MainMenu.Items.OrderByCustom().ToList())
#foreach (var subMenuItem in menuItem.Items.OrderByCustom().ToList())
#foreach (var subSubMenuItem in subMenuItem.Items.OrderByCustom().ToList())
File changed:
Web.Mvc/Views/Shared/Components/SideBarNav/Default.cshtml

CRM SDK OrganizationServiceContext null navigation properties on entity

Trying to migrate an existing solution away from the deprecated Microsoft.Xrm.Client namespace to just use the generated service context from CrmSvcUtil using CrmSDK 9.0.0.5.
Previously we were using Microsoft.Xrm.Client.CodeGeneration.CodeCustomization to get a lazily loaded context.
I have two copies of the same solution and have been working through some of the API changes.
I have enabled Proxy Types
client.OrganizationServiceProxy.EnableProxyTypes();
Which to my understanding switched it to act in a lazily-loaded manner. However, none of the navigation properties are loading as expected.
The few blog posts that I've found around this shift to CrmServiceClient etc suggest that even without lazy loading I should be able to load the property manually with a call to Entity.LoadProperty() which will either load the property or refresh the data. However, after doing that the navigation property is still null (specifically I'm trying to use a Contact navigation property). When I look through the RelatedEntities collection it is also empty.
I know that the entity has a related contact item as if I use a context generated with Microsoft.Xrm.Client.CodeGeneration.CodeCustomization it returns it and I can also see it in CRM itself using an advanced search.
var connectionUri = ConfigurationManager.ConnectionStrings["Xrm"].ConnectionString;
var client = new CrmServiceClient(connectionUri);
client.OrganizationServiceProxy.EnableProxyTypes();
var context = new XrmServiceContext(client);
var result = context.new_applicationSet.FirstOrDefault(x => x.new_applicantid.Id == CurrentUserId);
//result.Contact is null
context.LoadProperty(result, "Contact");
//result.Contact is still null
//result.RelatedEntities is empty

Linq lazy loading, (EF Code first, Web.API and MVC)

I am having an odd problem with data loading which I don't understand, and I am hoping someone can explain to me what is going on, and perhaps how to accomplish my task more directly.
I am building a website using the technologies listed in the subject of this question.
I have a set of objects - each object has several properties (Name, ID, etc.) and a collection (ICollection<>) of other objects. So just looking at the tree of objects and their collections, it looks like this:
Tab
-TabRows
--Sections
---SectionRow
----Article
(So each tab has one or more tabrows, each tabrow has one or more sections, and so on. Each sub-object has a link back the parent, so each sectionrow has a SectionID, each Section has a TabRowID, etc.)
OK, so given that structure, consider this code:
// GET api/Tab/5
public Tab GetTab(int id)
{
var tab = db.Tabs.FirstOrDefault(t => t.TabId == id);
var tabrows = db.TabRows.ToList();
var sections = db.Sections.ToList(); // This makes the tabRow.Sections populate
var sectionrows = db.SectionRows.ToList();
var articles = db.Articles.ToList();
return tab;
}
So here is what happens. When the first line (var tab =...) executes, I get a tab object, but the TabRows collection is empty. (It is not null because the constructor instantiates it).
When the second line (var tabrows =...) executes, tab.TabRows suddenly populates. tab.TabRows.Sections is empty.
When the third line executes, tab.TabRows.Sections suddenly populates.
And so on.
I am assuming this is some sort of "lazy loading" on behalf of Linq, or perhaps one of the other technologies. But I don't know them well enough to figure it out.
Is there a way to re-write this so that I can just call line 1 and basically have everything auto-populate without having to individually reference every single object in every single collection?
Lazy loading is enabled by default and eager loading disabled. Entity framework allows you to hint at eager loading using the include statements. Your statement will become something like this.
var tab = db.Tabs.FirstOrDefault(t => t.TabId == id).Include("TabRows");
or as Include(t => t.TabRows);
Take a look at this link for more information.
In your case you would need to handle nested includes as well. Which means you would be better off taking another Model (your class) structured as follows
Tabs -> Containing a List<TabRows> -> containing a List<Sections> etc.
You would then need to re-write the linq so it populates the entire Model including the nested entities using nested includes.
As a side note, too many of these inner joins might slow down your querying and so consider indexed views on your DB side if and when possible

ASP MVC3 keeping variable value through page refresh

Yo! As the topic says, I need to keep var's value through refresh. Thing is it's SessionKey. Other thing is it's generated automatically.
What I need to do is html <select> which won't lose data on refresh. Actually there're 2 <select>s which are filled programatically and you can pass data between them in real time. Then if I press save and page fails to validate these <select>s return to their original state. I already have it fixed, by keeping data in session and if it has certain key, <select>s are filled with correct data.
Why would I need automatically generated key? Well multi-tab working. If user would try to add 2+ new records to database at the same time (which is extreme, but possible), he needs to have that data kept under different keys so app can find desired stuff.
I could as well make client side validation, but... nope, just nope, too much work.
As for code, anything useful:
public ActionResult MethodUsedAfterPageLoad
{
...
Guid stronyGuid = Guid.NewGuid();
ViewData["strony"] = stronyGuid.ToString();
...
}
This way every refresh creates new Guid, but Guid is used as SessionKey!
If I do it following way:
public Class ControllerClass
{
private Guid stronyGuid;
...
}
This will reset variable, that's bad. Using static keyword is bad idea.

MVC3 with hundred of thousands layouts/templates

I have an application where each user can choose a custom layout. The layouts can be different and it's not just css styles but html as well.
I know that mvc would cache the layout, but having so many layouts I doubt it would fit in cache. So what would it be better to save templates in DB or on the disk?
FYI: DB that I'm using is MongoDB.
I would save the layouts on disk because at the moment I don't see any advantage in a database (unless you do). But one thing that is worth mentioning is that you can create a class derived from OutputCacheAttribute and have your saved result depend on the layout you're using.
Does the layout depend on user? You could use the VaryByCustom property to have it vary by user.
EDIT
Are your users allowed to change layouts dinamically? If yes, you should also have a guid associated to your users change it each time the layouts change so you return on your VaryByCustom method:
return string.Format("User-{0}-{1}", user.Id, user.LayoutUpdateGuid);
See the meaning of this? This way, when a user changes the layouts, they will see their pages updated immediately.
How to apply the VaryByCustom attribute in your situation
In your action method, you may use:
[OutputCache(Duration = 3600, VaryByCustom = "UserLayouts")]
public ActionResult Details(string param)
{
// Returning the view
}
Then, in your VaryByCustom method in your Global.asax.cs file:
protected override string VaryByCustom(string custom)
{
switch (custom)
{
case "UserLayouts":
//// Here you fetch your user details so you can return a unique
//// string for each user and "publishing cycle"
//// Also, I strongly suggest you cache this user object and expire it
//// whenever the user is changed (e.g. when the LayoutUpdateGuid is
//// changed) so you achieve maximum speed and not defeat the purpose
//// of using output cache.
return string.Format("User-{0}-{1}", user.Id, user.LayoutUpdateGuid);
break;
}
}
The missing piece
The missing piece here is that you need to store a value that I called LayoutUpdateGuid (I'm sure you'll find a better name) and change that value whenever a user changes his layouts => this will lead to a different string being returned by the VaryByCustom(string) method in the Global.asasx.cs which in turn will force your action method to run again and return the result with the updated layout.
Makes sense to you?
Note: I can't test the specific code I wrote here, but I am sure (apart from typos) it is correct.

Resources