It made me look for the solution for this problem. Sure, I could do the new builds during the nights but what if the site is hosted by external company and you don't have access to the servers? You won't be able to force anyone from that company to stay in the office over night just to deploy the new version of the site.
The other solution would be to send emails to all editors saying that server will be restarted so they can can save all their work. This idea has only only small drawback - it assumes that editors check their emails frequently. I've already spent enough time maintaining sites to know that it barely happens.
So lets go step by step with this solution. Firstly I created the web page that would be used to diplay active users. I put the repater on it:
<asp:Repeater ID="rptUsers" runat="server">
<HeaderTemplate><table></HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# ((MembershipUser)Container.DataItem).UserName %></td>
<td><%# ((MembershipUser)Container.DataItem).LastActivityDate.ToString("HH:mm:ss")%></td>
</tr>
</ItemTemplate>
<FooterTemplate></table></FooterTemplate>
</asp:Repeater>
and overrode OnLoad method:
public partial class OnlineUsers : SimplePage
{
private static DateTime applicationStartTime;
public static DateTime ApplicationStartTime
{
set { applicationStartTime = value; }
}
protected override void OnLoad(EventArgs e)
{
if (!User.Identity.IsAuthenticated)
{
AccessDenied();
}
List<MembershipUser> users = new List<MembershipUser>();
foreach (MembershipUser user in Membership.GetAllUsers())
{
if (user.IsOnline && user.LastActivityDate > applicationStartTime)
{
users.Add(user);
}
}
users.Sort(delegate(MembershipUser u1, MembershipUser u2)
{ return u2.LastActivityDate.CompareTo(u1.LastActivityDate); });
rptUsers.DataSource = users;
rptUsers.DataBind();
base.OnLoad(e);
}
}
On the beginning I though it would be enough to check MembershipUser.IsOnline property, but it turned out that when application is started all users are treated as online, cause MembershipUser.LastActivityDate is set to the time when application started. That's why I added applicationStartTime field that I set in Global.asax.cs file in Application_Start method and compare it with LastActivityDate property:
public class Global : EPiServer.Global
{
protected void Application_Start(Object sender, EventArgs e)
{
OnlineUsers.ApplicationStartTime = DateTime.Now;
}
}
And that's all. I can check whether my build would interrupt anyone's work. Remember, a happy customer is your walking advertisement. Lets try not to upset them unnecessarily ;)
Source code can be downloaded from here: source code