Friday, May 18, 2012

Sitecore Fetch Squad

Automated crawler fetching websites and blogs from Sitecore content

Archive for the ‘DMS’ Category

Sitecore OMS Experience Analytics

Posted by admin On June - 7 - 2011
Learn ways Sitecores Online Marketing Suite unifies website content management system with built in analytics and marketing automation to improve campaign ROI and much more. For more information visit www.sitecore.net
Views:
3390
1
ratings
Time:
03:03
More in
Science & Technology

This blog post describes what I consider to be important pipelines specific to the Sitecore Digital Marketin System (DMS, formerly OMS). For more information about pipelines, see my blog post All About Pipelines in the Sitecore ASPNET CMS.

Contributing to Sitecore Shared Source Projects

Posted by admin On January - 29 - 2009

The following tips for working with Sitecore shared source are based on my recent experience contributing the FieldValueComparer (based on to the comparer in this post) to the Sitecore Shared Source project.

  • Review this introduction to contributing shared source to obtain access to Subversion or to request a new project room.
  • Each project room is basically a Wiki. The only way back to the list of project rooms seems to be http://trac.sitecore.net/Index, so most project rooms include this link.
  • Review this guide to contributing shared source.
  • Copy files into the Trunk directory and check them in.
  • I don’t like learning a new markup, but when editing the Wiki:
    • It seems to format linefeeds as HTML paragraphs or line breaks.
    • Use equals signs for major headings (the spacing seems to be important): 
      = heading =
      
    • Use more equals signs for minor headings:
      == heading ==
      
    • Preceed text with an exclamation mark to avoid the Wiki automatically creating a link:
      = Welcome to the !ProjectRoomName =
      
    • Wrap URLs with quare brackets, optionally followed by a space and the text of the link:
      [http://sitecore.net Sitecore Marketing Site]
      
    • Wrap code with three curly braces to preformat it for easy copy and paste:
      {{{
      // code
      }}}
      
    • You can create entries in numbered lists by entering a space character, a number, and a period on a blank line:
       1. First.
       2. Second.
      
  • Please report issues and feature requests for shared source components by posting on the Shared Source Modules forum on the Sitecore Developer Network.

I will try to maintain this list and the FieldValueComparer project room as a template for cutting and pasting when creating new projects.

John West Blogs about Sitecore

Adding an item and publishing in S5

Posted by admin On December - 29 - 2008
using System;
using Sitecore;
using Sitecore.Data.Items;
using Sitecore.Publishing;
using Sitecore.Configuration;
using Sitecore.SecurityModel;

namespace Addition.Test
{
///

/// Class to demo creation of an item and publishing.
///

public class S5Demos
{
// alternativelly paths can be used as well
public const string _masterId = "{E13FA2BC-FBB9-4F36-9601-C620E0FC6ED8}";
public const string _templateId = "{797D0FE3-16C6-4910-8174-68A226AACE67}";
public const string _insertionRoot = "{7776B388-75CE-4E06-A2A6-F7F6E053FFF8}";

// get an item from master database
public static Item GetItemFromSitecoreMaster(string itemPath)
{
return S5Demos.GetItemFromSitecore(itemPath, "master");
}

// get an item from web database
public static Item GetItemFromSitecoreWeb(string itemPath)
{
return S5Demos.GetItemFromSitecore(itemPath, "web");
}

// get an item based on GUID or path from a specified database
public static Item GetItemFromSitecore(string itemPath, string dbName)
{
Item itmResult = null;

Sitecore.Data.Database dataDB = new Sitecore.Data.Database(dbName);
if (dataDB != null)
{
Sitecore.Data.ItemUriBuilder bUri = new Sitecore.Data.ItemUriBuilder(itemPath, dataDB);
if (bUri != null)
{
Sitecore.Data.ItemUri uri = new Sitecore.Data.ItemUri(bUri.ItemUri);
if (uri != null)
{
itmResult = Sitecore.Data.Database.GetItem(uri);
}
}
}

return itmResult;
}

// create a sitecore node
protected void CreateAnItem(string itmName)
{
// where we insert?
Item root = GetItemFromSitecoreMaster(_insertionRoot);
// we can use a master as model
MasterItem masterItm = GetItemFromSitecoreMaster(_masterId);
// a tempalte is fine as well
TemplateItem templateItm = GetItemFromSitecoreMaster(_templateId);

using(SecurityDisabler disabler1 = new SecurityDisabler())
{
root.Editing.BeginEdit();

Sitecore.Diagnostics.Log.Info("adding " + itmName.ToString(), this);
Item itmAdd = root.Add(itmName, masterItm);
// or, by using the template: Item itmAdd = root.Add(itmName, templateItm);
if (itmAdd != null)
{
// modify a field
Sitecore.Data.Fields.Field fldLoc;

itmAdd.Editing.BeginEdit();
try
{
fldLoc = itmAdd.Fields["SomeField"];
if (fldLoc != null)
{
fldLoc.Value = "Some Value";
}
}
catch
{
}
finally
{
itmAdd.Editing.EndEdit();
}
}

root.Editing.EndEdit();
Sitecore.Diagnostics.Log.Info("adding done", this);
}

}

// publish a sitecore node
protected void PublishNode(Item itm)
{
Sitecore.Diagnostics.Log.Info("publishing node " + itm.Paths.Path, this);
try
{
PublishOptions aOptions = new PublishOptions(PublishMode.Full,
Sitecore.Globalization.Language.DefaultLanguage, DateTime.Now);
aOptions.TargetDatabase = Factory.GetDatabase("web");
aOptions.RootItem = itm;
aOptions.SourceDatabase = itm.Database;

//Create and run a publisher
Publisher aPublisher = new Publisher(aOptions);

// use a disabler to not be forced to log in
using (Sitecore.SecurityModel.SecurityDisabler disabler1 = new Sitecore.SecurityModel.SecurityDisabler())
{
aPublisher.Publish();
}
Sitecore.Diagnostics.Log.Info("publishing done for " + itm.Paths.Path, this);
}
catch (Exception ex)
{
Sitecore.Diagnostics.Log.Error("error on publishing node " + itm.Paths.Path, ex, this);
}
}
}
}

The Sitecore Experience

Understanding ASP.Net memory

Posted by admin On December - 29 - 2008

Applies to 32 bit Windows

As many a developer has experienced memory is not an unlimited resource when using In-process memory like the ASP.Net cache. Ruuning out of it shows symptoms like the process recycling or OutOfmemory and MemoryLimit Exceded Exceptions here and there. Having a basic understanding of what is going on will help you a lot resolving problems like this.

Fact: In a standard setup your worker process always have 2GB Virtual memory available (no matter if you have 1, 2 or 4GB physical memory in the machine). If you use 1.5GB memory in your application but your machine only has 1GB physical memory, some of it is just swapped to disk. Thats why it is virtual memory. This also means that if you are running out of (virtual) memory it doesn’t help to add more physical memory.

So why am I limited to 2GB virtual memory?: Well, a 32bit operating system (OS) is only able to address 4GB memory with these 32 bits. In a standard setup 2 of these are reserved for the OS, and the remaining 2 reserved for applications like ASP.Net.

A common error in memory heavy applications is the OutOfMemory Exception (OOM). It happens when the framework is unable to allocate enough virtual memory to run a piece of code. This is a bad thing because they can be thrown almost anywhere in your code, making it hard to predict the outcome. What happens is that the framework lost a battle against custom code about access to the limited 2GB memory.

Microsoft solved this in IIS 5.0 by adding the setting memoryLimit to the machine.config file. This setting tells how many of the 2GB the workerprocess (custom code) should be allowed to use. The rest of the 2GB is then free for the Framework to use for executing code. In IIS 6.0 the Maximum used memory (in megabytes) property on the application pool is used for the same purpose. Where the setting is quite straightforward in IIS 6.0, this is not the case in IIS 5.0 where it is a percentage of physical memory. Say you have a machine with 2GB memory and the default setting is 60 (%) equalling 1.2GB. If you now add an extra 2GB for a total of 4GB, the 60% now equals 2.4GB out of 2 possible, which of course does not make sense. So make sure to review this setting in the beginning as well as at every change of physical memory.

So how many megabytes should be allowed for the workerprocess?: Microsoft recommends to “set the memory limit to the smaller of 60% of physical RAM or 800 MB“. Here is the explanation why. On almost anything but a 1GB machine 800MB will always be the smaller of the two numbers. So 800MB is the recommended setting for 2GB+ machines. Not really a lot of available cache memory if you have a machine with 4GB physical memory and 2GB virtual.

Microsoft argues: “There are a couple things to consider: First, the likelihood of experiencing an OutOfMemoryException begins to increase dramatically when “Process\Virtual Bytes” is within 600 MB of the virtual address space limit (generally 2 GB), and secondly, tests have shown that “Process\Virtual Bytes” is often larger than “Process\Private Bytes” by no more than 600 MB

If you search and read long on the net, you will eventually find that when you set the memoryLimit setting, the value it is compared against is the performance counter “Process\Private Bytes“, which you force to stay below 800MB. The logic is: 800MB plus 600 MB (that Virtual Bytes may be larger than Private Bytes) + 600MB (which is needed as buffer to avoid OOM’s) = 2000MB = 2GB which is the available amount of virtual memory. So if you set memoryLimit higher, you start risking OOM’s. Thats the logic behind.

So what will happen if you use more ASP.Net cache than is allowed through the memoryLimit? The system will throw a “memoryLimit Exceeded” exception and recycle the worker process to release memory. If you want to avoid this, you should make sure that Private Bytes never exceed the memoryLimit.

The last topic I will cover here is the 3GB switch which is available on some versions of Windows, but not all (none mentioned by purpose). This setting  makes only 1 GB available for the OS, and therefore leaves 3GB for applications like the worker process. Through the same maths as we used to determine the 800MB limit above, we can calculate that this setting allows a memory limut of 1800MB, as this still leaves 1200 MB for the rest. Below I have inserted a picture visualizing this:

ASP.Net Virtual Memory

Links: http://msdn2.microsoft.com/en-us/library/ms972959.aspx#monitor_perf_topic12

http://msdn2.microsoft.com/en-us/library/ms998583.aspx#scalenetchapt17_topic14

Jesper On Stuff

EXIF data from MediaItem

Posted by admin On December - 29 - 2008
Reading EXIF data from sitecore media items is probably gonna be -a lot- easier in the future, but as far as i can tell there’s no easy way of doing it so far..

Hopefully there’s a better (and easier) way of getting EXIF information, but i didn’t have time to find it, and this works, so it’ll do for now :)

