Issue while programmatically inserting Media Items

Sitecore has described how to create media items by yourself on SDN a while ago. Some how this code was broken while uploading JPG-files larger then 100kb. As I’m currently working on the location fo our customer and they’ve got a lot of network overhead(they are using Novell all over the place…) and the exception told me that the Uploaded file was closed, I decided to check the limits configured in our Web.config.

The httpRuntime Element has a lot of settings which influence the way they are connected to the end-user. I’ve played a little with the maxRequestLength and executionTimeOut. But unfortunetely it didn’t work. Digging in my memory about the specific problem, I remembert that JPG is like, every image format, block based. This might could have something to do with the issue.
There’s a requestLengthDiskThreshold in the httpRuntime. The default size is extremely low(256bytes!). After changing this value to 1kb(1024), it worked again like a charm.

So when you have some issues uploading. Try to add the requestLengthDiskThreshold-parameter to your web.config! I’ll ask the Sitecore Documentation team to add this to the page mentioned above.

Topic of the week: Publishing aliases

I want to pay some special attention to the Publishing Aliases topic on SDN5-Forum. Jennifer Chance, properly a wonderfull lady employed at an unknown Sitecore partner, has asked how she could publish Aliases. By clicking on publish these days, none of the related items will be touched. Of course this approach won’t case any performence issues as the system is doing what you’re asking, but how intuitive is such an approach?

When you’ve got any ideas about this, please feel free to post a reply on the thread and it properly becomes a nice discussion and product enhancement.

Manipulating URLs in 5.3

Last week I found and extremely simple tool in the namespace ‘Sitecore.Text’: UrlString. This class allows me to manipulate URLs in an easy way. Very usefull when you want to extend an URL with a querystring paramater. For example:

UrlString googleUrl = new UrlString(“http://www.google.nl/search?hl=nl”);
googleUrl.Add(“q”, “your search text”);
//Returns http://www.google.nl/search?hl=nl&q=your%20search%20text
Response.Write(googleUrl.GetUrl());

Or even when you want to change the protocol:

UrlString dotSitecoreFeed = new UrlString(“http://sitecore.alexiasoft.nl/feed/”);
dotSitecoreFeed.Protocol = “feed”;
//Returns feed://sitecore.alexiasoft.nl/feed/
Response.Write(dotSitecoreFeed.GetUrl());

Have a nice day!

Avoiding localhost

I’ve seen it over and over, programmers who use the literal “localhost” in their code. Together with Sitecore it’s absolutely NOT necesarry. Please, use Sitecore.Web.WebUtil.GetServerUrl() instead. It avoids plenty of strange issues while deploying.

Note: make sure that you place a slash after the output of the method as it doesn’t contain any by default.

By te way, it would be very cool to implement it by default in the UrlAgent in the scheduling section of the web.config. A lot of developers forget to configure it when they release their project… And the keepalive is very important as it makes sure all the Sitecore background threads stay awake :

<agent type=”Sitecore.Tasks.UrlAgent” method=”Run” interval=”01:00:00″>
    <param desc=”url”>http://localhost/sitecore/keepalive.aspx</param>
    <LogActivity>true</LogActivity>
</agent>

Properly a good suggestion to submit to Sitecore support… Tomorrow :P.

Improving productivity – Part 1 of X

Yes, I start this post with Part 1 of X. A lot of you guys have noticed that I’m not that good at finishing blogseries. I guess that’s the result of trying always be one step ahead. you forget what’s ahead ;-).

Well back to the subject again: productivity. For a long time I’m noticing that a lot of colleagues are writing and rewriting the same code on daily base. Not because it’s not efficient enough, but just because it’s another (new) customer or it’s a slightly different implementation of the same stuff. I really hate it when I’ve to rewrite my own work over and over. Mostly because our (X)HTML and CSS-guru’s and even designers are reusing lots of their ideas and products. For example, a Sitemap stays a Sitemap, a navigation stays a navigation and even lists with paging(such as search results and category lists) have the same layout or at least the same (X)HTML. I want to get right of changing my code for a single CSS-class or even rewriting my whole sitemap.xslt or .cs.

For a while now I’m studying on the best way to work with ASP.NET. A part of this study became a closer integration with Sitecore. 2 weeks ago, I reached finally decided to publish my work it as an Add-on to Sitecore. It will be a bigger product then just the some webcontrols, but later more on the absolute goals of the project and the final product. First some results. So here’s the code you will use in the near future for creating a Sitemap or a BreadCrumb:

<asp:SiteMapDataSource ID=”SiteMapDataSource1″ runat=”server” />
<asp:TreeView ID=”tvSitemap” runat=”server” DataSourceID=”SiteMapDataSource1″ />
<asp:SiteMapPath ID=”smpBreadCrumb” runat=”server” />

That can’t be true, can you believe it ;-)? Well I do!
Ofcourse there’s some additional configuration need. In this case we’ve to update the web.config. I’ve written a SiteMapProvider for Sitecore. And it seems to perform as well. So to the Web.config, how does it look like?

    <!– SiteMap Provider Configuration –>

    <siteMap enabled=true defaultProvider=SitecoreSiteMapProvider>

      <providers>

        <add name=SitecoreSiteMapProvider

            type=Sitecore.Web.SitecoreTreeSiteMapProvider

            site=Website

        />

      </providers>

    </siteMap>

