Programmatically skip publishing of item(s) in Sitecore

by aboo bolaky 23. July 2009 05:43

Scenario

Assume that you have a set of items (say..Product items) (sitting anywhere within the /sitecore/content..) based on a specific template. The requirement here is that

"A Product cannot be published if one of its fields (ProductID) isn't populated."

Background

To achieve this, we need to hook into the publish:itemProcessing event in the web.config. This event gets triggered every time an item is published. The general steps involved in this situation are:

  • Create a class with a method that adheres to the EventHandler delegate signature. Whenever you initiate a publish operation in sitecore (be it smart publish, incremental or full publish), the method will be called (depending on how many items that need to be published)
  • Modify the web.config to subscribe to ItemPublishing event

ItemPublisher Class

namespace Test.Events 
{
	public class ItemPublisher
	{
	   public void CheckProcessing(object sender, EventArgs args)
		{
		  ItemProcessingEventArgs theArgs = args as ItemProcessingEventArgs;
						
		  Item currentItem = theArgs.Context.PublishHelper.GetSourceItem(theArgs.Context.ItemId);

		  if ((currentItem != null) && (currentItem.Paths.IsContentItem))
		  {
			  //Template ID of item on which selective publishing is to be applied
			 if (currentItem.TemplateID == new ID("{9C9A2F3D-652A-4490-AB57-E9F1B4D5BF05}"))
			  {
				 Job currentJob = theArgs.Context.Job;
				 JobStatus currentJobStatus = currentJob.Status;

				 if (String.IsNullOrEmpty((currentItem.Fields["Product ID"].Value)))
				  {
					currentJobStatus.Messages.Add(String.Format("Item :{0} has not been published since it has no Product ID", currentItem.Name));
					theArgs.Cancel = true;
					return;
				   }
			  }
		   }
		}
	}
}


Line 7:
Cast the standard EventArgs class to ItemProcessingEvent. This is important since it gives you the possibility of retrieving details of the items being published.

Line 9: Retrieve the item being published.

Line 11: The check for "currentItem.Paths.IsContentItem" is important since we only want to check for content items. Since publishable items sitecore vary from templates,standard values, renderings... we do not want to check for the condition in ALL items.

Line 14: If the template of the current item matches the id of the Product template, then we're back in business.

Line 16 - 21: Find the reference to the current Job (and JobStatus)  being executed in the publish pipeline. If the item's field is empty, add a message to the JobStatus.

Line 22: Abort the publish operation of the current item. I don't think we require the return statement after that. Publishing will then resume for the next item in the publishing queue.

Web.Config Change

Locate the publish:itemProcessing event in the web.config. Hook up the new handler to the event.

<event name="publish:itemProcessing" 
help="Receives an argument of type ItemProcessingEventArgs (namespace: Sitecore.Publishing.Pipelines.PublishItem)" >
   <handler type="Test.Events.ItemPublisher,TestApplication" method="CheckProcessing" />
</event>

Let's put it to the test

That's all to it really. If you now  initiate a publish operation and one of the Products has an emtpy Product ID, you will end up with this (if you click on "Click here to see additional information" on the last screen of the publish wizard.)

Items Skipped = 1 (.i.e Camera item has been skipped during the publish process since it has no ProductID). If you switch to the web database, there will not be any "Camera" item. 

Result... :)

Tags: ,

.Net | Applications | Sitecore

The Sitecore Way

by Aboo Bolaky 9. July 2009 07:09

4 months since my last post. This should give you an idea of my hectic life as a software developer.  Build..Test.. Deploy.....Build..Test.. Deploy.. This seems to be the only thing that I have been doing lately and hasn't left me with any time to do anything else.

Things have got to change and NOW is the time :-)

Back in Febuary, I came accros a file (via some random Google Search about Sitecore) that outlined some good one-liners about building websites using Sitecore. At that time, I added the link to my favourites and didn't pay much attention to it. Now that I've accessed the link again (by mistake..), I realise that so many of those "guidelines" are correct. Unfortunately, I did not capture the author of the text file at that time. Here's the online version

The Sitecore Way

1) Think about the CMS users not just the Web site. The Sitecore Way.

2) Use XSLT to minimize code compilation for maintenance. The Sitecore Way.

3) Get better performance with ASP.NET user-controls.  The Sitecore Way.

4) Use an ASP.NET master for your layouts. The Sitecore Way.

5) Return Item ID for XSLT extension results. The Sitecore Way.

6) Avoid setting language in a request after the Sitecore pipeline. The Sitecore Way.

7) Use icons for your masters and templates. The Sitecore way.

8) Protect /sitecore as much as you can. The Sitecore way.

9) Cookieless is possible, but be careful. The Sitecore way.

10) It's very important to Organize the content structure correctly. The Sitecore Way.

