Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jason Espin 368 posts 1335 karma points
    Aug 25, 2015 @ 15:14
    Jason Espin
    0

    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?

    Any help would be greatly appreciated.

  • Ismail Mayat 4511 posts 10091 karma points MVP 2x admin c-trib
    Aug 25, 2015 @ 15:19
    Ismail Mayat
    0

    Jason,

    Any issues in the umbracolog? The latest version of Umbraco I have used is 7.2.4.

    Regards

    Ismail

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Aug 25, 2015 @ 15:21
    Shannon Deminick
    0

    yes, it's because you are binding to events on your ctor:

     ExamineManager.Instance.IndexProviderCollection["ExternalIndexer"].GatheringNodeData += ExamineEvents_GatheringNodeData;
     ExamineManager.Instance.IndexProviderCollection["AxumIndexer"].GatheringNodeData += ExamineEvents_GatheringNodeData;
    

    You should never really do that. ApplicationBase is super old and shouldn't be used anymore

    You should move all of that logic to your AppEvents and bind to events inside of started.

  • Jason Espin 368 posts 1335 karma points
    Aug 25, 2015 @ 15:23
    Jason Espin
    0

    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

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Aug 25, 2015 @ 15:26
    Shannon Deminick
    0

    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.

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Aug 25, 2015 @ 15:22
    Shannon Deminick
    0

    ...basically you are binding to events before Umbraco boots. This might have 'worked' before but was causing other issues.

  • Jason Espin 368 posts 1335 karma points
    Aug 25, 2015 @ 15:27
    Jason Espin
    0

    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?

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Aug 25, 2015 @ 15:30
    Shannon Deminick
    0

    On another note, you will suffer performance penalties for the way you are coding your event handler:

    This call:

     IEnumerable<IContent> ancestors = cs.GetAncestors(nodeId);
    

    Should be:

     IEnumerable<IContent> ancestors = cs.GetAncestors(nodeId).ToArray();
    

    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.

  • Jason Espin 368 posts 1335 karma points
    Aug 25, 2015 @ 15:31
    Jason Espin
    0

    Okay so what I have now done is the following:

    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);
                                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);
                }
            }
        }
    

    Is this the right approach or have I misunderstood?

  • Shannon Deminick 1526 posts 5272 karma points MVP 3x
    Aug 25, 2015 @ 15:38
    Shannon Deminick
    0

    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:

     ExamineManager.Instance.IndexProviderCollection["ExternalIndexer"].GatheringNodeData += ExamineEvents_GatheringNodeData;
     ExamineManager.Instance.IndexProviderCollection["AxumIndexer"].GatheringNodeData += ExamineEvents_GatheringNodeData;
    

    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.

  • Jason Espin 368 posts 1335 karma points
    Aug 25, 2015 @ 15:49
    Jason Espin
    0

    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
    
  • Jason Espin 368 posts 1335 karma points
    Aug 25, 2015 @ 16:27
    Jason Espin
    0

    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.

    For instance, if I run the following code:

            ISearchCriteria criteria = AxumSearcher.CreateSearchCriteria();
            IBooleanOperation query = criteria.NodeTypeAlias("homepage");
    
            ISearchResults results = AxumSearcher.Search(query.Compile());
    

    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.

  • Jason Espin 368 posts 1335 karma points
    Aug 26, 2015 @ 08:55
    Jason Espin
    0

    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());
            }
        }
    }
    

    http://staheri.com/my-blog/2015/march/custom-examine-indexing-using-umbraco-cache/

  • Jason Espin 368 posts 1335 karma points
    Aug 26, 2015 @ 10:31
    Jason Espin
    100

    My final solution to this issue was this:

    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 class ExamineEvents
        {
            public static void GatheringContentData(object sender, IndexingNodeDataEventArgs e, UmbracoHelper helper)
            {
                try
                {
                    var content = helper.TypedContent(e.NodeId);
                    var homepage = content.AncestorOrSelf("homepage");
                    e.Fields.Add("siteNode", homepage.Id.ToString());
                }
                catch (System.NullReferenceException ex)
                {
                    if (e.Fields["level"] != "1")
                    {
                        IContentService cs = ApplicationContext.Current.Services.ContentService;
                        IContent[] unpublishedPageAncestors = cs.GetAncestors(e.NodeId).ToArray();
                        if (unpublishedPageAncestors.Where(x => x.ContentType.Alias.ToLower() == "homepage").Count() == 1)
                        {
                            int id = unpublishedPageAncestors.First().Id;
                            e.Fields.Add("siteNode", id.ToString());
                        }
                    }
                    else
                    {
                        e.Fields.Add("siteNode", e.Fields["id"]);
                    }
                }
                catch (Exception ex)
                {
                    // Do Nothing
                }
            }
        }
    
Please Sign in or register to post replies

Write your reply to:

Draft