Large files in the Media Library

A common asked question by customers and colleague-developers is what’s the max size for Media Library items since they are imported in the database in Sitecore 5.3. The answer on this question is quite easy: 16 Mb is the predefined absolute maximum for the RequestLength of a .NET defined in the Web.config:

 2385     <!–

 2386       httpRuntime Attributes:

 2387         executionTimeout=”[seconds]” – time in seconds before request is automatically timed out

 2388         maxRequestLength=”[KBytes]” – KBytes size of maximum request length to accept

 2389         useFullyQualifiedRedirectUrl=”[true|false]” – Fully qualifiy the URL for client redirects

 2390         minFreeThreads=”[count]” – minimum number of free thread to allow execution of new requests

 2391         minLocalRequestFreeThreads=”[count]” – minimum number of free thread to allow execution of new local requests

 2392         appRequestQueueLimit=”[count]” – maximum number of requests queued for the application

 2393       –>

 2394     <httpRuntime maxRequestLength=16384 executionTimeout=600 />

Altough Sitecore has defined 16 Mb as maximum, I would recommend you to instruate the customer to upload files with the maximumSize of 8Mb. This because of backwards compatibility to older browsers may stop the request after 8Mb…

When you’ve got larger files, provide the customers another way to upload. Let them send you a CD or allow them to upload it to a FTP server. After that you’re simply able to place the file in the /upload/-folder. Directly in the right folder(you have to create ‘m) or move them afterwards in the content tree.

Hope this helped…
Have a nice day 🙂

SEO and fallback scenarios for Titles

Based on the tips and trics in this topic on the SDN-fora, I’ve decided that it’s time to give you guys some SEO hints and, directly linked to this topic, I’ll discuss fallback scenarios for titles. First of all, a list of Search Optimalisation Tips in combination with Sitecore. They aren’t new for any experienced webdeveloper, but they are commonly forgotten!

  • Allow your editors to define keywords and the description for the page. When these field are blank, define together with your customer to fall back on the homepage or some predefined values.
  • Remove unnecessary tags, such as ‘creator.description’ in the head-section of your HTML. It might be marked as search engine spam these days.
  • Build a self readable explaining title: [Company Name] – [Sitecore Section]  – [Page Title], but don’t write down all your keywords here! Again marked as spam…
  • Make the users able to define the Page Title by their own, but limit the size of their content field so they can’t make a mistake such as filling in the keywords.
  • Set the text filled in at the description page(as mentioned in the first item), as the title for the links created in navigations and sitemaps.
  • Use H1/H2/H*-tags in the right way. Just one H1 on a page.
  • Allow users to define H3’s using the rich text editor.
  • Make urls accessible in 3 ways: page.aspx / page and page/.
  • Provide a Google Sitemap
  • Don’t forget the images! Sitecore kind of requires in 5.3 to fill in the Alt-tag. Allright, that’s nice unless it isn’t rendered…

Well when all of the above is implemented, make sure there is lots of variabel content and make sure the editors are aware of SEO and how to write search engine friendly content.

Now to the fallback scenarios. What do I mean with fallback scenarios? It isn’t so hard at all, a fallback scenario is the steps that you take when a content field, you expect to be filled isn’t filled in by the user. This might have 2 reasons:

  1. You haven’t set up any validators on fields, so users are able to fill the boxes with everything they want including leaving the fields blank…
  2. By design you do allow field to be empty

In the last circumstance, you have to make sure what to do when you detect the field is empty. Because you have to display at least a simple link / page title / text. So you have to define what is going to happen when the field is empty, which field to use, and when that field is empty…, etc. And while writing this, I recognise one of the biggest cause of change requests: there are not enough field defined… The customer wants to show another title in the menu as shown on the page or in the title-tag in the head. So when you’ve collected all you fields. Do define together with your customer what the fallback steps are. So the right content is always displayed.
And if you want to make sure there’s always something displayed, make Item.Name your last fallback step…

