Friday, May 18, 2012

Sitecore Fetch Squad

Automated crawler fetching websites and blogs from Sitecore content

Archive for the ‘Sitecore Blogs’ Category

New Year, New Sitecore Blog

Posted by admin On October - 30 - 2011

I have been thinking about this for a while, and finally decided to create another Sitecore blog on our Community area dedicated to sharing my experiences in the field working closely with implementation partners:

http://www.sitecore.net/AlexShyba

My ambitious plan is too continue sharing anything deeply technical here while the new blog would be a place where technical meets business half way.

Hope you enjoy it!

Consulting and Supporting Sitecore Developer Community

Sitecore Product URLs Amazon Style

Posted by admin On October - 30 - 2011

If you are a Sitecore CMS developer and you love shopping on Amazon, you probably had the same thought: what would it take to re-create Amazon.com in Sitecore? Completely from scratch. Ok, maybe it’s just me.
So you will need to think about how to architect your content tree properly. Luckily, Derek has a blog dedicated solely to content tree architecture so I don’t need to go into much detail here.
Let’s say you have your content tree already designed. We are going to take Nicam demo site as an example:image
So all the camera products are structured in categories, that’s nice.
Since we talk about URLs in this post, everything is set there too. Each product has a content path which more or less serves as product URL on the public facing side.
In other words, I would be able to access my D3X camera using the following URL:
http://localhost/en/Products/Digital_SLR/Full_featured/D3X.aspx

One of the things you need to know is that Sitecore is constructing those URLs on the fly based on LinkManager configuration in web.config. And it is actually doing a pretty great job out of the box by giving you a number of options when it comes to URL construction. You can prepend language ISO code in URL, use display name instead of item name, etc. You can learn more about it here.

But what if we want to have fluid URLs that are constructed based on product attributes, meta data or some other criteria? Just as on Amazon.com, where the product URL is clearly driven by product attributes:

SNAGHTMLaa324b6For example, for all of our SLR cameras, use the following URL pattern: http://localhost/{SLR}/{Name}/{SKU}, where SKU is an attribute on the product itself:

imageWell, as it turns out, it is quite straightforward to do.
When it comes to handling any custom URL handling requirements, there are mainly two components you have to deal with.
1. Custom Item Resolver.
The custom logic here will attempt to resolve a valid item in the content tree by the custom URL.
2. Custom Link Provider.
This is the flip side of the solution. We need to teach Sitecore to generate product URLs based on our custom rules.
In addition, you would generally need a component to process such custom URL rules. In my example I would simply use IDTable, which allows to store any mapping to an item in a flat table. For the sake of simplicity I will be updating my IDTable based mapping table every time an item is saved via a handler.
The result will look something like this:
image
So here are all the pieces:
1. Custom Item Resolver:

public class ProductUrlResolver : HttpRequestProcessor
{
   public override void Process(HttpRequestArgs args)
   {
      Assert.ArgumentNotNull(args, "args");
      if (Context.Item != null || Context.Database == null || args.Url.ItemPath.Length == 0) return;
      Context.Item = ProductUrlManager.GetProductItemByFilePath(args.Url.FilePath);
   }
}

<processor type="Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel"/>
<!-- the proper order is important -->
<processor type="Custom.ProductUrlResolver, ProductUrlResolver"/>
<processor type="Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel"/>

2. Custom Link Provider:

public class ProductLinkProvider : LinkProvider
{
   public override string GetItemUrl(Item item, UrlOptions options)
   {
     Assert.ArgumentNotNull(item, "item");
     Assert.ArgumentNotNull(options, "options");
     return item.IsProduct() ? item.ProductUrl() : base.GetItemUrl(item, options);
   }
}

<linkManager defaultProvider="sitecore">
      <providers>
        <clear/>
         <add name="sitecore"
              type="Custom.ProductLinkProvider, ProductUrlResolver"
              .../>
      </providers>
</linkManager>

3. ItemSaved event handler:

