Archive

Posts Tagged ‘IIS’

.NET C#: Recycle current Application Pool programmatically (for IIS 6+)

February 12, 2008 LeandroDG 7 comments

I’ve been working on how to recycle the current application pool for my ASP .NET application.

There are 3 steps for doing this:

  1. Verify if application is running on IIS that supports application pools (if not, there’s nothing to recycle).
  2. Get application pool name (obtained from the DirectoryServices entry corresponding to our virtual directory).
  3. Invoke Recycle method in the DirectoryServices entry corresponding to the application pool.

I divided the code into this 3 steps, the RecycleApplicationPool method can be used separately for recycling any application pool (by knowing only its name). The RecycleCurrentApplicationPool method returns a boolean value indicating if the application pool was recycled.

public static class ApplicationPoolRecycle
{
    /// <summary>Attempts to recycle current application pool</summary>
    /// <returns>Boolean indicating if application pool was successfully recycled</returns>
    public static bool RecycleCurrentApplicationPool()
    {
        try
        {
            // Application hosted on IIS that supports App Pools, like 6.0 and 7.0
            if (IsApplicationRunningOnAppPool())
            {
                // Get current application pool name
                string appPoolId = GetCurrentApplicationPoolId();
                // Recycle current application pool
                RecycleApplicationPool(appPoolId);
                return true;
            }
            else
                return false;
        }
        catch
        {
            return false;
        }
    }

    private static bool IsApplicationRunningOnAppPool()
    {
        // Application is not hosted on IIS
        if (!AppDomain.CurrentDomain.FriendlyName.StartsWith("/LM/"))
            return false;
        // Application hosted on IIS that doesn't support App Pools, like 5.1
        else if (!DirectoryEntry.Exists("IIS://Localhost/W3SVC/AppPools"))
            return false;
        else
            return true;
    }

    private static string GetCurrentApplicationPoolId()
    {
        string virtualDirPath = AppDomain.CurrentDomain.FriendlyName;
        virtualDirPath = virtualDirPath.Substring(4);
        int index = virtualDirPath.Length + 1;
        index = virtualDirPath.LastIndexOf("-", index - 1, index - 1);
        index = virtualDirPath.LastIndexOf("-", index - 1, index - 1);
        virtualDirPath = "IIS://localhost/" + virtualDirPath.Remove(index);
        DirectoryEntry virtualDirEntry = new DirectoryEntry(virtualDirPath);
        return virtualDirEntry.Properties["AppPoolId"].Value.ToString();
    }

    private static void RecycleApplicationPool(string appPoolId)
    {
        string appPoolPath = "IIS://localhost/W3SVC/AppPools/" + appPoolId;
        DirectoryEntry appPoolEntry = new DirectoryEntry(appPoolPath);
        appPoolEntry.Invoke("Recycle");
    }
}

VN:F [1.9.11_1134]
Rating: 5.0/5 (1 vote cast)

Cassini & SerializationException: Type is not resolved for member…

December 18, 2007 LeandroDG 7 comments

I’m working on an architecture project now, and I needed to create an HttpModule which would measure the request time for pages.

So I needed to save information (the time and some other data) in the Begin_Request event and then read it in the End_Request event. I could have used Request.Context, but part of the idea of the project is this information in the current thread because it can be used both in Winforms and in Webforms.
This information is saved in the current thread using a class that implements ILogicalThreadAffinative. When I saved my information in the current thread (using CallContext.SetData()), suddenly an exception (not debuggeable) came up, which said:

System.Runtime.Serialization.SerializationException: Type is not resolved for member '{0}'.
   at Microsoft.VisualStudio.WebHost.Server.GetProcessToken()
   at Microsoft.VisualStudio.WebHost.Host.GetProcessToken()
   at Microsoft.VisualStudio.WebHost.Request.GetUserToken()
   at Microsoft.VisualStudio.WebHost.Request.GetServerVariable(String name)
   at System.Web.Security.WindowsAuthenticationModule.OnEnter(Object source, EventArgs eventArgs)
   at System.Web.HttpApplication.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)

I was using Cassini server to test the application (the light-weight webserver that comes with Visual Studio .NET). I decided to test it with IIS and had absolutely no problem, worked like a charm. So I figured it was a problem with Cassini, not being able to find the assembly which contained my class at some point.

After some research I found a workaround in a post, I could make my class heritate from MarshalByRefObject and it would work perfectly. Even though this workaround makes it work perfectly in both Cassini and IIS (although I believe there is a small performance drop) , we shouldn’t have to worry about this, I always believed the idea of Cassini was to allow working with Web Applications without needing to create a Virtual directory in IIS, you shouldn’t even need to have IIS installed, and it should reproduce the exact same behavior in both servers.

Other workarounds I found included saving the assembly to the GAC, registering the bin directory in DEVPATH environment variable, but I think the one I describe is the easiest one to implement.

This bug has been reported by Paulo Morgado at Microsoft Connect, here is the link: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=274696.

VN:F [1.9.11_1134]
Rating: 5.0/5 (1 vote cast)
Categories: Development Tags: , , , ,