Content Management in 2007, Part 1: Consolidation and collaboration

As a reaction on this trilogy of articles (in Dutch) or maybe even more my opinion of the (W)CMS world in 2007.  The most important aspects of this changing world (trends) are reviewed from my sight as upcoming Content Management Specialist at LECTRIC. And most important, to participate in the innovative world of which might be called ‘Web 2.0’.

The kickoff of this set of blogposts is done a late Friday night. Actually I’m to late writing these posts. All newssites on the internet and even the most populair blogs have already published their vision on 2007. I would rather suggest to call this set of posts more a review on the development of the Content Management Market instead of an end of the year prediction.

Looking back on 2006 we have seen a changing world: The enterprise product catalog has changed dramatically. Just a couple of examples: Oracle has bought Stellent, IBM became the proud owner of FileNet and just before the end of the summer, Open Text reached an agreement on acquiring Hummingbird. And that was just for the Enterprise segment! The news in the Web segment was dominated by the news that the same Open Text was presenting a new webstrategy by collaborating with RedDot WCMS. A big Canadian WCMS company, Hot Banana, was acquired by the, for me less known, J.L. Hasley Corporation.

And ofcourse, we have seen the upcoming of Microsoft Office Sharepoint Server 2007. From the first beta’s, several Microsoft Partners over the world have implemented MOSS2007 succesfully. The list of additional, new and improved functionality is endless but the temprature of the community is already a lot of lower. By the way, is it launched already ;)?

The main reason of the huge enterprise distributors to acquire those small parties is just because because of the climate in the web-world. With changing perspectives from huge companies as Microsoft and a new set of Mashups delivert by Google, the big distributors have been waken up. By buying smaller parties with just a slight, but missing, expertise, the core products aren’t going to change. It’s more future work. Those ‘new’ features, such as analystics have always been there, but are hot nowadays. By changing your company strategy you’ll show the world outside you’re innovating.

But what is going to happen with the existing software and source code of the smaller companies? Well, quite simple, as the team of genius engineers, architects and product managers has already left the new company, this product won’t be enhanced anymore. The core product of the acquirer will improve a little by the new concepts, but taking the risk to combine the best of both worlds(and create a new, really innovative product) won’t be taken by any of the companies.

Last but not least, we’ve got the commercial perspective. Any economist will agree with me when I say that the best way to destroy a opponent is by acquiring all its shares. You won’t lose directly all of the customers and you saved yourself stuff like marketing campagnes, etc. As described above, it can even improve your product a bit more. And last and maybe the most important reason: from a sales perspective, you become a bigger sheep in the market so ‘changing startegies’ will be taken serious. For the first time?

So what does this mean for 2007? I actually think we should expect tons of new documentation on the web. The distributors have been able to migrate the minimal set of products, they allow to live on, to their own styles. Ofcourse last years’ strategies will not meet those new product, so for this reason alternating strategies are launched. Generally these alternating strategies will contain the collaboration of the foreign ECMS/WCMS with the distributors’ own ECMS. Next to that integration, cool and funny stuff like usability and analytics become part of the basic set of tools around the systems.

That’s it for now, hope you canu nderstand whatI’m trying to say. Feel free to discuss my opinion or correct me.
The other articles will be written about multimedia, crossmedia and new media(such as blogs). The last article will reflect these changes on the product Sitecore.

Security Editor: Disallowing access to a domain…

Thursday is the day, I normally go to school, but as schools are closed the first week of January, I had a day off. As the boys @ work know it’s allowed to disturb me, they regarly will :). They are so kind to ask if it’s allowed, so I can do something about it if I want to, but as most of the question are quite challenging I won’t.

Today our teamlead, Martijn, had a question how to restrict access for domains in the User Manager. The answer this afternoon was: no… But actually, I’ve found a solution without writing code! Here’s a lesson: hacking the client :).