The following code will return the resolution specific EXIF information of a passed in MediaItem:

public string GetImageResolution(Sitecore.Data.Items.MediaItem mi)
{
//
check item before we begin
if (mi != null)
{
// inject the stream from
the media item to an image (needed to get exif reader
running)
System.Drawing.Image img =
System.Drawing.Image.FromStream(mi.GetMediaStream());
if
(img!=null)
{
// init a new exif reader
Sitecore.Drawing.Exif.Reader
ExifReader = new Sitecore.Drawing.Exif.Reader(img);
if (ExifReader !=
null)
{
// allocate the different types of properties we’re gonna be
using
Sitecore.Drawing.Exif.Properties.Property
prop;
Sitecore.Drawing.Exif.Properties.UInt16Property
u16prop;
Sitecore.Drawing.Exif.Properties.RationalProperty rprop;
// start
fetching properties..
prop =
ExifReader.GetProperty((int)Sitecore.Drawing.Exif.Properties.Tag.ResolutionUnit);
if
(prop != null)
{
// first is a UInt16 property that we’ll step through and
see what type it is..
u16prop =
(Sitecore.Drawing.Exif.Properties.UInt16Property)prop;
if
(u16prop!=null)
{
// get the resolution unit
string resUnit =
“dpi”;
switch (u16prop[0])
{
case 1:
resUnit =
“n/a”;
break;
case 2:
resUnit = “dpi”;
break;
case 3:
resUnit
= “dpcm”;
break;
}
// now go fetch the two remaining properties
(they’re both rational properties)
// horizontal resolution
string
horzRes = “1/72″;
prop =
ExifReader.GetProperty((int)Sitecore.Drawing.Exif.Properties.Tag.XResolution);
if
(prop != null)
{
// cast it to rational property
rprop =
(Sitecore.Drawing.Exif.Properties.RationalProperty)prop;
if (rprop !=
null)
{
if (rprop.Values[0].ToString() != “”)
{
horzRes =
rprop.Values[0].ToString();
// try to calculate it appropriately.. (sucks,
but we gotta do it unless we want mumbo jumbo text to appear..)..
string[]
hstrs = rprop.Values[0].ToString().Split(‘/’);
if
(hstrs.Length>0)
{
// format the string
horzRes =
string.Format(“{0}”, (double.Parse(hstrs[0].Trim()) /
double.Parse(hstrs[1].Trim())));
}
}
}
}
// repeat for
vertical
string vertRes = “1/72″;
prop =
ExifReader.GetProperty((int)Sitecore.Drawing.Exif.Properties.Tag.YResolution);
if
(prop != null)
{
// cast it to rational property
rprop =
(Sitecore.Drawing.Exif.Properties.RationalProperty)prop;
if (rprop !=
null)
{
if (rprop.Values[0].ToString() != “”)
{
vertRes =
rprop.Values[0].ToString();
// try to calculate it appropriately.. (sucks,
but we gotta do it unless we want mumbo jumbo text to appear..)..
string[]
vstrs = rprop.Values[0].ToString().Split(‘/’);
if (vstrs.Length >
0)
{
// format the string
vertRes = string.Format(“{0}”,
(double.Parse(vstrs[0].Trim()) /
double.Parse(vstrs[1].Trim())));
}
}
}
}
// finally format the
output and return it
return string.Format(“{0} {1} x {2} {3}”, horzRes,
resUnit, vertRes, resUnit);
}
}
}
}
}
return “”;
}