public class ProductHandler
{
      protected void OnItemSaved(object sender, EventArgs args)
      {
         if (args == null) return;

         var item = Event.ExtractParameter(args, 0) as Item;

         if (item == null) return;

         if (item.IsProduct())
         {
            item.RegisterMapping();
         }
      }
}

<event name="item:saved">
    ...
   <handler type="Custom.ProductHandler,ProductUrlResolver" method="OnItemSaved"/>
</event>

4. Utility Manager where all the logic is handled:

public static class ProductUrlManager
   {
      public static string IdTableKey
      {
         get { return "ProductResolver"; }
      }

      public static bool IsProduct(this Item item)
      {
         var template = TemplateManager.GetTemplate(item);
         return template != null &&
template.DescendsFromOrEquals(ID.Parse("{B87EFAE7-D3D5-4E07-A6FC-012AAA13A6CF}"));
      }

      public static string ProductUrl(this Item item)
      {
         return "/{0}/{1}/{2}".FormatWith(item.TemplateName.ToLowerInvariant(),
item.Name.ToLowerInvariant(),
item["SKU"]);
      }

      public static Item GetProductItemByFilePath(string filePath)
      {
         var id = IDTable.GetID(ProductUrlManager.IdTableKey, filePath);

         if (id != null && !ID.IsNullOrEmpty(id.ID))
         {
            return Context.Database.GetItem(id.ID);
         }

         return null;
      }

      public static void RegisterMapping(this Item item)
      {
         IDTable.RemoveID(ProductUrlManager.IdTableKey, item.ID);
         IDTable.Add(ProductUrlManager.IdTableKey, item.ProductUrl(), item.ID);
      }
   }

Conceptually, what do you think about this?
Note that this is a pretty hardcoded way of implementing such requirement. Please consider this as a prototype rather than a solution ready for production.

Consulting and Supporting Sitecore Developer Community

8 Reasons to Use New Search in Sitecore

Posted by admin On October - 30 - 2011

Greetings,

Back in 2010 at the first Dreamcore conference, I was honored to present on two topics: ”Data Retrieval Techniques with Sitecore” and “Using Lucene.NET with Sitecore”.
If you have not seen any of those, download the slides and check them out. I consider myself being a data guy, so that’s why I really enjoyed presenting on these topics. Not sure why, but I love everything about data access, and absolutely adore what Microsoft did with Entity Framework 4, especially the oData stuff. There is something truly exciting in seeing your data flow and materialize in one shape or another.

Anyways, back to the topic. During my presentation on Lucene/Sitecore marriage, I was showing that Sitecore actually has two (!!!) implementation of Lucene.NET. One is a legacy, what we call “old” search. Everything within Sitecore.Data.Indexing namespace is considered to be “old” search. It is configured and implemented differently, though it uses the same Lucene.NET dll. There is also the “new” search which is represented by a few classes within Sitecore.Search namespace.

The main point of the presentation was to show that you should not really use the “old” search if you develop on Sitecore 6.

Here are some extracts from the presentation explaining why:

1. Much richer out of the box:

a. one can specify locations, templates, etc.
b. indexes all fields
c. supports tagging
d. automatic prioritization

2. More extensible, more flexible and “overridable”

a. Configuration is separated from database

3. Better API

a. enforcing programming best practices

b. friendlier and easier to work with

c. external integration is possible

d. supports of “context of search operation“

4. Faster and more dependable.

Convinced yet?

Both “old” and “new” search index are being maintained by Sitecore in a similar fashion. However, they present different APIs to interact with them.

There is got to be a reason, but I frequently witness Sitecore implementers favor “old” over the “new” one. My only explanation is that we did not fully document the “new” search with the release of Sitecore 6, and that SDN was not steering developers in the right direction.

My humble hope is to address this shortcoming.

Here are 8 reasons why I should consider using “new” search.

1. All the good stuff about the “new” search listed above.

2. There is already a very comprehensive document on the “new” search on SDN. It should explain most of what the “new” search is about.

3. There is a shared source project called “Advanced Database Crawler” which leverages the “new” search and pushes its limits further introducing such things as field filters, dynamically computed fields, extended field crawler factory, plus includes an easy to use Searcher APIs that should abstract complexities of building search queries.