I think you can live with that amount of rules don’t you? Of course, you’ve to add your own CssClasses. And you’re properly a bit worried about the produced (X)HTML, but don’t worry, the package will include some Adapters as well, so your Sitemap will be rendered in a real Web 2.0 way :D.
As you can see you’ve to configure the website, this needs to be done, so the Sitemap isn’t going to cache the whole database. The cache will be flushed every single publish action. So it uses all the right data at anytime.

By now, I’m refactoring my solution for another type of Sitemap. I’ll come back on that in a later entry. The Current TreeSiteMap also misses some extensibility as you are used to. The following 3 features need to be completed, but have to wait till I’ve finished my refactoring(some Base-classes so the further development and creating of your own SiteMapProviders will be very easy).

  1. By now I’m using the Item.DisplayName, I will give you the possibility to override my ‘string GetTitle(Item itemNode)’ in the web.config
  2. Same goes out to the used URL.
  3. StartPath can be defined in the future.

When will all of this be released? Hmmm… Hopefully it will be ready for some alpha testing by the end of September. Some of the chaps around Sitemap already have an old build to play with, but the code is dramatically under development and testing, so you can’t even talk about a pre-alpha.

For now, enjoy coding and have a good weekend!

Adding your own httpHandler to Sitecore 5.3

As you all know, Sitecore has customized the whole ASP.NET framework a little for own proposes. Sometimes this does mean that you have to take a little more actions to get some stuff done. Today I’m going to show you how we can create a cool .ashx. I’m going to generate some extreme cool circles ;).
You properly can do this without following all the steps below and do it how it should be done, but you won’t have a fully initialized Sitecore-context in that case.

First I’ve to think about the url I want to access the httpHandler.
Note: Like Sitecore does with its media and icons, I do recommend to start your url with a tilde(~). The ASP.NET-engine does recognize the tilde as the root, so both the following urls will give you the same page:
http://yoursite.ext/~/media/mypicture.ashx
http://yoursite.ext/something/~/media/mypicture.ashx

My url for generating those cool circle should become:
http://localhost/~/generation/images/cirkel.ashx

Then I’ve to decide how it should be rewritten internal. Media-urls will be rewritten to sitecore_media.ashx inside Sitecore, Icons become sitecore_icons.ashx, etc. I’ll use ‘custom_imagegen.ashx’.

Now we’ve to configure this. First we setup the nice url. Therefor we’ve to open the web.config. Then you’ve to search for the node ‘customHandlers’ under the ‘sitecore’-node. Then add another customHandler like I’ve done below:

    <customHandlers>

      <handler trigger=~/media/ handler=sitecore_media.ashx />

      <handler trigger=~/api/ handler=sitecore_api.ashx />

      <handler trigger=~/rest/ handler=sitecore_rest.ashx />

      <handler trigger=~/xaml/ handler=sitecore_xaml.ashx />

      <handler trigger=~/icon/ handler=sitecore_icon.ashx />

      <handler trigger=~/generation/images/ handler=custom_imagegen.ashx />

    </customHandlers>

Then the we’ve to configure the httpHandler under the ‘system.web’-node:

    <httpHandlers>

      <add verb=* path=sitecore_media.ashx type=Sitecore.Resources.Media.MediaRequestHandler, Sitecore.Kernel />

      <add verb=* path=sitecore_rest.ashx type=Sitecore.Web.UI.XamlSharp.Ajax.RestPageHandlerFactory, Sitecore.Kernel />

      <add verb=* path=sitecore_xaml.ashx type=Sitecore.Web.UI.XamlSharp.Xaml.XamlPageHandlerFactory, Sitecore.Kernel />

      <add verb=* path=sitecore_icon.ashx type=Sitecore.Resources.IconRequestHandler, Sitecore.Kernel />

      <add verb=* path=custom_imagegen.ashx type=Sitecore.TestSite.ImageGenerator, Sitecore.TestSite />

    </httpHandlers>

