Sitecore context in HttpHandler - sitecore

I have HttpTaskAsyncHandler in my sitecore solution and i call it I have sutup IngnoreUrlPrefix and etc.
By some reason i can't get access to SC.Context.Database Database is null in ProcessRequestAsync(HttpContext context) method,
it looks like I don't access to Sitecore context in HttpHandler.
How to resolve it ?
Thanks.

You wont be able to access Sitecore Context (Database or Item) in the Handler. We have confirmed this with Sitecore Support for our task.
The best way is Implement a Processor in the Request pipeline begin.
How to Implement
Inherit HttpRequestProcessor in your class found in (using Sitecore.Pipelines.HttpRequest;)
and add that Processor after SiteResolver in < httpRequestBegin >
<processor type="Sitecore.Pipelines.HttpRequest.SiteResolver, Sitecore.Kernel" />
<!-- Custom Module -->
<processor type="SND641.Customization.RobotsModule, SND641" />

If you choose to ignore your script file (by using IgnoreUrlPrefix), then you it will not be processed by Sitecore's request pipeline and thus will not have a Sitecore context.
I think you can solve it by removing your url prefix from IgnoreUrlPrefix and make sure the file extension of your handler is added to the allowed extensions parameter of the FilterUrlExtensions pipeline processor:
<processor type="Sitecore.Pipelines.HttpRequest.FilterUrlExtensions, Sitecore.Kernel">
<param desc="Allowed extensions (comma separated)">aspx</param>
</processor>
This way you can call your script and still have Sitecore process all the pipelines.

You can get context without pipeline. Along with web.config handler definition, you will need to add under customHandler. It helps in getting sitecore context. E.g
<customHandlers>
<handler trigger="blogfeed.xml" handler="blogfeed.xml" />
</customHandlers>

I'm sorry if I'm not getting exactly what you are trying to do. But by working with handlers I did have issues that my code was not able to access the sitecore object even when I updated the web.config and
I noticed that my handler was like this:
public class GetHandler: IHttpHandler
{
...
}
by adding the System.web.SessionState.IrequiresSessionStatem, like this:
public class GetHandler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{....}
then everything started to work and I was able to get items from sitecore without issues:
Public void ProcessRequest(HttpContext context)
{
Database webdb = Factory.GetDatabase("web");
}
previous my change the webdb was coming with nothing and the code was coming back with "Command "Sitecore.Database" is not valid"
after that changes, as I said, everything worked for me.
I hope this helps and adds some value to the existing answers.
regards,

Related

Sitecore > Disable html caching of a rendering

I am trying to upgrade the old project(based on storefront for Sitecore 8.0) to version Sitecore 8.1(latest one at the moment).
During this process I faced with a problem when I see the same products for all categories. So, for example, I select a category first time and see correct products. After that I choose any other category, but still see the same products(from the first category).
These data are returned by ProductList rendering(a controller rendering) and it is not run after the first call anymore(tried to reach corresponding action in a CatalogController in debug mode).
If we clear all caches(..sitecore/admin/cache.aspx) - then it works again, but only first time.
I understand that I can't disable caching for the whole site, I need to do it for this generic page(with "*" in item name) where the commerce data are shown - so for all categories and product pages. I checked this rendering in design mode and can see that all checkboxes related to cache are unchecked at the moment. Don't know what I have missed.
Thank you in advance for the help.
I believe you have caching enabled on control/sublayout defintion level which will cause to cache that rendering on every page on the site, a while ago i was able to come up with a solution to disable caching for a specific rendering/sublayout on specific pages, while keeping it caching on other pages.
I basically created a new rendering parameter template with checkbox "Cancel Cache Settings", then in my rendering definition item, I set the parameter template to the new template, if your site runs on Sitecore MVC, do the following:
Create a class called 'SetCacheability'
namespace Sitecore.SharedResources.Pipelines.Rendering
{
public class SetCacheability : Sitecore.Mvc.Pipelines.Response.RenderRendering.SetCacheability
{
protected override bool IsCacheable(Sitecore.Mvc.Presentation.Rendering rendering, Sitecore.Mvc.Pipelines.Response.RenderRendering.RenderRenderingArgs args)
{
if (!String.IsNullOrEmpty(rendering.Parameters["Cancel Cache Settings"])
&& rendering.Parameters["Cancel Cache Settings"] == "1")
{
return false;
}
return base.IsCacheable(rendering, args);
}
}
}
Create the patch config file in your include folder:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<mvc.renderRendering>
<processor patch:instead="processor[#type='Sitecore.Mvc.Pipelines.Response.RenderRendering.SetCacheability, Sitecore.Mvc']"
type="Sitecore.SharedResources.Pipelines.Rendering.SetCacheability, [YOUR ASSEMBLY NAME]"/>
</mvc.renderRendering>
</pipelines>
</sitecore>
</configuration>
Here is the blog i wrote on this: http://www.sitecorecoding.com/2014/09/disabling-caching-for-rendering-on-some.html
Hope this helps
The caching settings you've disabled are located in the presentation details on the control level:
Additionally, you should ensure that caching is disabled on your sublayout (or rendering) definition (under /sitecore/Layout/Sublayouts):