4. I have also blogged about it and recorded a very long and boring screencast showcasing this component.

5. Ivan blogged about it for quite a bit here and showed a few code snippets and workarounds.

6. The “new” Sitecore.Search namespace has a high chance of being the data access technique of choice, since that’s all you need to effectively query Sitecore data repository.

7. The “old” implementation may be deprecated in next major release, so it is important not to miss the early opportunity and migrate as soon as you can.

8. It is tried out in production by many already.
Just recently I actually was able to help a partner who decided to completely revamp their Sitecore Query based data access implementation with the “new” search. The results were reportedly dramatic and are already paying off.

One important note: please make sure to use either of the following Sitecore CMS versions if you go with it:
- 6.4.1 rev.101221
- 6.3.1 rev.110112
- 6.2.0 rev.101105 (Update-5)

They all contain some critical enhancements that will make your experience with the “new” search much smoother.

Enjoy it!

Consulting and Supporting Sitecore Developer Community

Dreamcore is going to be even more fun this year!

Posted by admin On October - 30 - 2011

What could be more fun than meeting your fellow Sitecore Enthusiasts and visiting beautiful Boston, especially in springtime? Learning about what’s new coming out, share ideas and best practices.
Well, you must have heard, we are doing it again!

As we still working hard on the agenda, but here are two known facts:

1. Yes, I will be speaking about common implementation scenarios. Specifics are coming soon.

2. Now exclusive information…just overheard it in the corridors of the marketing department.

This time we are going to have a special guest speaker: Carl Franklin!
In the world of technology, you know Carl as one of the first VB programmers, an extra famous Microsoft enthusiast, and of course, a founder and co-host of .NET Rocks!, an Internet audio talk show for people like you an me.

Again, specifics will be coming later, but rest assured that Carl’s inspirational message will leave no doubt that .NET Rocks! Along with that, we will be doing our own part, and show you exactly why Sitecore Rocks!

It is going to be so much fun! See you all in Boston!

Dreamcore 2011 is coming April 19-20, 2011 in Boston. Sign up now!

Consulting and Supporting Sitecore Developer Community

Using ELMAH for error logging within Sitecore

Posted by admin On October - 30 - 2011

Since a while I use ELMAH for error logging in my custom ASP.NET applications. Normally in a Sitecore project I log all exceptions to the Sitecore log files. But the disadvantage of this is that the exceptions are in the same files as all Sitecore log messages. So I tried to implement ELMAH within my Sitecore installation.

What is ELMAH?

According to the official site: “ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. It can be dynamically added to a running ASP.NET web application, or even all ASP.NET web applications on a machine, without any need for re-compilation or re-deployment.”

What does this mean?

ELMAH has the following features

  • Log all (unhandled) exceptions
  • A user interface which lets you view remotely all exceptions, including detailed information (even when customerrors mode is turned off!) and the original yellow error screen (YSOD)
  • Email notification when errors occur
  • RSS feeds which show the latest errors

ELMAH uses two key components. There is one HTTP module which logs exceptions, and one HTTP Handler that shows the exceptions. You can choose SQL Server, SQLite, MS Access, Oracle, Vista DB or MySQL as a storage medium to save the exceptions to.

How do you implement it?

First off all you need to download the right version from the official download page. Then copy the Elmah.dll file to your Bin folder. If you want to use the SQLite data storage then you also need to copy the System.Data.SQLite.dll into the Bin folder. For this example I will use the SQLite data storage.

When you copied the files into the Bin folder, you need to edit the web.config. Unfortunately the web.config changes are outside the <sitecore> node, so we can’t use the config include files.