As you can see, I’ve configured a class to the handler. Make sure the class implements System.Web.IHttpHandler and its members.
I’ve created the following demonstration class to test if my configuration works:

    1     public class ImageGenerator : IHttpHandler

    2     {

    3         #region IHttpHandler Members

    4 

    5         public bool IsReusable

    6         {

    7             get { return true; }

    8         }

    9 

   10         public void ProcessRequest(HttpContext context)

   11         {

   12             context.Response.Write(context.Request.RawUrl);

   13         }

   14 

   15         #endregion

   16     }

After building the solution it becomes time to test my implementation. Let’s try: http://localhost/~/generation/images/cirkel.ashx. And as expected, the page returns:

/~/generation/images/cirkel.ashx

Note: Make sure you set ‘IsReusable’ to true as it indicates weather the system can reuse the instance of the class for another request.
Alright, so that seems to work! Now it’s time to create a cool circle generator…

    1     public class ImageGenerator2 : IHttpHandler

    2     {

    3         #region Field(-s)

    4         public int DefaultAlpha

    5         {

    6             get

    7             {

    8                 return 80;

    9             }

   10         }

   11         public Color DefaultColor

   12         {

   13             get

   14             {

   15                 return Color.Red;

   16             }

   17         }

   18         public Size DefaultSize

   19         {

   20             get

   21             {

   22                 return new Size(200, 200);

   23             }

   24         }

   25         public int QueryStringAlpha

   26         {

   27             get

   28             {

   29                 return GetIntFromQueryString(“alpha”, DefaultAlpha, 255);

   30             }

   31         }

   32 

   33         public Color QueryStringColor

   34         {

   35             get

   36             {

   37                 return Color.FromArgb(GetIntFromQueryString(“c”, DefaultColor.ToArgb(), 2000));

   38             }

   39         }

   40         public Size QueryStringSize

   41         {

   42             get

   43             {

   44                 return new Size(GetIntFromQueryString(“w”, DefaultSize.Width, 2000), GetIntFromQueryString(“h”, DefaultSize.Height, 2000));

   45             }

   46         }

   47         #endregion

   48 

   49         #region IHttpHandler Members

   50         public bool IsReusable

   51         {

   52             get { return true; }

   53         }

   54 

   55         public void ProcessRequest(HttpContext context)

   56         {

   57             WriteResponseHeader(context);

   58 

   59             using (Bitmap myImg = new Bitmap(QueryStringSize.Width, QueryStringSize.Height))

   60             {

   61                 DrawOnBitmap(myImg);

   62 

   63                 MemoryStream ms = new MemoryStream();

   64                 myImg.Save(ms, ImageFormat.Png);

   65                 ms.WriteTo(context.Response.OutputStream);

   66             }

   67         }

   68         #endregion

   69 

   70         #region Protected Members

   71         protected void WriteResponseHeader(HttpContext context)

   72         {

   73             context.Response.ClearHeaders();

   74             context.Response.AddHeader(“Content-Type”, “image/png”);

   75             context.Response.AddHeader(“Content-Transfer-Encoding”, “binary”);

   76             context.Response.CacheControl = “public”;

   77         }

   78 

   79         protected void DrawOnBitmap(Bitmap image)

   80         {

   81             Rectangle rect = new Rectangle(Point.Empty, QueryStringSize);

   82 

   83             //Hack to make sure the Ellipse fits in my Image

   84             rect.Width–;

   85             rect.Height–;

   86 

   87             using (Graphics g = Graphics.FromImage(image))

   88             {

   89                 g.SmoothingMode = SmoothingMode.AntiAlias;

   90                 Color c = Color.FromArgb(QueryStringAlpha, QueryStringColor.R, QueryStringColor.G, QueryStringColor.B);

   91 

   92                 g.DrawEllipse(new Pen(c), rect);

   93                 g.FillEllipse(new SolidBrush(c), rect);

   94             }

   95         }

   96         #endregion

   97 

   98         #region Private Static Helper(-s)

   99         private static int GetIntFromQueryString(string key, int defaultValue, int maxValue)

  100         {

  101             string qsValue = HttpContext.Current.Request.QueryString[key];

  102             int resultValue;

  103 

  104             if (!string.IsNullOrEmpty(qsValue) && int.TryParse(qsValue, out resultValue) && resultValue <= maxValue)

  105             {

  106                 return resultValue;

  107             }

  108             return defaultValue;

  109         }

  110         #endregion

  111     }

