item.Delete() gives Object reference not set to an instance of an object error in Sitecore - sitecore

In my Sitecore application I have the below statements.
using (new Sitecore.SecurityModel.SecurityDisabler())
{
Item item = database.GetItem(itemId);
if (item != null)
{
item.Delete();
}
}
The item object is not null and in item.Delete(); statement the error occurs.
Can anyone tell whats wrong with this issue?
Updated:
Stack trace
at Sitecore.Tasks.ItemEventHandler.OnItemDeleted(Object sender, EventArgs args)
at Sitecore.Events.Event.EventSubscribers.RaiseEvent(String eventName, Object[] parameters, EventResult result)
at Sitecore.Events.Event.EventSubscribers.RaiseEvent(String eventName, Object[] parameters)
at Sitecore.Events.Event.RaiseEvent(String eventName, Object[] parameters)
at Sitecore.Events.Event.RaiseItemDeleted(Object sender, ItemDeletedEventArgs args)
at Sitecore.Events.Event.DataEngine_ItemDeleted(Object sender, ExecutedEventArgs`1 e)
at System.EventHandler`1.Invoke(Object sender, TEventArgs e)
at Sitecore.Data.Engines.EngineCommand`2.RaiseExecuted()
at Sitecore.Data.Engines.EngineCommand`2.Executed()
at Sitecore.Data.Engines.EngineCommand`2.Execute()
at Sitecore.Data.Engines.DataEngine.DeleteItem(Item item)
at Sitecore.Data.Managers.ItemProvider.DeleteItem(Item item, SecurityCheck securityCheck)
at Sitecore.Data.Managers.ItemManager.DeleteItem(Item item)
at Sitecore.Data.Items.Item.Delete(Boolean removeBlobs)
at Sitecore.Data.Items.Item.Delete()
I have further found that the item is actually got deleted from the Sitecore tree, and then gave the error.

item.Delete() gives Object reference not set to an instance of an object error in Sitecore
Normally this can happen because of security. Maybe the user impersonated does not have read access to the item or the item requires permission in order to be deleted.
Look into using the SecurityDisabler and the UserSwitcher.
in the cookbook you can see a reference to this type of issue: http://sdn.sitecore.net/upload/sitecore6/content_api_cookbook-a4.pdf
there are a couple of snippets of the disabler throughout the PDF. for example on page 12.
Also page 47 talks about the error.
Still I found some cases using the SecurityDisabler does not work. I have an example where the security explicitly prohibit a delete by a normal user. Only the Admin is capable to do such. In this case I'm still getting the error that you are getting even though I'm using the securityDisabler:
/////SNIPPET
...
string userName = #"sitecore\[A USER]";
if (Sitecore.Security.Accounts.User.Exists(userName))
{
Sitecore.Security.Accounts.User user = Sitecore.Security.Accounts.User.FromName(userName, false);
//using (new Sitecore.Security.Accounts.UserSwitcher(user))
using (new Sitecore.SecurityModel.SecurityDisabler())
{
using (new Sitecore.Security.Accounts.UserSwitcher(user))
{
//DO SOMETHING
}
}
}
////END OF SNIPPET
Good luck with your code.
Regards,

I remember that I met this problem few time ago and I resolved it with BeginEdit() and EndEdit(). It's a little bit strange but it works.
Can you change your code to:
using (new Sitecore.SecurityModel.SecurityDisabler())
{
Item item = database.GetItem(itemId);
if (item != null)
{
item.Editing.BeginEdit();
item.Delete();
item.Editing.EndEdit();
}
}

The method which is triggering the exception Sitecore.Tasks.ItemEventHandler.OnItemDeleted tries to Remove "Itemstaks" for that item, from the "taskdatabase"
So the only reason i can guess for this error is your configuration has something wrong. Do you have this section in your config file or include file?:
<TaskDatabase type="Sitecore.Data.$(database).$(database)TaskDatabase, Sitecore.Kernel">
<param connectionStringName="core" />
</TaskDatabase>
Is the related connection string available?

Related

How to configure EXM to create new messages with a custom language version, as default

I am trying to configure the EXM root for an Austrian website to create the new messages with a de-AT language version and to have the de-AT language selected as default.
My question is: How can I configure EXM to automatically create a language version for de-AT when a new message is created?
What I've done so far ..
I managed to achieve having the de-AT selected automatically by playing around with the Language - Select the target language field from the Message Context section of the Standard fields - but the actual message item that is created does not contain the de-AT version - and I am getting an error when trying to save the message.
Error message: Edited language version 'German (Austria)' could not be found. It may have been deleted by another user.
As it can be seen in this screnshot, when I open EXM and I create a new message, the de-AT language version is automatically selected. The problem is that the message has no de-AT language version assigned, so it won't allow to save the item.
I think you missed to add language version to standard values of your message template.
Templates in EXM works in a same way as anywhere in Sitecore. You should have language versions for your emails under:
/sitecore/templates/Email Campaign/Messages
/sitecore/templates/Branches/Email Campaign/Messages
None of the 'tricks' worked to automatically add a new language version when you create a new message inside EXM, therefore I've added a new OnItemSave event which checks if the Item is derived from the base Message template and creates a new language version - based on the own business logic.
Config:
<configuration xmlns:x="http://www.sitecore.net/xmlconfig/">
<sitecore>
<events>
<event name="item:added">
<handler type="ABC.SitecoreExtensions.Handlers.EmailExperienceExtensions, ABC" method="OnItemAdded" />
</event>
</events>
</sitecore>
Code
namespace ABC.SitecoreExtensions.Handlers
{
class EmailExperienceExtensions
{
readonly Sitecore.Data.Database masterDb = Sitecore.Configuration.Factory.GetDatabase("master");
private const string EXM_BASE_EMAIL_TEMPLATE_ID = "{A0EA9681-5C86-43AB-80F7-C522DADF6F12}";
public void OnItemAdded(object sender, EventArgs args)
{
Assert.ArgumentNotNull((object)args, "args");
Item obj1 = Event.ExtractParameter(args, 0) as Item;
if (obj1 == null)
return;
if (obj1.IsDerived(new Sitecore.Data.ID(EXM_BASE_EMAIL_TEMPLATE_ID )))
{
//logic to determine the context site and to pickup the language
....
if (rootItem == null)
{
return;
}
var siteContext = SiteContext.GetSite(rootItem.Name);
var lang = LanguageManager.GetLanguage(siteContext.Language);
Item ca = masterDb.GetItem(obj1.Paths.FullPath, lang);
using (new Sitecore.SecurityModel.SecurityDisabler())
{
try
{
if (0 == ca.Versions.Count)
{
ca.Versions.AddVersion();
}
}
catch (Exception ex)
{
// catch exception
}
}
}
}
}
}

Sitecore goals for Media Item don't affect engagement value

I use Sitecore 7.2 revision 140526 + DMS. I'm trying to assign goal to the media item (PDF). When I try to download this media item the goal get registered in the PageEvents table but Engagement Value of the visit does not change. I found following code inside StartTrackingProcessor:
Tracker.CurrentPage.OnCancel += (EventHandler)((obj, args) =>
{
AcceptChangesArgs acceptChangesArgs = args as AcceptChangesArgs;
if (acceptChangesArgs == null)
return;
VisitorDataSet.VisitsRow currentVisit = acceptChangesArgs.Visitor.CurrentVisit;
if (currentVisit == null)
return;
Tracker.CurrentPage.RollBackValue(pageEventData, currentVisit);
});
This code prevents engagement value from increasing for the pages that have been cancelled somewhere in the pipeline.
And then I found the code that cancel the page in the Sitecore.Analytics.RobotDetection.Media.MediaRequestEventHandler whech is enabled by Sitecore.Analytics.RobotDetection.config:
using (new ContextItemSwitcher(obj))
{
try
{
this.StartTracking();
VisitorDataSet.PagesRow previousPage = Tracker.CurrentVisit.PreviousPage;
if (previousPage != null)
{
Guid pageId = previousPage.PageId;
foreach (VisitorDataSet.PageEventsRow pageEventsRow in Enumerable.ToArray<VisitorDataSet.PageEventsRow>(Tracker.CurrentPage.PageEvents))
pageEventsRow.PageId = pageId;
Tracker.CurrentPage.Cancel();
}
this.EndTracking();
}
catch (Exception ex)
{
Log.Error("Media request analytics failed", ex, this.GetType());
}
}
So this MediaRequestEventHandler cancels the page and therefore engagement value does not increase. I can override this behavior or disable RobotDetection.config but I want to understand the consequences and why it was done this way and I know there are recommendations not to disable Sitecore.Analytics.RobotDetection.config
So my question: what is the best way to assign points to the visit for media item download?
For those who might come across the same problem here is the response from sitecore support. This behavior was reported as a bug and as a workaround they suggested to comment out following lines in Sitecore.Analytics.RobotDetection.config:
<event name="media:request">
<handler patch:instead="*[#type='Sitecore.Analytics.Media.MediaRequestEventHandler, Sitecore.Analytics']" type="Sitecore.Analytics.RobotDetection.Media.MediaRequestEventHandler, Sitecore.Analytics.RobotDetection" method="OnMediaRequest"/>
</event>

Tracking a Page Event from ASHX Handler

Im currently trying to track a PageEvent within a ASHX Handler. My code basically looks like this:
public class GetProductPdf : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
if (!Tracker.IsActive)
{
Tracker.Initialize();
Tracker.StartTracking();
}
//Track PageEvent here...
}
public bool IsReusable
{
get
{
return false;
}
}
}
The Tracker is always inactive and Tracker.Current == null. On method call "Tracker.StartTracking();" the following Exception is thrown:
[InvalidOperationException: Tracker.Current is not initialized]
Sitecore.Analytics.Pipelines.StartAnalytics.StartTracking.Process(PipelineArgs args) +317
(Object , Object[] ) +83
Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args) +445
Project.Web.Handler.PdfCreation.GetProductPdf.ProcessRequest(HttpContext context) in d:\Project\Website\Handler\PdfCreation\GetProductPdf.ashx.cs:69
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +913
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +165
I tried all possible solutions suggested here.
When doing the same in a mvc controller the Tracker is active and Tracker.Current != null.
Does anyone has an idea, what could cause this or are there any other suggestions for a solution?
Thanks in advance.
I am not certain that your Ashx Handler can be executed within the necessary Sitecore Context so that Tacker.Current will not be valid nor can be started via Tracker.StartTracking(). Someone might be able to confirm but I have another solution you can try which works for me.
As nice as it would be for the Ashx Handler to register the Event for you, instead you can fire a JavaScript function on the link to the file. So that when the link is clicked the JavaScript makes a web request to a MVC Controller and the controller registers the event for you.
I have implemented this myself using WebApi Controllers. Data Attributes were on the a tag, JavaScript posted those attributes to the controller, the controller used those attributes to determine which Event to register and the description to use on the Event.
<asp:HyperLink runat="server" data-goalid="{08030449-A811-428B-95F0-59FCD42B8DEB}" data-goaldescription="Product 0112 brochure">
[System.Web.Mvc.HttpPost]
public JsonResult RegisterGoal(string goalId, string goalDescription)
{
Item eventItem = Sitecore.Context.Database.GetItem(goalId);
var goal = new PageEventItem(eventItem);
var eventData = Tracker.Current.PreviousPage.Register(goal);
eventData.Data = goal["Description"] + " " + goalDescription;
Tracker.Current.Interaction.AcceptModifications();
return Json(new PageEventRequestResult()
{
Success = true,
Message = "Successfully registered goal",
});
}
It works really well. The only downside is having to add it to the various links that lead to the files you want to track.
I wrote a blog about tracking various interactions on a site and registering Sitecore Events / Goals you might want to look at, scroll down to the 'Storing custom data in xDB' section.

Sitecore automatically sets publishing restrictions on item when edited

Our instance of Sitecore is auto setting a publishing restriction on the item with the current date/time when a user selects Edit. This only appears to happen when RequireLockBeforeEditing=true. Is this expected behavior? Why does this happen and is there a way to turn it off?
<setting name="RequireLockBeforeEditing" value="true" /> is the default setting and will result in a new item Version being placed into Draft when the author selects Edit. In this senario, it's normal for Sitecore to assign a Publishable From date/time to the new version. This is not so much a restriction as it is a date/time stamp of when that version was created.
The date is needed as it is used to determine which version should be live. If there is no "from" date set, the version will not be publishable.
As for your custom code, if you post it here, I may be able to help you avoid it conflicting with Sitecore's default behavior. There may be some simple checks that you can do such as ignoring the Edit if the publishable from date matches the last updated date.
EDIT:
Instead of modifying Sitecore's default behavior (which will probably bite you later on) consider checking to see if the item being edited is brand new. When a new version is added, the item's created date and Valid from fields will match.
public void OnItemSaving(object sender, EventArgs args)
{
try
{
Item item = Event.ExtractParameter(args, 0) as Item;
ItemChanges itemChanges = Event.ExtractParameter(args, 1) as ItemChanges;
// Ensure that a change was made to the valid to/from fields
if (item != null &&
itemChanges != null &&
itemChanges.FieldChanges.ContainsAnyOf(FieldIDs.ValidFrom, FieldIDs.ValidTo))
{
// Ensure that the item is not brand new (such as when an author locks or clicks Edit)
if (item.Publishing.ValidTo != DateTime.MaxValue ||
item.Publishing.ValidFrom.ToString("MMddyyyyHHmmss") !=
item.Statistics.Created.ToString("MMddyyyyHHmmss"))
{
// Do work here...
}
}
}
catch (Exception ex)
{
Log.Error("Error in item:saved event", ex, this);
}
}

Server Error "Object reference not set to an instance of an object" after insert from branch

Everything works correctly but after Sitecore update from 7.0 to 7.2 I see the following Server Error when creating a site from a branch
[NullReferenceException: Object reference not set to an instance of an object.]
Sitecore.Nexus.Data.DataCommands.AddFromTemplateCommand.(Item , Item , String , ID , ID , String , SafeDictionary`2 ) +420
Sitecore.Nexus.Data.DataCommands.AddFromTemplateCommand.(Item , Item , String , ID , ID , String , SafeDictionary`2 ) +856
Sitecore.Nexus.Data.DataCommands.AddFromTemplateCommand.(String , Item , Item , ID ) +569
Sitecore.Data.Engines.DataCommands.AddFromTemplateCommand.DoExecute() +113
Sitecore.Data.Engines.EngineCommand`2.Execute() +121
Sitecore.Data.Engines.DataEngine.AddFromTemplate(String itemName, ID templateId, Item destination, ID newId) +101
Sitecore.Data.Managers.ItemProvider.AddFromTemplate(String itemName, ID templateId, Item destination, ID newId) +363
Sitecore.Data.Managers.ItemManager.AddFromTemplate(String itemName, ID templateId, Item destination, ID newItemId) +203
Sitecore.Data.Managers.ItemManager.AddFromTemplate(String itemName, ID templateId, Item destination) +286
Sitecore.Data.Items.Item.Add(String name, BranchId branchId) +110
Sitecore.Workflows.WorkflowContext.AddItem(String name, BranchItem branch, Item parent) +279
Sitecore.Shell.Framework.Commands.AddMaster.Add(ClientPipelineArgs args) +803
[TargetInvocationException: Exception has been thrown by the target of an invocation.]
System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) +0
System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) +76
System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture) +211
System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters) +35
Sitecore.Nexus.Pipelines.NexusPipelineApi.Resume(PipelineArgs args, Pipeline pipeline) +398
Sitecore.Web.UI.Sheer.ClientPage.ResumePipeline() +285
Sitecore.Web.UI.Sheer.ClientPage.OnPreRender(EventArgs e) +547
Sitecore.Shell.Applications.ContentManager.ContentEditorPage.OnPreRender(EventArgs e) +25
System.Web.UI.Control.PreRenderRecursiveInternal() +113
System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +4297
A site creates correctly and I see no problems there.
As far as I see the error occurs in the item:addmaster command:
<command name="item:addmaster" type="Sitecore.Shell.Framework.Commands.AddMaster,Sitecore.Kernel" />
I have tried to decompile Sitecore.Nexus library but without any success. After some of hours of the investigation I found that the error disappears if turn off a custom event handler
<event name="item:created">
<handler type="App.Client.Tasks.ItemEventHandler, App.Client" method="OnItemCreated" />
</event>
The handler is responsible for auto mapping configuration settings in a new site created from a branch. Technically there is an item in branch template called Mapper and it works as a trigger. It is the last item in the branch tree. So when an admin adds a site from a branch, event handler checks that the Mapper is created (in other words a site is created), runs auto mapping functionality and deletes the trigger.
If to omit all checks, the handler looks like
new ItemMappingManager(contextItem, Database.GetDatabase("master").Items[ID.Parse(MappingConfigurationItemId)]).Execute();
// delete the trigger item once the branch has been created and mapping is done
using (new SecurityDisabler())
{
contextItem.Delete();
}
Looks like something changed in the Sitecore's event model but I have a lack of knowledge here.
Try wrapping any calls to Sitecore.Data.Engines.DataEngine.AddFromTemplate or any calls that you are making that add an item with an EventDisabler. Because the exception is being thrown in Nexus, it's difficult to say what the exact cause of the issue is.
When I experienced a similar issue, I had a theory that there may have been some eventing that was firing and causing the exceptions. The error did not always occur, and it was difficult to find the cause of the error since it was being thrown in Nexus. While investigating and debugging as best I could (deobfuscated, decompiled and read through and debugged into Nexus), I found that there were several API calls being made that raise events (e.g. AddVersion, AddMaster, etc.). I considered my theory confirmed when the exception disappeared after I wrapped my code in an EventDisabler.
My Similar Experience
I just experienced nearly the same issue with Sitecore 8.1.2. The difference between my code and the code in the OP is that I am leveraging the new (I believe newer than the OP) ItemProvider via a processor that I have added to the AddFromTemplate pipeline.
The below is the processor that I added. I use this processor to run rules, and I was receiving the exact same error, until I wrapped my call to Sitecore.Data.Engines.DataEngine.AddFromTemplate (must be called or else the item never actually gets created) in an EventDisabler.
Processor Before Fix
public override void Process([NotNull] AddFromTemplateArgs args)
{
ID id;
if (args.Aborted
|| string.IsNullOrWhiteSpace(RuleFolderId)
|| !Settings.Rules.ItemEventHandlers.RulesSupported(args.Destination.Database)
|| !ID.TryParse(RuleFolderId, out id))
{
return;
}
Assert.HasAccess(args.Destination.Access.CanCreate(), "You do not have permission to create items here.");
// exception thrown from this call, which is a required call for this
// processor, or else the item will not actually be created
var item = args.Destination.Database.Engines.DataEngine.AddFromTemplate(
args.ItemName,
args.TemplateId,
args.Destination,
args.NewId);
args.ProcessorItem = item;
args.Result = item;
var ruleContext = new PipelineArgsRuleContext<AddFromTemplateArgs>(args);
RuleManager.RunRules(ruleContext, id);
}
Processor with fix
public override void Process([NotNull] AddFromTemplateArgs args)
{
ID id;
if (args.Aborted
|| string.IsNullOrWhiteSpace(RuleFolderId)
|| !Settings.Rules.ItemEventHandlers.RulesSupported(args.Destination.Database)
|| !ID.TryParse(RuleFolderId, out id))
{
return;
}
Assert.HasAccess(args.Destination.Access.CanCreate(), "You do not have permission to create items here.");
using (new EventDisabler()) // fixes the exception from nexus
{
var item = args.Destination.Database.Engines.DataEngine.AddFromTemplate(
args.ItemName,
args.TemplateId,
args.Destination,
args.NewId);
args.ProcessorItem = item;
args.Result = item;
}
var ruleContext = new PipelineArgsRuleContext<AddFromTemplateArgs>(args);
RuleManager.RunRules(ruleContext, id);
}
Additional Observations
The error was only experienced about 33% of the time and only when adding an item from a branch template programmatically (never occurred when adding from the UI). The exact location of the error also appeared to change each time, and I was not able to find the source of this randomization.