Friday, September 26, 2014

MongoDB

I have been playing with MongoDB and come across some command that I find useful.

1. Install MongoDB as a Windows Service:

Taken from http://stackoverflow.com/questions/2438055/how-to-run-mongodb-as-windows-service
First I executed this command:
D:\mongodb\bin>mongod --remove
Then executed this one:
D:\mongodb\bin>mongod --dbpath=D:\mongodb --logpath=D:\mongodb\log.txt --install
After that right there in the command prompt execute:
services.msc
And look for MongoDB service and click start.


Wednesday, October 16, 2013

Slow loading, locking and unlocking of items in "My Items" when contents are enormous (800k++ items)

Few weeks back I was engaged in solving an issue with slow loading, locking and unlocking of items in "My Items" when contents in Sitecore content tree are massive in term of numbers. 

Being in a print media space, the client who also happened to be one of the leading print media company in Malaysia, they naturally would have massive amounts of contents. Henceforth the performance of the locking mechanism through "My Item" interface was compromised.

To start of, here are the statistic before the tweak:

Number of items in the content tree: 800k++
Load "My Items"                            : 65 seconds
Unlock All "My Items"                    : 60 seconds
Unlock Single Item                         : 5 seconds

The problem or cause of this issue is because of the query being used to populate "My Items"

in 

namespace Sitecore.Shell.Applications.WebEdit.Dialogs.LockedItems
...
///
/// Raises the event.
/// 
///
/// The object that contains the event data.
///            
protected override void OnLoad(EventArgs e)
{
      Assert.CanRunApplication("/sitecore/content/Applications/Content Editor/Ribbons/Chunks/Locks/My Items");
      Assert.ArgumentNotNull((object) e, "e");
      base.OnLoad(e);
      if (XamlControl.AjaxScriptManager.IsEvent)
        return;
      ComponentArtGridHandler.Manage(this.Items, (IGridSource) new GridSource((IEnumerable) (Client.ContentDatabase.SelectItems("fast://*[@__lock='%\"" + Context.User.Name + "\"%']") ?? new Item[0])), true);
      CommonExtensions.LocalizeGrid(this.Items);
}

To solve this issue I drafted a list of logic to address this issue with minimal impact to the existing code and logic.

1. Store user locked item IDs into User Profile
2. Instead of querying the DB, the "LockedItemPage" a.k.a "My Items" will now first look at User Profile
3. If the User Profile is empty (string.empty), it will then call the query code and store this list of item IDs back to User Profile. So it is as expected for the first time user to be slow at first when clicking "My Items"
4. If indeed there is no items that are locked by the context user, an indicative string "Empty" to label the user having no items locked to him will be stored in his/her User Profile. This is to prevent the query to be executed unnecessary
5. Lock and Unlock mechanism will need to be updated to update the Locked Item IDs in the user profile
6. Prior to loading the list of items in "My Items", filtration of IDs for invalid IDs due to Admin unlocking and/or items being deleted are performed.

With that in mind, the code changes are made on the following commands and shell file

1. Item:CheckIn command
2. Item:CheckOut command
3. Webedit:UnlockAll command
4. sitecore\shell\applications\webedit\dialogs\lockeditems\LockedItems.xaml.xml
5. Create a class that will override the backend code for LockedItems.xaml
6. Update the commands.config
7. Create a User Profile in Core DB

Instead of going through the code as it is quite extensive, I will instead share the code to achieve the above. Here is the link https://www.dropbox.com/s/qnsoue98dfaerjw/srcv3.zip 

The link will contains only the code in which it will need to be compile and also user profile to be created before the above will work.

After implementing the above, the new statistic is as follow:

Load "My Items"                            : 2seconds
Unlock All "My Items"                    : 7 seconds
Unlock Single Item                         : 1 seconds

 

Wednesday, December 26, 2012

Lucene Search - Search All Fields in Sitecore

Recently, I was having troubled trying to figure out why I couldn't get any hits from querying a custom field that I have added programmatically onto Lucene Index. Now beside the customization I have added, I have used Sitecore Advanced Database Crawler that makes life easier working with Lucene and Sitecore.

Anyway, after digging and debugging, I found out that when searching for all Sitecore field through the index, it actually searching on 1 single field in Lucene Index. Essentially this single field in single Lucene Document contain the value of all the fields in a single Sitecore Item. This field in Lucene is called "_content"

For this reason, if I need to search both all of Sitecore fields and the additional fields I have created, I will need to modify the query to search for both "_content" and "additional fields" I have created.

Monday, November 19, 2012

Sitecore Page Editor - RTE field cant be edited

To ensure Page Editor works well in Sitecore, components will need to be coded using Sitecore controls such as 

<sc:text field='text' runat='server'>

So for example if my components html code as such below 

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="StoryResources.ascx.cs"
    Inherits="Sitecore.Web.layouts.StoryResources" %>

    <p>
<sc:text field='text' runat='server'>
    </p>