Playing around with the options described above showed me that /~/media/ is hardcoded in a lot of Sitecore-code. That’s a pity. Hopefully one of the developers will pick this up and fix it in the next build.

Tips 4 debugging your ‘hanging’ Sitecore applications

Yesterday we had a serious issue with one of the improved layout for a release 2 of one of our projects. As it really became a show stopper for 2 of my colleagues I decided to give it the highest priority. While debugging I came to the conclusion I wasn’t really following a straight path. Just ‘doing something’. So 10 minutes ago I wrote down the most of the steps taken and I want to share them with you. So you can debug your apps in a way better way.

Usefull requirements for debugging:

  • Always try to have a read-only acocunt to the production environment. I know it’s  from a security point of view not always a good choice, but when it remains read-only, it won’t harm your production environment ever.
  • Make sure you’ve got a quite clean machine. A SQL Server 2005 with CLR Support will make your results less obvious. Same goes out to BizTalk, multiple webservers, etc. So try to isolate your problem.

Steps to take:

  1. Identify where the issue is
    1. Walk trough your logfiles. Are there any warning such as:

      2572 10:43:30 WARN  Timing threshold exceeded for web page. Milliseconds: 30436,72. Threshold: 1000. Page URL: /Sitemap.aspx
      2572 10:43:30 WARN  Item threshold exceeded for web page. Items accessed: 8940. Threshold: 1000. Page URL: /Sitemap.aspx

    2. Run the Sitecore debugger and tracer
    3. Enable and disable sublayouts and renderings
    4. In some cases you’ve to select another Layout/Masterpage
    5. When you can’t find anything, just attach Visual Studio to your ASP.NET-process, reload the page and wait for exceptions/overflows. When this doesn’t help, use the debugger-pause button and manually step trough your code.
  2. So now you’ve identiefied where the issue is you general got 2 options, XSLT or code. For both I’ve some hints as well:
    • XSLT
      • Find out if you aren’t running trough to many levels of items.
      • Try to minimize your amount of data used.
      • XPath, Axes and predicates are extremely heavy get rid of them!
      • Make sure you made the right choice when using developing this functionality.
      • Are you using caching? Is this functionality cachable?
    • Code
      • Using Sitecore Query? Read this post by Sitecore’s Kim Hornung on Query performence.
      • Are there any haevy operation such as connections/regexp/data convert(e.g. XmlDoc construction)
      • Is your code accessed once or more often? Aren’t you databinding twice per pageview for example?
      • Use SectionTimers to divide your page in clear pieces.

Happy debugging!

Creating media items using the API

There’s a real cool topic on SDN5-Forum about creating items using the API. A bunch of active chaps from the community are present there including Peter who provides a nice solution.

Make sure you also read the following reply written by myself on using the EditContext:

It’s not really recommended to use the EditContext as the code will run out of that scope when an exception occurs. I would rather suggest to use Item.Editing. The ItemEditing class allows you to use transaction-like methods such as AcceptChanges, BeginEdit, CancelEdit, EndEdit, RejectChanges, etc. This will improve the readability and flow of your code.

You might expect the using-contraint to be the best option, but it isn’t! Please be aware of this when you write production code.

Sitecore seems to listen to feedback

Just foudn out that Sitecore really listens to feedback :). A while ago I sent the developer my own URLUtil as Item.Path.GetFriendlyUrl() seemed to create broken links for more advanced site-configs.
So I spent a whole day on writing this util and look, the latest build(earlier build might have it too) has the following overloads:

  1. GetFriendlyUrl() //Default, no interface changes 
  2. GetFriendlyUrl(bool shorten) //Default, no interface changes
  3. GetFriendlyUrl(string sitename) //Resolve url by site
  4. GetFriendlyUrl(string startPath, string virtualFolder) //Same a above but now you can control your own startath and virtual folder

Goo to see that Sitecore actually listens to this kind of feedback. Altough I remember I had a very strong case, I didn’ t expect them to accelarate this quick without breaking any interfaces at all :).
Note: haven’t tested  it fully, but it seems to work :).