First of all, have looked in the Core database if the domain were confiured there. Under the node of the application for example. They aren’t… 
Second, I’d to found out what’s the exact XAML-file behind the User Manager. It’s ‘Security Manager.xml’ located in ‘/sitecore/shell\Applications/Security/Security manager/’. I opened the file and searched for any DataSource definitions defining the domain. To bad, there wasn’t one… As the XAML-file specified the code beside, I had at least a path to continue searching:

<CodeBeside Type=”Sitecore.Shell.Applications.Security.SecurityManager.SecurityManagerForm,Sitecore.Client”/>

Continued searching using Lutz Roeder’s .NET Reflector. I openend Sitecore.Client and lucky me, it isn’t dotfuscated :). Navigated to the SecurityManagerForm-class and opened the client-property. Look what the Disassembler explained to me:

Indeed it’s a ClientPage property which means it is set before. And indeed it is… In the OnLoad method(look at the highlighted part):

My simple conclusion was that I just had to change the QueryString parameter ‘do’ to default select a domain… As our customer should only be able to read the contents in the Extranet domain, we should set the qs to ‘do=extranet’ and disallow the ribbon for anyone except administrators.

Well, we should  change the QueryString of a Sheer Application. A bell is ringing… A Sheer App is called from the menu. Menu items are shortcuts to Sheer Apps… Let’s duplicate a ‘shortcut’ a play a bit around with the field inside the ‘shortcut’ and it works!

 

Cool! Now it’s just up to the security. I’m going to disallow the Domain-ribbon for the userrole our customer works with and after that the User Manager looks like this:

Wohooo :). Mission accomplished! And now… Time to sleep :P. See you tomorrow!

Using predefined FieldIDs and ItemIDs

Next to the Util-classes in the root-namespace of Sitecore. There are also lots of constants defined in different classes. It are to many of them and describing would definitelly take to much time, so I’ve just capy and pasted the full list with the documentation written by the Sitecore developer self:

  • ArchivedItemFieldIDs – Fields of the Tasks/Command template.
  • CommandFieldIDs – Fields of the Tasks/Command template.
  • CommandsCommandFieldIDs – Fields of the Commands/Command template.
  • DeviceFieldIDs – Fields of the Layout/Device template.
  • FieldIDs – Implements a static class for holding well-known GUIDs relating to fields.
  • ItemIDs – Implements a static class for holding assorted well-known GUID values.
  • LayoutFieldIDs – Fields of the Layout/Layout template.
  • PackageRegistrationFieldIDs – Fields of the ‘Packages/Package registration’ template.
  • RoleFieldIDs – Fields of the Security/Role template.
  • ScheduleFieldIDs – Fields of the Tasks/Schedule template.
  • SecurityDatabaseTemplateIDs – Implements a static class for holding well-known GUIDs relating to templates.
  • ShellFieldIDs – Implements a static class for holding assorted well-known GUID values.
  • SystemFieldIDs – Implements a static class for holding well-known GUIDs relating to template fields.
  • TemplateFieldIDs – Implements a static class for holding well-known GUIDs relating to template fields.
  • TemplateIDs – Implements a static class for holding well-known GUIDs relating to templates.
  • TemplateSectionFieldIDs – Implements a static class for holding well-known GUIDs relating to template sections.
  • UserFieldIDs – Fields of the Security/User template.
  • WorkflowFieldIDs – Implements a static class for holding assorted well-known GUID values.

So how are these FieldIDs used? Well they are actually the core of the system. I’ll show you how you can implement your own simple ‘ContextItem’.
First of all we create a ContextItem constructor with 1 argument: an innerItem where we can retrieve the data from.
And after that, we introduce the 2 fields, Created and Published with some dummy values.

    1 using System;

    2 using Sitecore;

    3 using Sitecore.Data.Items;

    4 namespace SitecorePlayground.Examples

    5 {

    6     class ContextItem

    7     {

    8         private Item _innerItem;

    9         public ContextItem(Item innerItem)

   10         {

   11             this._innerItem = innerItem;

   12         }

   13 

   14         public DateTime Created

   15         {

   16             get { return DateTime.Now;  }  

   17         }

   18         public DateTime Published

   19         {

   20             get { return DateTime.Now; }

   21         }

   22     }

   23 }

