Musielak Marek

Posted on Tuesday, July 21, 2009 by Marek Musielak

ASP.NET web site performance

I've been working on a site for a tile and wood flooring specialist store recently. That was my first own project on such a big scale. Ok, maybe not so big comparing to projects that I worked on as a Cognifide employee, but still pretty big as a single person project. It was a challenging experience for me as I set up a goal for myself - the site has to load as fast as possible.

The result can be seen here el-ART. The site is in Polish but there is no need for understanding the content so don't worry ;)

Here is the full story of my work with this site.


Many web developers think that if the site is small then they don't have to worry about the speed of the response time. Unfortunately, they are wrong. Look at the site again (el-ART). There was not much html there but there were about 15 images (including logos and css images), several css files and couple of scripts. 30 or 40 requests per every page load. Then I started optimization - there are dozens of tools which can help you with it - I prefer Page Speed Firefox addon.
Lets go step by step with several of it's clues:

Combine external CSS


There are several ways of reducing the number of requests that are sent by the browser. One of them is combining external css files. The easiest way for this is just to create a single file and copy the content of all css files into the new file. Then just replace all previous css links with the one to the new file. However, the solution is not perfect. If you have several files, you can easily keep order in them and it's easy to find what you need. With one file it becomes a challenge.

But there is an easy solution - you can create your own handler that will combine all css files for you and will return them as a single response. If your site is an ASP.NET site, you can use custom resource handler like this one. If you use other environment, you will find something similar for sure. I used my own one with gzip compression enabled, extended caching and setting header values. It not only decreases the number of the requests, but reduces the size of the response as well.

Combine external Javascript


This one is pretty similar to combining css files. However, it has to be extended if you are using Web Extensions - the site will use a lot of .axd files and it's a little bit harder to cope with them. But Damian Kulik created a solution for this which can be found here http://damikulik.blogspot.com/2009/07/script-and-styles-optimizer-for-aspnet.html. I'm not going to copy and paste from his blog here so if you want to know more about it then just stay on his blog for a couple of minutes.

Optimize the order of styles and scripts


The order of the styles and javascript files is really important. Sometimes it is enough just to move link up or down on the page to decrease the time of loading page significantly. How? It's all about the parallelization downloads. The general rule is: css files should be in the < head /> tag, while js files should be placed as far in the content as it is possible, sometimes even just before the end of the < body /> tag. More about ordering on google code.

Optimizing images


There are 2 main rules here:
- use compressed images - in many cases you can compress your images so they look exactly the same but they are smaller. Page Speed will compress the files for you and display links to compressed images so you can use them on your site.
- do not resize images in html - do not display big images that are resized - the browser will have to download the big file anyway and, what is worse, IE browsers use a pretty bad algorithm for resizing images so they look not nice.

CSS sprites


This one is huge! Probably I should mention about it on the very top of the article but never mind. The whole idea of CSS sprites is described on the css tricks site. Instead of downloading dozens of images and wasting time for requesting all of them, you can download only one image and display parts of it wherever you need them. Take a closer look at my site again (el-ART) - there are 6 links with images in the bottom part of the page. If you would check their properties you would see that all of them has the same background - gallery.jpg, just moved with background-position css property. The image is smaller than 6 separate images and browsers load it several times faster.

Compress response


One more thing that could be done is compression of the response html. When you write html then you should format it so it could be easily read and maintain, but when you send it to the user, it should be as small as possible. It really easy to apply it in ASP.NET. The only thing to do is to edit the Application_BeginRequest method in Global.asax.cs class as follows:
protected void Application_BeginRequest(object sender, EventArgs e)
{
if (Request.RawUrl.ToLower().EndsWith(".aspx"))
{
string acceptEncoding = Request.Headers["Accept-Encoding"];

if (!string.IsNullOrEmpty(acceptEncoding))
{
acceptEncoding = acceptEncoding.ToLower();

if (acceptEncoding.Contains("gzip"))
{
Response.Filter = new HtmlCompressStream(Response.Filter, CompressionMode.Compress,
HtmlCompressStream.CompressionType.GZip);
Response.AddHeader("Content-encoding", "gzip");
}

else if (acceptEncoding.Contains("deflate"))
{
Response.Filter = new HtmlCompressStream(Response.Filter, CompressionMode.Compress,
HtmlCompressStream.CompressionType.Deflate);
Response.AddHeader("Content-encoding", "deflate");
}
}
}
}



Decrease loading time - summary


All those optimization tips helped me to create the site that is displayed very fast. There are only 12 requests for the content, the size of all of them is about 210KB, and the site loads for me in less than 1 second. Just to show you the difference, BBC site uses 82 requests (556KB) and loads about 10 seconds for me.