11) Finalize design as much as you can before implementation. The Sitecore way.

12) Ask for design behavior specs not just content info. The Sitecore way.

13) Use file system for large files instead of media library. The Sitecore way.

14) Use source-control for new/changed files inside Sitecore. The Sitecore Way.

15) Please avoid inline C# code in XSLT. The Sitecore way.

16) Test renderings using the debugger ALWAYS. The Sitecore way.

17) Multi-site, multi-language, identify what the client needs. The Sitecore Way.

18) Globalization is easy with Sitecore...use it. The Sitecore way.

19) Create custom XAML apps for better experience. The Sitecore way.

20) Use Sitecore's security mechanism for other applications. The Sitecore way.

21) Be careful of data cache synchronization between two sites. The Sitecore way.

22) Remove default favico.ico or your client might yell at you. The Sitecore way.

23) To stage or not to stage. We say to stage. The Sitecore way.

24) Use Lucene.net if you can for site search...it's FREE. THe Sitecore way.

25) Disaster recovery plan: zipped Web site and DB backups.  The Sitecore way.

26) Minimize rendering URL parameters to keep an SEO-friendly site. The Sitecore way.

27) Dont' forget the robots.txt...just good Web practice. The Sitecore way.

28) Analyze secuirty by feature and content access. The Sitecore way.

29) Download the Enhanced Email Action, why not? The Sitecore way.

30) Content analysis should be a top priority. The Sitecore way.

31) Use nested templates but be careful. The Sitecore way.

32) Make life easy by using a sticky session load-balancer. The Sitecore way.

33) More than a CMS, it's an integration platform. The Sitecore way.

34) Get more value by integrating it with internal systems. The Sitecore way.

35) Deliver templates and masters early to  avoid content freeze. The Sitecore way.

36) Physical storage of data does not look like Sitecore XML. THe Sitecore way.

37) Ever used Sitecore Query to query the Sitecore XML?  It's cool. The Sitecore way.

38) Use the search in the Sitecore bar for a quick content search. The Sitecore way.

39) No gray desktop background or you might loose your cursor : ). THe Sitecore way.

40) Drag content items on the desktop to create a shortcut. The Sitecore Way.

Credits: Unknown Author

 

How many of these have you achieved????

 

Tags: ,

.Net | Applications | Sitecore | Tips & Tricks

Method Overloading in WCF

by aboo bolaky 24. November 2008 07:32

In WSDL-based operations, method overloading is hard to achieve. It's not as easy as it would seem with C++ or even C#, where an interface could be defined as

[ServiceContract]
public interface IHelloWorld
{
	[OperationContract]
	void Add(int num1 ,int num2);
	[OperationContract]
	void Add(string s1, string s2);
} 

When you implement this interface in your class, the code (if it's well written Sealed) will compile just fine. The moment you update your service reference, it all goes crazy. The Error Message is "The Request failed with the error message : Cannot have two operations in the same contract with the same name".

The resolution is to add the Name attribute to the OperationContract on each method defined in the interface.

[ServiceContract]
public interface IHelloWorld
{
	[OperationContract(Name="AddNumber") ]
	void Add(int num1 ,int num2);
	[OperationContract(Name="ConcatenateStrings")]
	void Add(string s1, string s2);
} 

When proxy is generated on the client, the operations now have aliased names.  NICE !!

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="HelloWorldRef.IHelloWorld")]
public interface IHelloWorld 
{
	[System.ServiceModel.OperationContractAttribute(
		Action="http://tempuri.org/IHelloWorld/AddNumber", 
		ReplyAction="http://tempuri.org/IHelloWorld/AddNumberResponse")]
	void AddNumber(int num1, int num2);

	[System.ServiceModel.OperationContractAttribute(
		Action="http://tempuri.org/IHelloWorld/ConcatenateStrings",
		ReplyAction="http://tempuri.org/IHelloWorld/ConcatenateStringsResponse")]
	void ConcatenateStrings(string s1, string s2);

} 

Tags:

.Net | WCF | Tips & Tricks

Paging and Sorting in a Gridview without using an ObjectDataSource

by Aboo Bolaky 20. November 2008 19:43

Ryan Olshan has created a nice article about Paging and Sorting in a Gridview without using an ObjectDataSource. It's pretty nifty and gives you an insight at you can programmatically do with a GridView.

The article can be viewed here.

Tags:

.Net | Asp.Net

Creating a collapsible HTML List using JQuery

by Aboo Bolaky 17. November 2008 17:19

Yesterday, I came across this really nice article by Jeroen Coumans that explains how to create a collapsible HTML list using JQuery. The reasons why I like his solution are:

1. It's simple and easy to understand. It takes only a couple of lines to write the JQuery code.

2. It allows you to add the "active" CSS class to the selected item in the list.