I would expect that my RTE field called 'Text' will be editable in Page Editor. Surprise surprise, it is not editable. In fact when I look at the Firebug console, there is js error. 

Thinking hard plus trial and error, found out the issue was because of the nested P tag. This is introduce when wrapping my sc:text with a P tag. Now of course being a RTE editor chances of having a P tag in it is high. This resulted into nested P. 

Further to that, I googled nested P tag to found out what happened when you nest a P tag and I found an interesting article. Below is the link 

http://cksource.com/forums/viewtopic.php?f=6&t=11870

In the article, it mentions that nested P tag will transform into unnested P tag. This transformation or invalid html cause the Page Editor to break. So to resolve this, I wrapped the sc:text with a div instead. 

Thursday, October 4, 2012

Sitecore Admin Tools (e.g. cache.aspx) not working

Recently I was tasked to figure out why tools under /sitecore/admin folder are not working. Tools such as cache clearing (cache.aspx).

Now the system is Sitecore Intranet Portal setup running on Sitecore 6.1 with multiple integration points such as Active Directory and Sharepoint. Naturally the configurations are quite many. Anyway when I am trying to access the tool it will throw an arrow as such

Server Error in '/' Application.

Object reference not set to an instance of an object.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

Source Error:

An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:


[NullReferenceException: Object reference not set to an instance 
of an object.]
   Sitecore.Nexus.Web.HttpModule. (Object sender, EventArgs e) +340
   System.Web.SyncEventExecutionStep.System.Web.HttpApplication
.IExecutionStep.Execute() +79
   System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& 
   completedSynchronously) +170



Version Information: Microsoft .NET Framework Version:2.0.50727.5420; ASP.NET Version:2.0.50727.5420 

Figuring out the issue, the error was caused when


<location> tag is added.

Removing it solved the problem

Monday, September 3, 2012

Filtering users by Domain in UserManager


Often we introduce a new domain in usermanager and would like to filter out the users associated to the new domain. This post will outlines how we go about achieving that.


The following outlines the steps needed to filter out users associated to unwanted domain in UserManager.
Firstly, a new class that inherit from UserManager will need to be created. The class will then override OnLoad method to filter the users. The code to achieve that is as follow
01.public class AdvancedUserManager : UserManager
02. {
03. protected override void OnLoad(EventArgs e)
04. {
05. Assert.ArgumentNotNull(e, "e");
06. base.OnLoad(e);
07. Assert.CanRunApplication("Security/User Manager");
08. var managedUsers = global::Sitecore.Context.User.Delegation.GetManagedUsers().Where(IsAllowedDomain);
09. ComponentArtGridHandler<User>.Manage(Users, new GridSource<User>(managedUsers), RebindRequired);
10. Users.LocalizeGrid();
11. }
12.
13. // Properties
14. private bool RebindRequired
15. {
16. get
17. {
18. return ((!Page.IsPostBack && (Request.QueryString["Cart_Users_Callback"] != "yes")) || (Page.Request.Params["requireRebind"] == "true"));
19. }
20. }
21.
22. private static bool IsAllowedDomain(Account user)
23. {
24. if (user.Domain == null) return false;
25. var domainToCheck = user.Domain.Name.ToLower();
26. var excludedDomain = global::Sitecore.Configuration.Settings.GetSetting("ExcludedDomainInUserManager");
27. if (string.IsNullOrEmpty(excludedDomain)) return true;
28. var domainArray = excludedDomain.Split("|".ToCharArray());
29. return domainArray.Select(domain => domain.ToLower().Equals(domainToCheck)).All(isExcludedDomain => !isExcludedDomain);
30. }
31. }
After the class has been created, we need to modify the UserManager.aspx to point to the new namespace. The path to the UserManager will be as follow
\sitecore\shell\Applications\Security\UserManager\UserManager.aspx
Overwrite the default
1.<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="UserManager.aspx.cs" Inherits="Sitecore.Shell.Applications.Security.UserManager.UserManager" %>
Lastly, we need to create a Sitecore Setting in config file name "ExcludedDomainInUserManager" to determine which Domain to filter.
That's it! You should now have filtered user manager. :)

Wednesday, April 11, 2012

ECM - Scheduled email is not working

Recently, I was presented an issue where email cannot be scheduled from ECM. Though test email or immediate dispatch of emails work just fine. The following set of actions will replicate the issue on the particular setup we have

  1. User creates a newsletter (any template) under target audience draft folder.
  2. User schedules dispatch the newsletter.
  3. System moves newsletter to scheduled folder.
  4. System creates a new task item.
  5. System triggers task when schedule arrives (sometimes with few minutes delay*).
  6. System moves newsletter to dispatch folder.
  7. System set the newsletter status to pause.
With the help from support team in Sitecore, the issue was resolved. Apparently the strange behavior is caused by setting EventQueue to true.

However the setup is actually a Scaled Setup where EventQueue is essential in clearing cache and also to rebuild indexes on the delivery server. For now, further test will be conducted and i will update once more information is available.