After that, we’ve to retrieve the fields from Sitecore. We’ll use our innerItem for data. But now, the fieldnames… Names? No we are going to use Sitecore.FieldIDs. The code will look like this:

    1         public DateTime Created

    2         {

    3             get { return this._innerItem.Fields[Sitecore.FieldIDs.Created];  }  

    4         }

But this will not compile, we have to convert the Value of the field to a DateTime:

    1         public DateTime Created

    2         {

    3             get {

    4                 string fieldValue = this._innerItem.Fields[Sitecore.FieldIDs.Created].Value;

    5                 return Sitecore.DateUtil.ParseDateTime(fieldValue, DateTime.Now);

    6             }  

    7         }

Finally the code will look like this, but can be highly improved by checking if the field do actually exist, checking if the innerItem is not null, etc:

    1 using System;

    2 using Sitecore;

    3 using Sitecore.Data.Items;

    4 namespace SitecorePlayground.Examples

    5 {

    6     class ContextItem

    7     {

    8         private Item _innerItem;

    9         public ContextItem(Item innerItem)

   10         {

   11             this._innerItem = innerItem;

   12         }

   13 

   14         public DateTime Created

   15         {

   16             get {

   17                 string fieldValue = this._innerItem.Fields[Sitecore.FieldIDs.Created].Value;

   18                 return Sitecore.DateUtil.ParseDateTime(fieldValue, DateTime.Now);

   19             }  

   20         }

   21         public DateTime Published

   22         {

   23             get

   24             {

   25                 string fieldValue = this._innerItem.Fields[Sitecore.FieldIDs.PublishDate].Value;

   26                 return Sitecore.DateUtil.ParseDateTime(fieldValue, DateTime.Now);

   27             }

   28         }

   29     }

   30 }

Explore the classes metioned above using on SDN or download a CHM-file and take advantage of this provided functionality!

Good way to start improving your Sitecore Solutions: Context/Util Objects

This post is a good example of how your proces of building software can improve a lot over the year. Where I want to talk about is quite simple: retrieving your data from Sitecore using C# / VB or any other .NET-enabled language.

The problem:
Customers are never happy when websites do not work at all. It’s quite annoying for those guys when Sitecore delivers some the ‘UnhandledException.aspx’ or  the damn ugly yellow and red page. Haven’t tested so far, but Hans told me once, he should be able to make the server crash just because of the uncaught Exception objects. I do believe him, which makes this problem a category 1 problem: functionality AND security…

Ways to keep your customer happy:

  1. Create delicious Error pages. Designers are able to let exception taste like cookies. Just by giving the exception the color of the website. Implementation can be done by replacing the UnhandledException.aspx.
  2. Report to your maintenance department exception are occuring, buffer them(1 exception per hour is more then enough!), but send them. At least, log them so you can recover and reproduce it!
  3. When functionality behaves unexpected because of wrong user input, just create an ugly Literal with the message such as ‘User input isn’t valid, please try again’. Crashing or even worst, a UI which doesn’t react makes the user click again on the Submit button, and on all those others… Stresstesting is preformed indeed in a way uncontrollable way!

Solution:
I’ll not say this is a solution for all but it works for 90% of our exceptions: Create a Context/Util class with method such as:
GetFieldFromItem(Item currentItem, string fieldName). Here are some examples used in the project I’ve worked on today:

/// <summary>
/// Return the friendlyUrl from an item, based on a path in the Sitecore tree
/// </summary>
/// <param name=”itemPath”>the path to return the friendly url from</param>
/// <returns>friendly url of the path, returns “#” as default</returns>
public static string GetUrlFromItem(string itemPath)
{
// set the default return value
string url = “#”

// check for null-references
if (!string.IsNullOrEmpty(itemPath))
{
// retrieve the item, based on a path
Item myItem = Sitecore.Context.Database.GetItem(itemPath);

// check for null-references
if (myItem != null)
{
// call the custom getFriendlyUrl method
url = Context.getFriendlyUrl(myItem);
}
}

return url;
}

/// <summary>
/// Get a boolean from checkbox field
/// </summary>
/// <param name=”currentItem”>the Sitecore item that containt the field</param>
/// <param name=”fieldname”>the name of the field to retrieve</param>
/// <param name=”defaultValue”>value to return when item doesn’t exists</param>
/// <returns>a bool with the fieldvalue. It returns the default value when field isn’t available</returns>
public static bool GetBoolFromItem(Item currentItem, string fieldname, bool defaultValue)
{
CheckboxField chbField = currentItem.Fields[fieldname];
if (chbField == null)
{
return defaultValue;
}
else
{
return chbField.Checked;
}
}

 

All fields are accessed using the class containing the above methods. It’s a lot more flexible. Take a look at these lines:
// call the custom getFriendlyUrl method
url = Context.getFriendlyUrl(myItem);
So we are able to preform our own formatting of the created links, for Search Engine Optimalisation for example! And, the most important, we are sure we will never return ‘null’. So nullpointer will NEVER occur.
This kind of methods should be (Unit-)tested very carefully.

Ofcourse this isn’t ‘the solution’ for all. I do always compare these small solutions for much hugher problems with the way you build an application in Ruby On Rails ;):
Create WebApplication With Rich Internet2 Aspects Running On Webserver

That’s impossible, Rome wasn’t built in 1 day and the same for Sitecore solution, they aren’t stable by just writing code like above! More on this topic soon as more and more people are asking for it…

JSON in the news

Because of the GMail vulnerability the XML vs JSON discussion has started again. And as you might know, Jakob has implemented JSON in the last version of the Sitecore version because of it’s lots of quicker and it saved him expanding the codebase. Now lots of discussions have started what’s the best and most secure solution.


Full number notation in JSON

When you’re interested in just the way the Sitecore Client works, the following links aren’t recommended lecture for you, but if you think you’re going to use JSON or even built your own advanced Sheer/JSON apps, the following links are a must read:

Taking advantage of the Sitecore-namespace

One of my favorite namespaces is ‘Sitecore’.  It contains so many Util classes I commonly use:

DateUtil – Providing parse and serialize functionality for DateTime’s, TimeSpan’s and ISO-Dates.
Converting/Parsing
DateTime – ParseDateTime(String value, DateTime default)
DateTime – ParseDateTime(String value, DateTime default, CultureInfo ci)
TimeSpan – ParseTimeSpan(String value)
TimeSpan – ParseTimeSpan(String value, TimeSpan default)

MainUtil – Environment Util from reflection to IO and from Drawing to Diagnostics.
Some collection utils:
BuildHashtable -> Easily build an Hashtable by a set of object(params or array)
AddArrays -> Merging Arrays incl explicit casting
CompactArray -> Clean up an array when it contains some nulls/empties, ugly but very necesarry in case of untrusted input!
ConvertArray -> ArrayCaster. Might be deprecated as System.Array is extended a lot in 2.0.
GetExtraEntries -> Compare 2 Hashtables return difference… As a Hashtable 😉

Environment method:
GetProcesID, GetProcesInfo, GetProcesMemoryInfo, GetProcesName  -> Way to get to know how the current proces acts.
Trace -> Write a message to the Sitecore-trace
TraceIf -> Equal to Trace except the first argument it makes it act like Debug.Assert.
GarbageCollect -> …..

Reflection stuff:
CreateObject -> Quick invokation:

object MyObject = MainUtil.CreateObject(“/bin/MyAssembly.dll”, “MyNamespace.MyObject”);
object MyObject2 = MainUtil.CreateObject(“MyAssembly”, “MyNamespace.MyObject2”, parameter1, parameter2);