3. Most importantly, it allows you to have a clickable parent item (where the link to the parent item doesn't just point to a #; it can refer to other pages on your site) 

You can have a look at the article here

 

Tags:

.Net | Asp.Net | Tips & Tricks

Creating a nested html list for the Category List in BlogEngineNET - Part Two

by Aboo Bolaky 12. November 2008 10:09

Quick Recap:

Part One : Outlines the steps required to build an nested HTML List for the Categories in BlogEngine.NET. The List can then be used on the FrontEnd section of the site.Full details of the walkthrough can be found here.

I've been working on Part Two of the solution (obviously,this builds upon the work done in Part One), which is about binding the Categories collection to a treeview control, thus making life a lot easier on the backend page. Walkthrough of Part Two

I do reckon that there is a lot to read on those two articles ..but I hope it's well worth it !! Cool

 

Tags: ,

.Net | Applications

Creating a nested html list for the Category List in BlogEngineNET - Part One

by Aboo Bolaky 8. November 2008 12:18

I've been following up the success of BlogEngine.Net closely and amongst its successful releases, I noticed that the Category List control has hardly changed at all.  Am I being too fussy here or is it time for a change?  I must admit that BlogEngine.Net is based on a rock-solid platform and has indeed exceeded my expectations in terms of architecture and extensibility.

[Kudos to the BlogEngine Team]

The purpose of this article is to outline the steps required to produce a nested list of categories from BlogEngine.Net.

UPDATE (08th November 2008):

WHERE is the article? I realised that the article is too lengthy to be included as a post. So i decided to create a Page instead : Creating a nested html list for the Category List in BlogEngineNET

I'm currently working on PART TWO of the article. Well, you ask, what is PART TWO about? In a nutshell, it will allow you to bind the Category List to a treeview control (for use in the admin section). 

Please let me know what you think. Cool

  

UPDATE (12th November 2008):

Part Two has just been published. You can access it here

Tags: ,

.Net | Applications

FeedBurner and HttpWebRequest Failure

by aboo bolaky 26. September 2008 08:34

 

The other day, I subscribed this blog to FeedBurner . This was all meant to be the way forward Tongue out. What i was trying to do was to use a Web Request to someone's feed url (in my example, http://feeds.feedburner.com/aboobolaky) to gather a few blog entries from the feed (a bit like the blog roll on the left hand side!).

It turns out that the web request fails with a status of "ProtocolError" , with an Exception of "The remote server returned an error: (404) Not Found." . However, if you use an RSS Reader or even point your web browser to the link, it works just fine!! Foot in mouth

Question here..How do we isolate the problem?

  • Is this intentional?
  • Is a proxy server responsible for this?
  • Or, maybe it has something to do with the User Agent?

 

I'll be thinking about this and post an update sooner or later.

In the meantime, I'd better revert my feed url to how it was before

using System;
using System.Configuration;
using System.Data;
using System.Web;
using System.Text;
using System.Net;
using System.IO;
using System.Xml;

public partial class _Default : System.Web.UI.Page
{ 
public class RequestState 
{ 

// This class stores the State of the request. 
const int BUFFER_SIZE = 1024; 
public StringBuilder requestData; 
public byte[] BufferRead; 
public HttpWebRequest Request; 
public HttpWebResponse response; 
public Stream streamResponse; 

	public RequestState() 
	{ 
		BufferRead = new byte[BUFFER_SIZE]; 
		requestData = new StringBuilder(); 
		Request = null; 
		streamResponse = null; 
	} 
} 
protected void Page_Load(object sender, EventArgs e) 
{ 
	HttpWebRequest httpRequest = (HttpWebRequest)WebRequest.Create("http://feeds.feedburner.com/aboobolaky"); 
	RequestState myRequestState = new RequestState(); 
	myRequestState.Request = httpRequest; 
	httpRequest.BeginGetResponse(ProcessResponse, myRequestState); 
} 
private static void ProcessResponse(IAsyncResult async) 
{ 
	RequestState state = (RequestState)async.AsyncState;
	try 
		{ 
			using (HttpWebResponse response = (HttpWebResponse)state.Request.EndGetResponse(async)) 
				{ 
					XmlDocument doc = new XmlDocument(); 
					doc.Load(response.GetResponseStream()); 
					XmlNodeList nodes = doc.SelectNodes("rss/channel/item"); 
					foreach (XmlNode node in nodes) 
					{ 
						string title = node.SelectSingleNode("title").InnerText; 
						/*likewise,list the relevant nodes under /rss/channel/item..*/ 
					} 
				} 
		} 
	catch (System.Net.WebException ex) 
		{
			throw ex; 
		}
} 

} 

Tags: ,

.Net | Asp.Net

Tag cloud

Flash Player 9 required.

About Me

I wish I could write something here..
//TODO: ElaborateMe