If you have any interesting experience with increasing performance of the ASP.NET sites or want to show how you deal with optimizing issues, do not hesitate to leave your comment below.



Read More »

Posted on Friday, May 15, 2009 by Marek Musielak

EPiServer - hiding 'Workflow' and 'Statistics' tabs

When you use edit mode of the EPiServer CMS and select any of the pages then you see 5 tabs above it: "View", "Edit", "Version List", "Workflow" and "Statistics". While the first 2 of them are used frequently and the third one ("Version List") is pretty useful for advanced users, the last 2 of them ("Workflow" and "Statistics") are redundant in many cases. And editors don't even need to know that they exist. So lets hide them.


EPiServer workflow and statistics tabs



It can be easily done in admin mode with a tool called 'Plug-in Manager' which can be found on the 'Config' tab.


EPiServer Plug-in Manager


The way of hiding the tabs is slightly different for various versions of EPiServer. I tested it in with 5.1.422.256 and 5.2.375.133 versions.

Hiding 'Workflow' tab:
- in 5.1.422.256 version - choose 'EPiServer.WorkflowFoundation.UI' plugin, switch to 'Overview' tab and deselect 'Workflow (EditPanel)' option in the 'User Interface' section.
- in 5.2.375.133 version - choose 'EPiServer User Interface' plugin, switch to 'Overview' tab and deselect 'Workflow (EditPanel)' option in the 'User Interface' section.

I you need to hide 'Statistics' tab (in both versions) choose 'EPiServer User Interface ' plugin, switch to 'Overview' tab and deselect 'Statistics (EditPanel)' option in the 'User Interface' section.

It can be slightly different in the version of the EPiServer which you use, but the general rule is the same.
Shout it
Read More »

Posted on Wednesday, April 15, 2009 by Marek Musielak

EPiServer - filter page tree view

Recently I was working on the EPiServer site that contains dozens of subsections. Every of them is managed by different editor. I was asked to display in page tree view in edit mode only those pages, that editor has editing access. It is reasonable as having dozens of pages (all marked with padlock) makes editing harder or at least less comfortable. Lets do not talk more about the background and take a look at implementation...


In general I think that EPiServer code is a little bit too sealed. I hate all those classes where you can not reimplement part of the code on your own or where you can not overwrite methods. However, this time I was nicely surprised. It was enough to create custom implementation of the EPiServer.PlugIn.PlugInAttribute and use DataFactory.Instance.FinishedLoadingChildren event.

Actually, on the beginning I wanted to use DataFactory.Instance.LoadingChildren and set RequiredAccess to AccessLevel.Edit (see below), but it didn't work for me. If you know why, please comment so I can learn something :)
private static void Instance_LoadingChildren(object sender, ChildrenEventArgs e)
{
e.RequiredAccess = AccessLevel.Edit;
}


First I created my class inheriting from EPiServer.PlugIn.PlugInAttribute and implemented Start method so it adds new ChildrenEventHandler to the DataFactory.Instance.FinishedLoadingChildren event:
using System.Web;
using EPiServer;
using EPiServer.Configuration;
using EPiServer.Core;
using EPiServer.PlugIn;
using EPiServer.Security;

namespace Maras.TreeAdapter
{
public class TreeAdapter : PlugInAttribute
{
public static void Start()
{
DataFactory.Instance.FinishedLoadingChildren += Instance_FinishedLoadingChildren;
}

private static void Instance_FinishedLoadingChildren(object sender, ChildrenEventArgs e)
{
if (IsAccessCheckNecessary(e))
{
int index = 0;
while (index < e.Children.Count)
{
if (e.Children[index].ACL.HasAccess(PrincipalInfo.Current.Principal, AccessLevel.Edit))
{
index++;
}
else
{
e.Children.RemoveAt(index);
}
}
}
}
}
}

As you can see, I check whether the access control is necessary and then I remove all the children that current user is not allowed to edit. Pretty important is the IsAccessCheckNecessary method. My implementation assumes that I want to filter pages in edit mode and for the children of the start page only, so it looks like this:
private static readonly string UI_URL = Settings.Instance.UIUrl.ToString().ToLower();

private static bool IsAccessCheckNecessary(ChildrenEventArgs e)
{
return e.PageLink == PageReference.StartPage &&
HttpContext.Current.Request.Url.ToString().ToLower().StartsWith(UI_URL);
}


If you know any easier way of doing what I needed, feel free to comment below.

Source code can be downloaded from here: source code



Shout it
Read More »

Posted on Thursday, March 12, 2009 by Marek Musielak

EPiServer rich text editor

