Keep your Dynamics CRM Extensions on Fire

Gayan Perera, 03 September 2010

If you’re creating web applications using asp.net or you’re a user that is using ISV extensions you might be aware of the spin up delay.

This delay has considerable impact on user experience when it comes to ISV extensions in Dynamics CRM. The delay is caused by the asp.net runtime serializing Microsoft.Crm.Sdk*.dlls. Sometimes this can take up to 60 seconds.

The good news is that it only happens the first time the application starts up. What we do with our extensions is to create a keep-alive.aspx page which makes couple of requests to the Dynamics CRM web service every 5 minutes during business hours using a scheduled task through the windows task scheduler.

Here’s the code for the console application.

if (ConfigurationManager.AppSettings["urls"] != null)
{
    // get all the urls we need to ping from the app.config file
    string[] sites = ConfigurationManager.AppSettings["urls"].Split(',');
    sites.ToList().ForEach(a =>
    {
        try
        {
            // app.config file dosn't like & symbols, so if you have a querystring with & replace it with |
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(a.Replace("|""&"));
            request.Credentials = CredentialCache.DefaultCredentials;
 
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream responseStream = response.GetResponseStream();
 
            responseStream.Dispose();
            response.Close();
 
            Console.WriteLine("pinged: {0}", a);
        }
        catch (Exception ex) // ignore errors
        {
            Console.WriteLine(ex.ToString());
        }
    });
}

And here is the code for the keep-alive.aspx page

public partial class keep_alive : System.Web.UI.Page
{
    protected override void OnInit(EventArgs e)
    {
        this.Load += new EventHandler(Page_Load);
        base.OnInit(e);
    }
 
    protected void Page_Load(object sender, EventArgs e)
    {
        var context = Helper.DataContextFromWeb;
        context.WhoAmI(); // awaken the serializer
 
        var contact = (from c in context.Contacts select c).Take(1).SingleOrDefault();
    }
}