The resulting output will give you a string along the lines of ’300 dpi x 300 dpi

Regards,

P.

d e v e l o p m e n t

MailMonitor Sitecore Edition

Posted by admin On December - 29 - 2008
I have been working on a product called Mail Monitor for years now. It is my pet project and has been for the last 3-4 years or so.

Mail Monitor is an E-mail /SMS campaign tool written in C# hosted on ASP.NET and uses all the cool stuff released from Microsoft within the last years. (Except Silverlight, for now). It is a tool written by a super nerd (me) and is therefore highly extendable using Providers, web-services, Remoting and GoF patterns.

But MailMonitor is not new – but the fact that I made a version for Sitecore is.

For now check out these screenshots.

Runi Thomsen Code Thoughts

Sitecore on .NET 3.5

Posted by admin On December - 29 - 2008

I can report that using Sitecore with .NET 3.5 and C# 3.0 truly is a seamless transition.

This is especially good news for us developers who tried to upgrade from .NET 1.1 to .NET 2.0.
Back in the day, the transition supposed to be seamless, but surely was not. There was always some strange library containing some braking change, or a project model
who was removed – only to make life difficult for us developers.
This is by my experience NOT the case when upgrading from .NET 2.0 to 3.5.

I have been running a production environment of Sitecore in .NET 3.5 for a couple of weeks now (since we
Microsoft Gold Partners got VS2008) – and there have been no problems so far.
But why is that?