PropertyLongString and XHTML String are probably the most frequently used types of properties in all EPiServer sites. They are used on nearly all content pages. However I wanted to use the editor control on the standard aspx page. I thought it would be really easy - just put HtmlEditor control on my page and voila. It was a little bit more complex but finally I managed to do what I needed.


Lets start with an aspx page. What we need to do is to put <EPiServer:Property /> on the page and set EditMode attribute to true. I set Width and Height attributes as well but this is optional. Remember not to forget about setting runat="server" property. I also put message panel and button on the page so I can show how to access the text put into the wysiwyg editor. Here is my aspx page:

<%@ Page Language="C#" AutoEventWireup="True" CodeBehind="HtmlEditorPage.aspx.cs" Inherits="MyProject.HtmlEditorPage" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Html Editor Page</title>
<link rel="stylesheet" type="text/css" href="/App_Themes/Default/Styles/system.css" />
</head>
<body>
<form runat="server" method="post">
<asp:Panel ID="pnlMessage" runat="server" Visible="false" CssClass="EP-systemMessage">
<asp:Literal ID="litMessage" runat="server" />
</asp:Panel>
<EPiServer:Property id="myHtmlEditor" Width="500" height="350" EditMode="true" runat="server" />
<asp:Button ID="btnSend" runat="server" Text="Send" OnClick="btnSend_Click" />
</form>
</body>
</html>


Now it's time to write something in code behind. First we need to register scripts that are required by the editor. I used ResolveUrlFromUI and ResolveUrlFromUtil methods but if you know your UI and Util directories then you can put whole paths without using those methods. Now lets create new PropertyLongString. We can select chosen editor options for the property or just select EditorToolOption.All. If you don't want to use any of them you don't have to set it at all. Next set Name of your property and assign it to the InnerProperty of the editor. That's all .You have pretty HtmlEditor on your page.

The last thing is accessing the data from the editor. I tried several ways of accessing it but only one worked for me: retrieving content of the property by using value from Request.Form. If you know any smarter way, let me know. So here is code behind (source code can be downloaded from here: source code):

#region

using System;
using EPiServer;
using EPiServer.Core;
using EPiServer.Editor;

#endregion

namespace MyProject
{
public partial class HtmlEditorPage : SimplePage
{
protected override void OnInit(EventArgs e)
{
base.OnInit(e);

if (!Page.ClientScript.IsClientScriptIncludeRegistered("system.js"))
{
Page.ClientScript.RegisterClientScriptInclude("system.js",
((PageBase) Page).ResolveUrlFromUI("javascript/system.js"));
Page.ClientScript.RegisterClientScriptInclude("system.aspx",
((PageBase) Page).ResolveUrlFromUI("javascript/system.aspx"));
Page.ClientScript.RegisterClientScriptInclude("episerverscriptmanager.js",
((PageBase) Page).ResolveUrlFromUtil(
"javascript/EPiServerScriptManager.js"));
}

PropertyLongString longString = new PropertyLongString();

// select chosen options or use EditorToolOption.All
longString.EditorToolOptions = EditorToolOption.Bold | EditorToolOption.Italic | EditorToolOption.Underline;
longString.Name = "MyLongStringProperty";
myHtmlEditor.InnerProperty = longString;
}

protected void btnSend_Click(object sender, EventArgs e)
{
// yeah this is the only way of accessing what you put in the editor
litMessage.Text = Request.Form[myHtmlEditor.ID + "$ctl00$" + myHtmlEditor.PropertyName];
pnlMessage.Visible = true;
}
}
}


Shout it
Read More »

Posted on Friday, March 06, 2009 by Marek Musielak

TheBugger - to see without looking

In my view, one of the most important developer skill is to see without looking. Let me explain what I mean. Assume that we have a piece of code that have some complex functionality. You see it for the very first time and you want to know how it works and what it is used for. You could debug the code of course. However it would be perfect if you were able to see without looking - look at the code, read it and know what it is responsible for.

As in all other cases training makes a master. But still, doing the same thing to many times makes it boring and even annoying. That's why I do really like to practice my skills in some other ways. One of them is minesweeper. Yeah, the same old minesweeper that you had in your first MS Windows. But the rules of the game are to easy for you. So lets make them a little bit harder.


It's really easy to find all bugs when you have a possibility of marking bugs. But what when you can not tick their location? You have to remember their placement, to see where they are without looking at them. First time is not so effortless. Believe me, the second one is much simpler. And tenth is even easier than you expected. The same is with code reading. So don't give up - practice.

Are you able to debug the field without a possibility of marking bugs? Sure you are. If you weren't, you wouldn't be here ;)



Start again


So how fast have you debugged the field?

Any ideas how to make TheBugger more challenging? Leave your comment and I will consider it for sure.

And what are your ways of training your mind?

Shout it
Read More »