Sitecore 8 throwing null exception when Datasource item does not exist

I am facing the below problem and can't find out how to get around to it.
I have a rendering and its datasource is pointing to an item in the tree.
I publish the rendering but I don't publish the referenced item.
While viewing the page I get an error. [attached is the screen shot of the error i am getting]
I am using glass mapper.
Thanks in advance for your help.
The best solution would be to tap into the mvc.getRenderer pipeline and validate the datasource actually exists, otherwise fallback gracefully.
There are a number of solutions already proposed for this and is a known "issue", although it is not a Glass specific issue:
Sitecore - automated validation of MVC rendering DataSource
Rendering Exception Handling - The Right Way
Robust MVC Rendering Exception Handler
HANDLING RENDERING EXCEPTIONS IN MVC SOLUTIONS WITH THE SITECORE ASP.NET CMS
All these solutions check if the datasource item exists, in normal mode the error is swallowed but in Page Editor mode a warning is displayed to the editors so show the fact that datasource needs to be set in cases where none has been selected.
It was also raised as an issue in Glass Mapper with a similar solution.
To elaborate jammykam's answer, you can do something like the code below which I have found in this blog
Config Patch:
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<pipelines>
<mvc .getrenderer="">
<processor patch:instead="processor[#type='Sitecore.Mvc.Pipelines.Response.GetRenderer.GetViewRenderer, Sitecore.Mvc']" type="Namespace.To.Sitecore.Pipelines.Response.GetRenderer.GetViewRendererWithItemValidation, Library">
</processor>
</mvc>
</pipelines>
</sitecore>
</configuration>
Code:
public class GetViewRendererWithItemValidation : GetViewRenderer
{ `
protected override Renderer GetRenderer(Rendering rendering, GetRendererArgs args)
{
var viewRenderer = base.GetRenderer(rendering, args) as ViewRenderer;
if (viewRenderer == null)
return null;
// Ignore item check when in page editor
// Also this will break if the item for the datasource has been deleted without removing the link.
if (Context.PageMode.IsPageEditor || Context.PageMode.IsPageEditorEditing)
return viewRenderer;
// Override renderer to null when there is an unpublished item refererenced by underlying view
return viewRenderer.Rendering.Item != null && viewRenderer.Rendering.RenderingItem.InnerItem != null
? viewRenderer
: null;
}
}

Perform logic when specific template is published

I have a template set up that I need to perform some logic on when it's published. When an item based on this template is published they want me to perform some basic CRUD operations on a table in an external database so everything is in sync. But that's kind of beside the point.
What I have set up right now is a new processor in the publishItem pipeline. I've found I can access the PublishItemContext.PublishOptions.RootItem to access the template, which I can compare on and perform logic as necessary. The problem is with so called deep publishes. I'm only seeing my processor firing for the root item, not for any of the sub items.
So, my questions is if there is a way to access every item that's being published, not just the root item?
A co-worker suggested I grab timestamps at the beginning of the pipeline and the end, and use the HistoryManager to check on what all has changed... but that seems pretty heavy-handed to me. I can't help but feel like there ought to be a property or setting nested in here somewhere where I can access everything that's being published.
I'd appreciate any assistance you folks can offer.
Oh, we're on version 6.5 for this project, I'm sure that'll be relevant.
Looks like you'll want to add a handler node to
<event name="publish:end">
event in the web.config. Documentation can be found here: http://sdn.sitecore.net/articles/api/using%20events.aspx
You can use `publish:itemProcessed' event:
<event name="publish:itemProcessed">
<handler
type="My.Assembly.Namespace.ItemProcessedProcessor, My.Assembly"
method="ItemProcessed">
</handler>
</event>
And then use args.Context.VersionToPublish:
using System;
using Sitecore.Data;
using Sitecore.Publishing.Pipelines.PublishItem;
namespace My.Assembly.Namespace
{
public class ItemProcessedProcessor
{
private static readonly ID ChosenTemplateID = ID.Parse("{ID-SHOULD-BE-HERE}");
public void ItemProcessed(object sender, EventArgs args)
{
ItemProcessedEventArgs itemProcessedEventArgs = args as ItemProcessedEventArgs;
PublishItemContext context = itemProcessedEventArgs != null ? itemProcessedEventArgs.Context : null;
if (context != null && context.VersionToPublish != null)
{
if (context.VersionToPublish.Template.ID == ChosenTemplateID)
{
// do the logic here
}
}
}
}
}
Well, as it turns out, my problem was not nearly as complicated as I expected. As was pointed out to me, of course looking at PublishItemContext.PublishOptions.RootItem will only return the root item. The processor actually is being hit by each item being published, I'm just looking at the wrong field.
var item = PublishItemContext.PublishHelper.GetSourceItem(context.ItemId);
This gets me what I need.
PEBKAC

How to prevent Sitecore modal dialog from redirecting user to new item?

I’m stuck with a little development annoyance. I have crated an application to extend Sitecore authoring interface.
The application queries some internal services and asks few additional questions from a content author before creating an new content item in Sitecore.
I have modeled the app on (Sitecore.Shell.Applications.Templates.CreateTemplate.CreateTemplateForm).
The problem I’m having is, as soon as an item is created my WizardForm is reloaded to load newly created item.
What I want is for the wizard to go through to the “Final” page and reload the main UI once the modal dialog is closed.
Exactly how new OOTB template wizard works. I know that if I comment my item creation code out the UI behaves as expected.
Looks like a create of an item generates some events in the background that UI is responding to and reloads my modal dialog with the newly created item. (I have tried the following solutions http://sdn.sitecore.net/Forum/ShowPost.aspx?postid=29092, http://sdn.sitecore.net/Forum/ShowPost.aspx?postid=29968, however this does not seem to solve it for me).
The original code seems to disable events like so:
this.CreateTemplatePicker.DisableEvents();
TemplateItem templateItem = Client.ContentDatabase.Templates.CreateTemplate(this.TemplateName.Value, selectionItem);
this.CreateTemplatePicker.EnableEvents();
I have tried the following:
Client.Site.Notifications.Disabled = true;
var item = container.Add(ItemUtil.ProposeValidItemName(this.Title.Value), Settings.ProductImageTemplateID);
Client.Site.Notifications.Disabled = false;
AND OLSO
Item item;
using (new EventDisabler())
{
item = container.Add(ItemUtil.ProposeValidItemName(this.Title.Value), Settings.ProductImageTemplateID);
}
All with the same result. The wizard modal dialog is reloaded as soon as I get to the page where the item is created.
Using fiddler I can see the command to reload the windows is sent to the client. I just cant figure out how do I tell Sitecore UI to ignore the event(s) or alternatively prevent event(s) from being generated in the first place. The first command being sent to the UI below tells the page to load Content Editor, exactly the thing I'm trying to prevent.
{"commands":[
{"command":"SetLocation","value":"/sitecore/shell/sitecore/content/Applications/Content%20Editor.aspx?fo=%7b186F686E-A8FF-4303-B59F-4D284A5A0196%7d&db=master&id=%7B186F686E-A8FF-4303-B59F-4D284A5A0196%7D&la=en&vs=1"},
{"command":"SetDialogValue","value":"{186F686E-A8FF-4303-B59F-4D284A5A0196}"},
{"command":"SetStyle","value":"none","id":"Constraints","name":"display"},
{"command":"SetStyle","value":"","id":"LastPage","name":"display"},
{"command":"SetAttribute","value":true,"id":"NextButton","name":"disabled"},
{"command":"SetOuterHtml","value":"<button id=\"CancelButton\" class=\"scButton\" TabIndex=\"0\" onclick=\"javascript:return scForm.postEvent(this,event)\" onkeydown=\"javascript:scForm.handleKey(this, event, null, '32')\">Finish</button>","id":"CancelButton"},
{"command":"Focus","value":"CancelButton","scrollintoview":"0"},{"command":"Eval","value":"scUpdateWizardControls();"},
{"command":"SetAttribute","value":true,"id":"BackButton","name":"disabled"},{"command":"Eval","value":"scAlignWizardButtons()"}
]}
Just a little info about my Sitecore environment:
Sitecore started
Sitecore.NET 7.0. (rev. 130810)
C:\Inetpub\wwwroot\sc71\Website\bin\Sitecore.Client.dll (Sitecore CMS, Sitecore Client Application, 7.0 rev. 130810)
C:\Inetpub\wwwroot\sc71\Website\bin\Sitecore.Kernel.dll (Sitecore CMS, Sitecore CMS Kernel Library, 7.0 rev. 130810)
C:\Inetpub\wwwroot\sc71\Website\bin\Sitecore.Nexus.dll (Sitecore.Nexus)
Operating system Microsoft Windows NT 6.2.9200.0
Microsoft.NET version 4.0.30319.18051
Process id: 8040
Windows identity used by the process: NT AUTHORITY\NETWORK SERVICE. Impersonation: False
Managed pipeline mode: Integrated
In the end the problem only affected bucketable items. No need to disable event or anything, that was a red herring. However, in my case I am working with buckets and bucketable items, so I needed to get it fixed.
The offending code ended being Sitecore.Buckets.Commands.AddFromTemplateCommand(). Thanks to Sitecore support engineers for getting to the bottom of this. A proposed workaround, that worked for me is as follow. This have been reported to Sitecore development team and I guess will be resolved at some stage in a future release of Sitecore. The current (at the time of writing) version Sitecore.NET 7.0. (rev. 130810) is affected.
You will need to substitute existing implementation with your own (see code below). To replace existing implementation overwrite the following configuration /App_Config/Includes/Sitecore.Buckets.config file at /sitecore/databases/database[#id="master"]. I ended up creating a configuration patch file that looked like this.
Configuration:
<?xml version="1.0"?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<databases>
<database id="master" singleInstance="true" type="Sitecore.Data.Database, Sitecore.Kernel">
<Engines.DataEngine.Commands.AddFromTemplatePrototype>
<obj patch:instead="obj[#type='Sitecore.Buckets.Commands.AddFromTemplateCommand, Sitecore.Buckets']"
type="Sitecore.Support.Buckets.Commands.AddFromTemplateCommand, MyAssembly"/>
</Engines.DataEngine.Commands.AddFromTemplatePrototype>
</database>
</databases>
</sitecore>
</configuration>
Code:
using Sitecore.Data.Items;
using Sitecore.Text;
using Sitecore.Web.UI.Sheer;
using System;
using System.Web;
namespace Sitecore.Support.Buckets.Commands
{
public class AddFromTemplateCommand : Sitecore.Buckets.Commands.AddFromTemplateCommand
{
protected override Sitecore.Data.Engines.DataCommands.AddFromTemplateCommand CreateInstance()
{
return new AddFromTemplateCommand();
}
protected override void SetLocation(Data.Items.Item item)
{
if ((HttpContext.Current != null) && (Context.ClientPage != null))
{
// This condition is set to go around an issue when a bucket item is created from within a custom wizard app.
// Replace the specified path with your own one.
if (Sitecore.Context.RawUrl != null && !Sitecore.Context.RawUrl.Contains("/sitecore/shell/Applications/Issues/Create Product Bucket.aspx"))
{
UrlString str = new UrlString(Sitecore.Buckets.Util.Constants.ContentEditorRawUrlAddress);
str.Add(Sitecore.Buckets.Util.Constants.OpenItemEditorQueryStringKeyName, item.ID.ToString());
item.Uri.AddToUrlString(str);
UIUtil.AddContentDatabaseParameter(str);
SheerResponse.SetLocation(str.ToString());
}
}
}
}
}

Castle MonoRail & ELMAH

Is anyone using Castle MonoRail and ELMAH with success?
We are using a number of Resuces to present users with friendly error messages, but if we do this the exceptions never get as far as ELMAH as the MonoRail rescue intercepts them.
Ideally we want the user to see the rescue, but for the exception to be logged in ELMAH.
Any ideas/pointers?
Cheers,
Jay.
After looking at the links Macka posted, I wrote this simple monorail exception handler:
public class ElmahExceptionHandler : AbstractExceptionHandler {
public override void Process(IRailsEngineContext context) {
ErrorSignal.FromCurrentContext().Raise(context.LastException);
}
}
Then I registered it in web.config, monorail section:
<monorail>
<extensions>
<extension type="Castle.MonoRail.Framework.Extensions.ExceptionChaining.ExceptionChainingExtension, Castle.MonoRail.Framework"/>
</extensions>
<exception>
<exceptionHandler type="MyNamespace.ElmahExceptionHandler, MyAssembly"/>
</exception>
...
</monorail>
And that's it.
After also posting on Google Groups it looks like Atif may have pointed me in the right direction.
You might want to look into error
signaling in ELMAH. It is designed for
scenarios where you want to pass an
exception through ELMAH's pipeline
even if it is being handled/swallowed.
Here are some pointers to get started
with error signaling:
http://code.google.com/p/elmah/wiki/DotNetSlackersArticle#Error_Signa...
http://code.google.com/p/elmah/wiki/DotNetSlackersArticle#Signaling_e...
-Atif