Well:

– There has been no change what so ever in the CLR runtime. It’s still 2.0. This was not the case coming from 1.1 to 2.0. MS had to update the CLR to include generics (parametric polymorphism)

– The C# Compiler has changed, but the target of the compiler remains.

– The library changes are purely additive. Meaning, that things you used in
.NET 2.0 remain the same – and all the new features have been added in new
.dlls, not changing the old ones.

So – Happy coding using C# 3.0 for Sitecore.

To finnish of, lets reflect on the different way to bind children of an Item to a repeater control in Sitecore:

(Wich one do you like the most ?)

//The sitecore way

childrenRepeater.DataSource = Context.Database.SelectItems(“/sitecore/content/home/*[@@templatename='DisplayBox']“);

//C# 1.0 way, using a standard foreach loop

ArrayList list = new ArrayList();

foreach (Item item in Sitecore.Context.Item.Children) {
if (item.TemplateName == “DisplayBox”)
list.Add(item);
}
childrenRepeater.DataSource = list;

//C# 2.0 way, using the iterator pattern (yield statement),and anonomouse delegate

childrenrepeater.DataSource = delegate {

foreach (Item child in Sitecore.Context.Item.Children) {
if (child.TemplateName == “DisplayBox”)
yield return child;
}
};

//C# 3.0 way using the query syntax
childrenRepeater.DataSource = from Item child in Sitecore.Context.Item.Children
where child.TemplateName ==“DisplayBox”

select child;

childrenRepeater.DataBind();

Runi Thomsen Code Thoughts

Sitecore and .NET 3.5 SP1

Posted by admin On December - 29 - 2008
Sitecore 6 was the victim of a bug in Microsoft .NET 3.5 SP1 – which meant that Sitecore 6 developers could not use Visual Studio 2008 SP1 or .NET Framwork 3.5 SP1.

You can read alle about it at Alexey Rusakov’s blog

However, I just discovered that Sitecore just now released a patch addressing this very problem. I tested it, and it seems to work.

What you want to do, is download Update rev.080820 from sdn5.sitecore.net

Good work Sitecore :-)

Runi Thomsen Code Thoughts

.NET Remoting Removed from Sitecore

Posted by admin On December - 29 - 2008
Some time ago I blogged about how Sitecore would include .NET Remoting, a feature that would make Sitecore more scalable and flexible.

Introducing Remoting support was a fundament for creating integration to Sitecore from applications that would not be hosted on the same process as the CMS – a scenario that is very likely in the enterprise. It would also open up the possibility of creating custom tools that could be run from any machine not running Sitecore, even supporting the creation of a Windows Power Shell client.

In essence, the only big different was the all classes in Sitecore.Kernel ultimately would implement MarshallByRefObject something that does not have any impact on the performance of the system, the rest was configuration. It means that supporting .NET Remoting is nearly effortless and free, whereas the benefits are great and powerful.

I just realized, to my great surprise, that none of the classes that used to implement MarshallByRefObject during the Beta period of Sitecore 5.3 still do.
I simply do not understand why Sitecore made this change, and would love to hear their input on this.

Runi Thomsen Code Thoughts