1. First we need to add a new sectiongroup to the configuration/configSections node
<sectionGroup name=”elmah”>
<section name=”errorLog” requirePermission=”false” type=”Elmah.ErrorLogSectionHandler, Elmah”/>
</sectionGroup>
2. Then we need to add the ELMAH section to the configuration node. In this section is configured what type of storage we use
<elmah>
<errorLog type=”Elmah.SQLiteErrorLog, Elmah” connectionStringName=”ELMAH.SQLite”/>
</elmah>
3. As you might noticed we also need to add a connectionstring. This can be added to the /App_Config/ConnectionStrings.config
<add name=”ELMAH.SQLite” connectionString=”Data Source=|DataDirectory|errors.s3db”/>
4. ELMAH uses a HTTP Handler with the file extension .axd. To prevent IIS returning a 404 we need to add the location and filename of the handler to the IgnoreUrlPrefixes setting.
<setting name=”IgnoreUrlPrefixes” value=”/sitecore/admin/elmah.axd|/sitecore….
5. Then we need to add the Http module which logs the exceptions to the end of the system.webserver/modules section
<add name=”ErrorLog” type=”Elmah.ErrorLogModule, Elmah”/>
6. The last part is adding the Http handler to the end of to the system.webserver/handlers section
<add name=”Elmah” path=”/sitecore/admin/elmah.axd” verb=”POST,GET,HEAD” type=”Elmah.ErrorLogPageFactory, Elmah” preCondition=”integratedMode” />

If all it setup correctly you can now view ELMAH log at http://www.mysite.com/sitecore/admin/elmah.axd

Right now ELMAH only logs the unhandled exceptions. If you want ELMAH to log exceptions which you handle in a catch statement you need to add the following line in your catch statement:

Elmah.ErrorSignal.FromCurrentContext().Raise(ex);

I created a simple application which lets you view the ELMAH error log within Sitecore. I will put this on the Shared Source environment later this week.

View Elmah logs within Sitecore

Mark van Aalst

Creating a Item Editor

Posted by admin On October - 30 - 2011

For a blog module that I am developing I wanted to create an custom item editor. As you might know those are the “tabs” in the Content Editor.

1. Create a aspx file for the item editor user interface.
2. Select the core database in the desktop mode
3. Open the Content Editor and go to the following path /Sitecore/Content/Applications/Content Editor/Editors/Items.
4. You can create an item editor using the /Sitecore Client/Content Editor/Editor data template.
5. You can give your item editor a name using the header field in the data section.
6. In the icon field you can enter a path to the icon.
7. In the url field you need to fill in the url to the aspx file created in step 1
8. Save the item.
9. Switch back to the master database.

Now we have created the item and the user-interface for the Item Editor. The next step is to assign the item editor to a template.

10. You can do this by setting it on the standard values or a individual item. Open the item in the content editor or template manager.
11 . Click on the configure tab, go to the appearance group and click the editor command. A dialog will appear.
12. In this dialog you can select the item editor you want to use, using the arrows you can sort.
13. Finally close the dialog and save and publish.

Now when you select a item based on this template you see a item editor in the content editor with the title you filled in. You can edit the item editor using normal ASP.Net controls. This is a great solution for creating custom reports. But when you want to create an real custom editor functionality, you would like to use the default save button of the content editor. I might be confusing for a end-user to have two save button in one screen.

Unfortunately, Sitecore provides no default solution for capturing that event. Thanks to Eugene Omelnitsky from Sitecore Support (for pointing me in the right direction) I found a solution. You can adapt to the Save event using javascript. I then used JQuery to do an ajax call to the server and execute my save method.

This is the Javascript function which captures the save event and triggers an ajax call to my page method.

<script type="text/javascript">
function scGetFrameValue(value, request)
{
if (request.parameters == "contenteditor:save" || request.parameters == "item:save")
{
$.ajax({
type: "POST",
url: "EntryEditor.aspx/SaveItem",
data: "{ e: '" + $('#EditorIntroduction').val() + "', title: '" + $('#tbTitle').val() + "', content: '" + $('#EditorContent').val() + "' }",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(msg) {
alert("succes!");
}
});
}
}
</script>

And this is the method that I use server side

