Examine extensions no longer working in Umbraco 7.2.8
Hi all,
In previous Umbraco installations I have used the following extension methods to trigger custom changes to the Examine indexes upon saving and loading up my Umbraco application. However, after running these in debug in Visual Studio after upgrading to Umbraco 7.2.8 these no longer seem to work.
using System;
using System.Text;
using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;
using Examine;
using umbraco.BusinessLogic;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.WebApi;
using Umbraco.Web;
using UmbracoExamine;
namespace Lost_World_Adventures.App_Code.Examine_Extensions
{
public class ExamineEvents : ApplicationBase
{
public ExamineEvents()
{
ExamineManager.Instance.IndexProviderCollection["ExternalIndexer"].GatheringNodeData += ExamineEvents_GatheringNodeData;
ExamineManager.Instance.IndexProviderCollection["AxumIndexer"].GatheringNodeData += ExamineEvents_GatheringNodeData;
}
void ExamineEvents_GatheringNodeData(object sender, IndexingNodeDataEventArgs e)
{
AddToContentsField(e);
}
private void AddToContentsField(IndexingNodeDataEventArgs e)
{
Dictionary<string, string> fields = e.Fields;
string level = fields["level"];
string id = fields["id"];
if (level != "1")
{
string nodeTypeAlias = fields["nodeTypeAlias"];
int nodeId = 0;
int ancestorId = 0;
try
{
nodeId = Convert.ToInt32(id);
if (nodeId != 0)
{
IContentService cs = ApplicationContext.Current.Services.ContentService;
try
{
IEnumerable<IContent> ancestors = cs.GetAncestors(nodeId);
if (ancestors.Where(x => x.ContentType.Alias.ToLower() == "homepage").Count() == 1)
{
ancestorId = ancestors.First().Id;
}
if (ancestorId > 0)
{
e.Fields.Add("siteNode", ancestorId.ToString());
}
}
catch (Exception)
{
// Do nothing
}
}
}
catch (Exception)
{
// Do nothing
}
}
else
{
e.Fields.Add("siteNode", id);
}
}
}
public class AppEvents : IApplicationEventHandler
{
public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
var helper = new UmbracoHelper(UmbracoContext.Current);
ExamineManager.Instance.IndexProviderCollection["AxumIndexer"].GatheringNodeData
+= (sender, e) => AppEvents.GatheringContentData(sender, e, helper);
}
public static void GatheringContentData(object sender, IndexingNodeDataEventArgs e, UmbracoHelper helper)
{
}
}
}
My code relies heavily on the field that this code adds to the index so it needs to be there so does anyone know how I can fix this or what has changed in this version?
Thanks for the information. Do you have any idea of what events I should be binding to?
I need to refresh the index when someone adds content programmatically via the content service and when someone saves or saves and publishes a document in Umbraco.
You are binding to the right events, you just aren't binding to them in the correct place.
Like I said, move all of your logic from your ExamineEvents class into your AppEvents class. Move the logic in your ExamineEvents ctor to your AppEvents.OnApplicationStarted, then delete your AppEvents.
You need to bind to the events once Umbraco has booted up.
So how do I go about ratifying this? Like I said my code is dependant on this and the only reason I did this in the first place was because I was advised to on here. I'm still fairly new to C# and .Net and to be honest all of this side of things is a little bit confusing to me.
I am assuming I just move the code I have in my Examine Events class inside of the OnApplicationStarted method of AppEvents but do I still pass in the same stuff as I was passing in before?
Because you are re-iterating of this IEnumerable a whole lot of times! especially with the use of Count() and First(). Without ToArray(), your call to Count() will re-iterate the entire ancestors collection... behind the scenes you don't know what that is doing! I suggest using Resharper, it will tell you if you are re-iterating IEnumerable collections which shouldn't be done.
Also, I would very strongly suggest that you don't ever swallow Exceptions. You should at least log the Exception:
LogHelper.Error<AppEvents >("Write something about why you felt the need to have a try catch", ex);
If you are just swallowing exceptions (ever), you will never know why things are not working as you intended.
You didn't add your event binding logic, so your events will never fire. You need to move the logic from the ctor in your ExamineEvents to the OnApplicationStarted method of your AppEvents.... specifically this block of code:
By the way, since you are looking up all ancestors for a single node each time a document is indexed, if you rebuild all and have a lot of nodes, this will be very aweful for performance.
If I add those to my OnApplicationStarted I get the error:
Error 3 The name 'ExamineEvents_GatheringNodeData' does not exist in the current context C:\Projects\Lost World Adventures\Lost World Adventures\App_Code\Examine_Extensions.cs 94 101 Lost World Adventures
Error 4 The name 'AppEvents_GatheringNodeData' does not exist in the current context C:\Projects\Lost World Adventures\Lost World Adventures\App_Code\Examine_Extensions.cs 95 97 Lost World Adventures
Okay, these suggested changes have now completely broken my application. Here is the final code I now have based upon the suggestions above:
public class AppEvents : IApplicationEventHandler
{
public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
var helper = new UmbracoHelper(UmbracoContext.Current);
ExamineManager.Instance.IndexProviderCollection["AxumIndexer"].GatheringNodeData
+= (sender, e) => AppEvents.GatheringContentData(sender, e, helper);
}
public static void GatheringContentData(object sender, IndexingNodeDataEventArgs e, UmbracoHelper helper)
{
AddToContentsField(e);
}
private static void AddToContentsField(IndexingNodeDataEventArgs e)
{
Dictionary<string, string> fields = e.Fields;
string level = fields["level"];
string id = fields["id"];
if (level != "1")
{
string nodeTypeAlias = fields["nodeTypeAlias"];
int nodeId = 0;
int ancestorId = 0;
try
{
nodeId = Convert.ToInt32(id);
if (nodeId != 0)
{
IContentService cs = ApplicationContext.Current.Services.ContentService;
try
{
IEnumerable<IContent> ancestors = cs.GetAncestors(nodeId).ToArray();
if (ancestors.Where(x => x.ContentType.Alias.ToLower() == "homepage").Count() == 1)
{
ancestorId = ancestors.First().Id;
}
if (ancestorId > 0)
{
if (e.Fields.ContainsKey("siteNode"))
{
e.Fields["siteNode"] = ancestorId.ToString();
}
else
{
e.Fields.Add("siteNode", ancestorId.ToString());
}
}
}
catch (Exception)
{
// Do nothing
}
}
}
catch (Exception)
{
// Do nothing
}
}
else
{
e.Fields.Add("siteNode", id);
}
}
}
}
For some reason when I save a Node in the back office, it first seems to run the GatheringContentData method. It then jumps up to the OnApplicationStarted and highlights the:
ExamineManager.Instance.IndexProviderCollection["AxumIndexer"].GatheringNodeData
+= (sender, e) => AppEvents.GatheringContentData(sender, e, helper);
Following this it jumps backwards and forwards between the two loads of times. When I use the back office Examine searcher tool to look for the node I have just saved, it is present in the index complete with the siteNode field I have added to the index using my code. However, when I run the other part of my application that relies on this or even indexing in general, it now fails.
Nothing is returned anymore. When I check the index, it would seem that for some reason now it is no longer writing my homepage to the index.
Could somebody please point me in the right direction as there is barely any literature on these new methods on Our and my application is dependent on the Indexing working in this way.
The reason I am having to do this in the first place is because the culture of a page doesn't seem to be indexed so I am storing a siteNode against every page so that I can tell which is the root element and apply logic accordingly.
I have now re-engineered this to the following based upon this article however I now find that nothing is being saved to my custom index at all.
using System;
using System.Text;
using System.Linq;
using System.Xml.Linq;
using System.Collections.Generic;
using Examine;
using umbraco.BusinessLogic;
using System.Web;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Services;
using Umbraco.Web.WebApi;
using Umbraco.Web;
using UmbracoExamine;
namespace Lost_World_Adventures.App_Code.Examine_Extensions
{
public class AppEvents : IApplicationEventHandler
{
public void OnApplicationInitialized(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
public void OnApplicationStarting(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
}
public void OnApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)
{
var helper = new UmbracoHelper(UmbracoContext.Current);
ExamineManager.Instance.IndexProviderCollection["AxumIndexer"].GatheringNodeData
+= (sender, e) => ExamineEvents.GatheringContentData(sender, e, helper);
}
public static void GatheringContentData(object sender, IndexingNodeDataEventArgs e, UmbracoHelper helper)
{
}
}
public static class ExamineEvents
{
public static void GatheringContentData(object sender, IndexingNodeDataEventArgs e, UmbracoHelper helper)
{
var content = helper.TypedContent(e.NodeId);
var homepage = content.Ancestor("homepage");
e.Fields.Add("siteNode", homepage.Id.ToString());
}
}
}
Examine extensions no longer working in Umbraco 7.2.8
Hi all,
In previous Umbraco installations I have used the following extension methods to trigger custom changes to the Examine indexes upon saving and loading up my Umbraco application. However, after running these in debug in Visual Studio after upgrading to Umbraco 7.2.8 these no longer seem to work.
My code relies heavily on the field that this code adds to the index so it needs to be there so does anyone know how I can fix this or what has changed in this version?
Any help would be greatly appreciated.
Jason,
Any issues in the umbracolog? The latest version of Umbraco I have used is 7.2.4.
Regards
Ismail
yes, it's because you are binding to events on your ctor:
You should never really do that.
ApplicationBase
is super old and shouldn't be used anymoreYou should move all of that logic to your AppEvents and bind to events inside of started.
Hi Shannon,
Thanks for the information. Do you have any idea of what events I should be binding to?
I need to refresh the index when someone adds content programmatically via the content service and when someone saves or saves and publishes a document in Umbraco.
Cheers,
Jason
You are binding to the right events, you just aren't binding to them in the correct place.
Like I said, move all of your logic from your
ExamineEvents
class into yourAppEvents
class. Move the logic in yourExamineEvents
ctor to yourAppEvents.OnApplicationStarted
, then delete yourAppEvents
.You need to bind to the events once Umbraco has booted up.
...basically you are binding to events before Umbraco boots. This might have 'worked' before but was causing other issues.
So how do I go about ratifying this? Like I said my code is dependant on this and the only reason I did this in the first place was because I was advised to on here. I'm still fairly new to C# and .Net and to be honest all of this side of things is a little bit confusing to me.
I am assuming I just move the code I have in my Examine Events class inside of the OnApplicationStarted method of AppEvents but do I still pass in the same stuff as I was passing in before?
On another note, you will suffer performance penalties for the way you are coding your event handler:
This call:
Should be:
Because you are re-iterating of this IEnumerable a whole lot of times! especially with the use of Count() and First(). Without ToArray(), your call to Count() will re-iterate the entire ancestors collection... behind the scenes you don't know what that is doing! I suggest using Resharper, it will tell you if you are re-iterating IEnumerable collections which shouldn't be done.
Also, I would very strongly suggest that you don't ever swallow Exceptions. You should at least log the Exception:
If you are just swallowing exceptions (ever), you will never know why things are not working as you intended.
Okay so what I have now done is the following:
Is this the right approach or have I misunderstood?
You didn't add your event binding logic, so your events will never fire. You need to move the logic from the ctor in your
ExamineEvents
to the OnApplicationStarted method of yourAppEvents
.... specifically this block of code:By the way, since you are looking up all ancestors for a single node each time a document is indexed, if you rebuild all and have a lot of nodes, this will be very aweful for performance.
If I add those to my OnApplicationStarted I get the error:
Okay, these suggested changes have now completely broken my application. Here is the final code I now have based upon the suggestions above:
For some reason when I save a Node in the back office, it first seems to run the GatheringContentData method. It then jumps up to the OnApplicationStarted and highlights the:
Following this it jumps backwards and forwards between the two loads of times. When I use the back office Examine searcher tool to look for the node I have just saved, it is present in the index complete with the siteNode field I have added to the index using my code. However, when I run the other part of my application that relies on this or even indexing in general, it now fails.
For instance, if I run the following code:
Nothing is returned anymore. When I check the index, it would seem that for some reason now it is no longer writing my homepage to the index.
Could somebody please point me in the right direction as there is barely any literature on these new methods on Our and my application is dependent on the Indexing working in this way.
The reason I am having to do this in the first place is because the culture of a page doesn't seem to be indexed so I am storing a siteNode against every page so that I can tell which is the root element and apply logic accordingly.
I have now re-engineered this to the following based upon this article however I now find that nothing is being saved to my custom index at all.
http://staheri.com/my-blog/2015/march/custom-examine-indexing-using-umbraco-cache/
My final solution to this issue was this:
is working on a reply...