Blog / Incidents
IIS Idle Timeout Causes Worker Process Shutdown
  • Dec 06, 2020
  • 70
  • 79

Internet Information Service (IIS) is a pain for developers and may cause more troubles for them on a shared host where they don't have full access. One of the usual problems that I encounter is the IIS Application Pool's Idle Timeout which I can't update the settings due to insufficient permissions. Let's see which problem that the Idle Timeout causes and how to deal with it.


Advertisement
 


1. The Problem of IIS Idle Timeout

If your application implements Session or Cookie Authentication which persists user's login data and is hosted on a Windows Server by IIS, you may notice the application forced you to logout every 20 minutes even when you set the expiration date to be much more later than that. This is because of the IIS Idle Timeout is set to 20 minutes by default which causes the worker process to shutdown after the set interval time. 

In my application, I used .Net Core Cookie Authentication and keep the data persistent for a year if user login and select Remember Me option.

AccountController.cs

[HttpPost]
public ActionResult Login(LoginViewModel model)
{
    try
    {
        bool valid = false;
 
        if (ModelState.IsValid)
            valid = _userManager.Login(model);
 
        if (valid)
        {
            var userClaims = new List<Claim>()
            {
                new Claim(ClaimTypes.Name, "Lucas")
            };
 
            var identity = new ClaimsIdentity(userClaims, CookieAuthenticationDefaults.AuthenticationScheme);
            HttpContext.SignInAsync(new ClaimsPrincipal(identity),
                new AuthenticationProperties
                {
                    IsPersistent = model.RememberMe,
                    ExpiresUtc = model.RememberMe ? DateTime.UtcNow.AddDays(365) : DateTime.UtcNow.AddSeconds(5)
                });
        }
        else
            ModelState.AddModelError("", "Incorrect Password!");
 
        return PartialView("_Login", model);
    }
    catch
    {
        ModelState.AddModelError("", "Something Wrong. Please Try Again!");
        return PartialView("_Login", model);
    }
}

StartUp.cs

public void ConfigureServices(IServiceCollection services)
{
    //Omitted Code...
    //...
    services.Configure<SecurityStampValidatorOptions>(options => {
        options.ValidationInterval = TimeSpan.FromDays(365);
    });
 
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(config =>
    {
        config.Cookie.Name = "__MyBlogCookie__";
        config.LoginPath = "/Home/Login";
        config.SlidingExpiration = true;
        config.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
        config.Cookie.Expiration = TimeSpan.FromSeconds(10);
        config.ExpireTimeSpan = TimeSpan.FromSeconds(10);
    });
 
    services.AddAuthorization();
 
   //...
}

However, the application keeps asking me to login again after every 20 minutes of being idle. We know it's the problem of IIS Idle Timeout and will see how to resolve it in 2 case scenarios: when you have and when you don't have permission to update IIS App Pool's settings.

2. Resolve IIS Idle Timeout Problem When You Have Permission to IIS Settings

It's an easy task if you are server administrator and able to update IIS App Pool Settings. You just need to go to Advanced Settings and either extend the Idle Timeout value to be more than 20 or set it to 0 so that there won't be any Idle Timeout period.


Advertisement
 


3. Resolve IIS Idle Timeout Problem When You Don't Have Permission to IIS Settings

It's me in this case because I purchased a shared GoDaddy Windows host server which doesn't allow me to update IIS Settings. Unfortunately, the App Pool Idle Timeout is set to be 20 by default so my application keeps asking me to login again after 20 minutes.

So, I need to come up with a solution to automatically make a request to the server every 1 minute. By doing so, the worker process will be kept busy and won't be shutdown by IIS. Let see how I did it in my .Net Core MVC project.

Step 1: Create a Thread Process

The idea is to keep a background running process which can be invoked every 1 minute since the application starts. A thread process can be used to approach this implementation. Create a static class called MyAppContext

MyAppContext.cs

public static class MyAppContext
{
    private static IMemoryCache _cache;
 
    public static void Configure(IMemoryCache cache)
    {
        _cache = cache;
    }
 
    public static void SetupRefreshJob()
    {
        Action remove = _cache.Get("Refresh") as Action;
        if (remove is Action)
        {
            _cache.Remove("Refresh");
            remove.EndInvoke(null);
        }
 
        //get the worker
        Action work = () =>
        {
            while (true)
            {
                Thread.Sleep(60000);
                WebClient refresh = new WebClient();
                try
                {
                    refresh.UploadString("https://lucasology.com", string.Empty);
                }
                catch (Exception ex)
                {
                    //Log Error here
                }
                finally
                {
                    refresh.Dispose();
                }
            }
        };
        Task.Run(() => work.Invoke());
 
        //add this job to cache
        _cache.Set("Refresh", work, new MemoryCacheEntryOptions()
        {
            AbsoluteExpiration = DateTimeOffset.MaxValue,
            SlidingExpiration = TimeSpan.FromDays(365),
            Priority = CacheItemPriority.Normal
        });
    }
}

In this class, we create a work delegate function which is invoked every 1 minute. This function just does 1 simple job which is uploading an empty string to the server. That's how to keep the worker process from being shutdown and from being idle. 

Step 2: Call SetupRefreshJob function in StartUp.cs

We need to fire this refresh job once the application starts. That is when we need to look at StartUp class where we can inject dependency for IMemoryCache as well as start the SetupRefreshJob.

StartUp.cs

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    //Omitted Code...
    //...
    MyAppContext.Configure(app.ApplicationServices.GetRequiredService<IMemoryCache>());
 
    MyAppContext.SetupRefreshJob();
 
    //...
}

Done! So now your application can keep the IIS App Pool busy every minute and avoid being shutdown. I hope that this post is helpful to you. Please let me know your thoughts in the comment section below. See you next time!


Search text in Stored Procedure in SQL SELECT DISTINCT o.name AS Object_Name, o.type_desc FROM sys.sql_modules m INNER JOIN sys.objects o ON m.object_id = o ...

Using cherry-pick to select specific commits for your Pull Request.1. Create a new branch based on the target of the Pull Requestgit branch cherry-branch origin/master2. Switch to a new branchgit chec ...

After deployment Angular and API on IIS, it's working fine unless I refresh the page. Once refreshed, the web encountered 404 error. In this article, I will explain how to resolve this.Since Angular i ...

There are some benefits of keeping both UI and API parts in the same place for small projects. In this article, I will explain how I did to deploy Angular Web and ASP .Net Core API in the same folder ...

I got CORS error after publishing my API and Angular app to IIS even though CORS is enabled and the origins of the Angular app is added. Below is how I resolved this issue.Just simple, make sure you s ...

In Object-Oriented Programming, S.O.L.I.D refers to the first five design principle for the purpose of making software designs more understandable, flexible, and maintainable. The principles was first ...

1. The Situation:Error Message:&nbsp;Pulse Secure Application failed to load Java. Please install correct JRE version.Description: This issue happens when I'm using a M1 Mac with a correct version of ...

Below is how to decrypt/convert a Hex string value into text using VB.Net:Decrypting Hex string value to string in VB.Net Function HexToString(ByVal hex As String) As String Dim text As New Sy ...

After a month of publishing on Google Play, Jungle Words has made it to the Top Android Games To Try Out In April 2021. Please check it out!&nbsp;GameKeys.netGameKeys is a website which introduces gam ...