[System.Web.Services.WebMethod]
public static void SaveItem(string entryid, string introduction, string content, string title)
{
Database master = Factory.GetDatabase("master");

Item currentItem = ItemManager.GetItem(new ID(entryid), Sitecore.Context.Language, Sitecore.Data.Version.Latest, master);
Entry currentEntry = new Entry(currentItem);

currentEntry.BeginEdit();
currentEntry.Title = title;
currentEntry.Introduction = introduction;
currentEntry.Text = content;
currentEntry.EndEdit();
}

The code above is not perfect, it needs a bit more flexibility but for testing purposes it works.

Mark van Aalst

Sitecore roadmap

Posted by admin On October - 30 - 2011

Tonight I was catching up with some RSS Feeds and Twitter messages, when I noticed that SPN (Sitecore Partner Network) is renewed. My compliments to the people behind the renewal, it looks so much better and it’s easier to find the information you’re looking for. Next one is SDN perhaps? I know I would appreciate it, and I think there are more people who would like it.

When I was crawling through the content of SPN I saw the roadmap. Curious as I am I opened it to see if it was a different version than the the outdated one at the old SPN. I then saw that I it’s updated and has some real nice improvements.

Here are some

  • Sitecore Client RSS feeds
  • WebDav
  • MS Word Fieldtype
  • Webforms 2.0
  • LINQ data abstraction
  • Re-factored publishing engine
  • Advanced clustering of any number of Production CMS Servers

Take a look at the roadmap, you will find more information there.

Mark van Aalst

Sitecore released version 6.2!

Posted by admin On October - 30 - 2011

Today Sitecore released version 6.2. According to the change log their are several new (cool) features.

  • Sitecore client RSS feeds for items in workflows
  • Built-in support for syndicating items using the RSS format.
  • WebDAV support in the media library
  • A new File Drop Area field type has been introduced
  • A new Word Field has been introduced!
  • Analytics Oracle support
  • Improved IIS7 support
  • Sitecore’s theme icons are now stored in zip-files.
  • Sitecore is now distributed with a number of icons that are having a Windows 7-look instead of an XP-look.

Besides that their are many improvements and fixes.

Go check it out! I’m installing it right now and gonna have a a look.

Mark van Aalst

New Sitecore 6 blog module released

Posted by admin On October - 30 - 2011

In the last couple of months I have been working on a new blog module for Sitecore 6.2. It started as a small module just for my own educational purpose but ended up as one of the largest modules I created. The module is a complete rewritten blog module, based upon the functionality of the old 5.3 version. The new version supports inline editing, fieldeditors, webcontrols for custom themes and Windows Live Writer integration. This release includes two sample blogs. One with a standard theme and one custom theme which shows you how to use the custom webcontrols.

List of features

  • Windows Live Writer integration (MetaWeblog API)
  • Full frontend (inline) editing
  • Webedit ribbon (with fieldeditors)
  • CSS based themes
  • Custom themes possible (one demo included)
  • Custom webcontrols (with inline editing)
  • Comments
  • Tagging and a tagcloud
  • RSS Feeds

At this moment the module in still in betá, and I would like to hear your feedback. You can use the comments or just send me a email (mark at evident.nl). When you encounter problems, found a bug or have any other kind of feedback please let me know and I will try to reply as soon as possible.

You can find the installation package and sources on the Shared Source environment.

Mark van Aalst

Blog module update

Posted by admin On October - 30 - 2011

This week I released the stable version of the EviBlog module. You can download the module from the Sitecore Shared Source. The module works on all Sitecore solutions based on version 6.2.

The module now includes the following features:

  • Inline Editing support
  • Windows Live Writer integration
  • Pingback
  • RSS (using the Sitecore 6.2 Integrated RSS)
  • Tagging and tagcloud
  • Categories
  • Comments (you can disable per setting)
  • FieldEditors for blog and entry settings
  • Custom webcontrols for integrating your own theme

The Shared Source coordinator Jimmie Overby created two video’s (1, 2) which shows you the most common use of the module. Currently I am writing some documentation about how to use the webcontrols in your own theme. With these webcontrols it’s quite easy to integrate the module within an existing Sitecore installation.

Please do not hesitate to use the Shared Source forum when you have questions about the module.

Mark van Aalst