Others:
GetImage -> With all these overloads, any imagetag can be created.
FormatSize -> Convert a logn to a nice string such as ‘2Mb’
AppendMissingIDBrase -> As described in the .chm: Appends a mssing closing brace “}” if a path starts with a brace “{“.
UmapPath -> Instead  of mapping, we’re going to unmap it today. Back to the relative paths!

StringUtil – All kind of System.String methods you wish you had access to before.
Most used:
GetString -> Overloaded method where you can define a value ‘to parse’ and a default one in case of null or empty. The overload provides you params, which selects the first var which isn’t null or empty(GetString(“”, null, emptyInputObject, “default!!”) -> “default!!”).
Unquote -> Remove single and doubles quotes in an efficient way:

string s0 = StringUtil.Unquote(“‘Hello world'”); // “Hello world”
string s1 = StringUtil.Unquote(“‘Hello Andy’s world'”); // “Hello Andy’s world”

CutUp -> Splitting string after x chars returning an ArrayList
Repeat -> Repeat a String n2-times.

UIUtil – Very quick way to access (browser-)variables and other usefull others.
Non XAML developers:
IsIE -> Indicates wether it’s IE or not.
ParseStyle -> Parse a StyleString to a string

There are lots of more methods and other Utils. Writing and explaining them all will take way to much time. Take a look at the Reference section on SDN. Make sure you look in the right API-documentation for the Sitecore version you are using.
By the way, there are some other Util-classes, not located in the Sitecore-namespace, but expand Sitecore.IO for example. Tomorrow, I’ll discuss the *IDs-classes in the Sitecore namespace. They are important aswell.

Anyway, next time, before writing your own Util-method, take a look in the above Util-classes, it might accelarate your development a bit! And for those who want to use them in as XSLT extention, take a look at this entry.
Goodnight 🙂

January welcome: Five thing you might not know about me

It is kind of a virus, all those people Tagging each other. Although I haven’t been tagged by myself, when even Scott Guthrie joins the club, the Sitecore community should participate too… I’ll do the kick-off:

  1. I was born 20 years ago, in the beautifull city ‘s-Hertogenbosch in the south of Holland. Only the first 4 years of my live I haven’t lived in ‘s-Hertogenbosch, but in a small county below ‘s-Hertogenbosch: Vught.
  2. At the age of 17, I have finished high school and just 3 days after participating on my last exam, I joined LECTRIC. As a part of a learning/working program, I’ve been able to work and study together. These days, I’m part of the Sitecore team, together with 4 other engineers and responsible for knowledge sharing and the communication with Sitecore.
  3. As an informaticus you might me not expect to be linked to any religious organisation. Well actually I’m a kind of. In one of the nicest city in Europe, Trier in Germany, there’s a kind of Catholic University(Katholische Akademie Trier) located. I’ve been several times in Trier and parcitipated on some of their media-related activities. Not as a believer, but as a human being. The Akademie is located in an unbelievable huge, historic building called ‘Robert Schumann Haus’ with the best view over Trier. For those who become interested and who are able to visit Trier, visit the ‘Robert Schumann Haus’ and immediatelly you’ll notice that the electronic door open in your direction. To say welcome!
  4. Next to computers and programming, I like to play and watch basketball. Going out at least once per week and being a Wikipedia addict :P.
  5. I’ll take several looks on other CMS’s during the year. Although Sitecore isn’t fully explored by myself, I want to get to know some more about the conceptual stuff of portals, e-HRM, etc and look at the way they are implemented on the other side. This might change my view of Sitecore a little. But also gives me the possibility to provide better in-depth articles on my blog :).

Happy new year! Make sure 2007 becomes even better then 2006 or 2005…

I’m going to tag Lars Fløe Nielsen, Jakob Christensen, Ole Thrane, Peter Johansson and Alexey Rusakov. Let’s get this community rollin’…